CoordinatorLayout系列(四)CollapsingToolbarLayout

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

終於到CollapsingToolbarLayout這個強大而裝逼的佈局了,這個佈局的實現和原理都是非常的簡單,比如下面的效果:
在這裏插入圖片描述
是不是很酷?當然這還是比較簡單的,這僅僅是使用到了系統自帶的一些功能,通過自定義可以實現更復雜的效果。

demo地址:https://github.com/whoami-I/CoordinatorLayoutExample

先講實現的方式,再講實現的過程。

實現原理

通過查看CollapsingToolBarLayout的源代碼,發現其實現方式非常簡單,源代碼加在一起也就1000多行,其實簡單的原因有兩方面,一是CollapsingToolBarLayout其實是一個FrameLayout;二是因爲這種效果的核心實現其實是CoordinatorLayout和AppBarLayout,CollapsingToolBarLayout其實是基於兩者之上稍微拓展了一下而已。
在之前的文章中講過,當滑動下面的NestedScrollView時,由於NestedScroll機制最終會導致AppBarLayout的child view滑動,所以只需要建立起AppBarLayout和CollapsingToolBarLayout的關聯即可。
AppBarLayout有一個內部類OnOffsetChangedListener這個就是用以監聽AppBarLayout滑動的距離:

public interface OnOffsetChangedListener extends BaseOnOffsetChangedListener<AppBarLayout> {
    void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset);
  }

verticalOffset代表滑動距離,向上滑動這個值小於0,向上滑動大於0.
CollapsingToolBarLayout就是實現這個監聽,根據滑動的距離,實現不同的動作,比如:標題的移動和放大縮小、ToolBar的透明度等等。

實現過程

上佈局

<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:title="風景"
            app:scrimAnimationDuration="50"
            app:collapsedTitleTextAppearance="@style/ToolbarTitleStyle"
            app:expandedTitleTextAppearance="@style/BigToolbarTitleStyle"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

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

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                <!--把toolbar背景設置成透明-->
                android:background="#00000000"
                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>

先理解CollapsingToolBarLayout幾個屬性的意義:

app:contentScrim :表示收縮時,CollapsingToolBarLayout的遮擋顏色
app:statusBarScrim :表示收縮時,狀態欄的遮擋顏色
app:collapsedTitleTextAppearance :收縮最終狀態時,title的樣式
app:expandedTitleTextAppearance :展開最終狀態時,title的樣式
app:scrimAnimationDuration : 遮擋顏色以動畫的形式出現,該值表示動畫時長
app:layout_collapseMode : pin表示收縮時,此view不參與滑動,默認爲parallax表示會參與滑動

在這裏要注意title要設置到CollapsingToolBarLayout上,而不是ToolBar,否則會導致title樣式不對,具體原因是CollapsingToolBarLayout自己本身就會根據移動的距離,動態畫出一個title,因此ToolBar就沒有必要設置title了,設置完這些就有效果了:
在這裏插入圖片描述
狀態欄顏色不對,這是因爲沒有實現沉浸,而且需要把狀態欄顏色改成透明,在setContentView之前:

View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);

沉浸之後,ToolBar也會到狀態欄後面,因此需要將ToolBar下移一個狀態欄的高度:

FrameLayout.LayoutParams lps = (FrameLayout.LayoutParams) mToolBar.getLayoutParams();
lps.topMargin = DisplayUtils.getStatusBarHeight(this);

設置完之後的效果:
在這裏插入圖片描述

差不多了,就是遮擋顏色scrim出現的時機不是很好,我們需要它在接近於頂部的時候纔出現,因此還需要設置CollapsingToolBarLayout的ScrimVisibleHeightTrigger屬性:

ViewTreeObserver vto = mAppBarLayout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mAppBarLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                mCollapsingToolbarLayout.setScrimVisibleHeightTrigger(mToolBar.getHeight()+1+DisplayUtils.getStatusBarHeight(MainActivity.this));
            }
        });

這樣就達到開頭的效果了。至於上面爲什麼+1,看源碼就ok了。
接下來的文章就準備實現下拉的時候,如何使得圖片能夠放大,而且再寫幾個例子實現自定義的效果。

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