CoordinatorLayout系列(五)例子

系列文章:
CoordinatorLayout系列(一):Behavior
CoordinatorLayout系列(二)AppBarLayout
CoordinatorLayout系列(三)AppBarLayout之layout_scrollFlags
CoordinatorLayout系列(四)CollapsingToolbarLayout
CoordinatorLayout系列(五)例子

這一篇講兩個例子,實現如下效果;
在這裏插入圖片描述在這裏插入圖片描述
demo地址:https://github.com/whoami-I/CoordinatorLayoutExample
第一個是ToolBar能跟隨手指的上下滑動而產生漸變的效果,而不是默認的動畫,默認效果是達到某個閾值之後,就執行一個動畫把ToolBar變成綠色。
實現起來也很簡單,就是運用AppBarLayout的OnOffsetChangedListener監聽,上代碼:

<com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:collapsedTitleTextAppearance="@style/ToolbarTitleStyle"
            app:contentScrim="@null"
            app:expandedTitleTextAppearance="@style/BigToolbarTitleStyle"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:scrimAnimationDuration="50"
            app:scrimVisibleHeightTrigger="0dp"
            app:statusBarScrim="@null"
            app:title="櫻花">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:scaleType="centerCrop"
                android:src="@drawable/pic2"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/colorPrimary"
                app:contentInsetStart="0dp"
                app:contentInsetStartWithNavigation="0dp"
                app:layout_collapseMode="pin"
                app:navigationIcon="@drawable/ic_arrow_back"
                app:titleTextAppearance="@style/ToolbarTitleStyle"></androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>


    </com.google.android.material.appbar.AppBarLayout>

佈局一般,就是把ToolBar放進CollapsingToolBarLayout

AppBarLayout.OnOffsetChangedListener listener = new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                // get total height and calc ratio
                int totalHeight = mCollapsingToolbarLayout.getHeight() - mToolBar.getHeight() - ((FrameLayout.LayoutParams) mToolBar.getLayoutParams()).topMargin;
                float ratio = getRatio(-verticalOffset, totalHeight);
                changeToolBar(ratio); //改變toolbar透明度
                changeStatusBar(ratio); //改變狀態欄顏色
            }
        };
        // 初始化時,將toolbar設置成透明
        changeToolBar(0);
	private void changeStatusBar(float ratio) {
        int transparent = (int) (255 * ratio);
        int color = 0x008577 | (transparent << 24);
        getWindow().setStatusBarColor(color);
    }
 	private void changeToolBar(float ratio) {
        mToolBar.setAlpha(ratio);
    }
    private float getRatio(int cur, int total) {
        float ratio = 0.0f;
        //這裏之所以這樣轉換,是設置toolbar開始變透明時的閾值,這個閾值爲滑動到toolbar下面100像素處,纔開始變化
        int offset = 100;
        if (cur >= total - offset) {
            cur = cur - (total - offset);
            total = offset;
            ratio = cur * 1.0f / total;
            ratio = ratio > 1.0f ? 1.0f : ratio;
        }
        return ratio;
    }

添加AppBarLayout滑動監聽,然後根據滑動的距離來設置透明度信息,要注意,因爲這是我們自定義的效果,因此要先disable系統默認的效果,可以把CollapsingToolBarLayout的scrim都設置成null

app:contentScrim="@null"
app:statusBarScrim="@null"

或者是閾值改爲0

app:scrimVisibleHeightTrigger="0dp"

第二個例子也是可以用上面同樣的方式實現的,但我們換一種思路,使用自定義Behavior的方法,看看能不能行得通。

首先看佈局,因爲要使用Behavior,那麼CircleImageView肯定是作爲CoordinatorLayout的直接子view存在的

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentScrim="@color/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:scrimAnimationDuration="50"
            app:scrimVisibleHeightTrigger="0dp">
            ......

        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/img_head"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/head"
        android:layout_gravity="center_horizontal"
        app:layout_behavior=".collapsingtoolbarlayoutexample2.HeadScaleBehavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

上面的recyclerview和Toolbar都被我省略掉了
直接上Behavior吧:

public class HeadScaleBehavior extends CoordinatorLayout.Behavior<ImageView> {

    private static String TAG = "HeadScaleBehavior";

    public HeadScaleBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull ImageView child, @NonNull View dependency) {
        //set position
        int centerY = (int) ((dependency.getBottom() - dependency.getTop() + dependency.getY()) / 2);
        child.setY(centerY - child.getHeight() / 2);

        //set scale and alpha
        float ratio = (-dependency.getY()) / (((AppBarLayout)dependency).getTotalScrollRange());
        child.setScaleX(1.0f - ratio);
        child.setScaleY(1.0f - ratio);
        return true;
    }

    @Override
    public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull ImageView child, @NonNull View dependency) {

        return dependency instanceof AppBarLayout;
    }
}

首先確定位置,因爲我們的效果是CircleImageView跟隨AppBarLayout上下移動的,但是現在的CircleImageView是位於CoordinatorLayout裏面的,因此需要知道AppBarLayout的移動距離和位置,移動距離就使用getY()方法獲取,然後計算比例的時候,需要知道AppBarLayout總共能夠滑動多少距離,使用AppBarLayout.getTotalScrollRange()方法即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章