【Android】Anroid5.0+新控件---酷炫標題欄的簡單學習


Android5.0+推出的新控件感覺特別酷,最近想模仿大神做個看圖App出來,所以先把這些新控件用熟悉了。
新控件的介紹、使用等等網上相應的文章已經特別多了,題主也沒那能力去寫篇詳解出來,本篇隨筆記錄的主要是題主學習這些新控件時遇見的一些困惑以及在搞了半天后的一絲理解,或許也有新手也會碰到跟我一樣的困惑,相互學習哈,如果有哪個地方理解錯了,還望告知。


效果

首先看下效果,本篇也就是只記錄以下兩張動圖中所涉及到的新控件

AppBarLayout+CollapsingToolbarLayout+Toolbar

以前手機里的App風格雖然各種各樣,但對於標題欄其實都差不多,很少能見到類似上圖中的效果。題主之前一直以為標題欄也就是一個簡單的導航欄,也就是放個標題,配幾個圖標而已。但其實還可以像上面一樣實現一些較酷炫的效果的。

首先介紹下這里用到的控件:AppBarLayout+CollapsingToolbarLayout+Toolbar

AppBarLayout + CollapsingToolbarLayout

AppBarLayout is a vertical LinearLayout which implements many of the features of material designs app bar concept, namely scrolling gestures.

 

CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar. It is designed to be used as a direct child of a AppBarLayout.

上面是官網的介紹,AppBarLayout其實就是一個繼承自LinearLayout,默認實現子控件垂直布局的基本容器,相區別於LinearLayout的是,它提供給它的子控件一個響應滑動事件的行為。

CollapsingToolbarLayout則只是一個對Toolbar進行包裝,實現了可以對標題欄進行折疊功能的一個基本容器,它是作為AppBarLayout的直接子布局來使用。

這么說好像也不怎么好理解,題主就按自己的理解講得通俗點,舉個例子:
上面那張動圖里,標題欄包括了一個Toolbar、一個背景圖(imageView)、一個FAB按鈕。這里的Toolbar、imageView都是AppbarLayout的子控件。
當滑動屏幕時,子控件都做出了相應的行為(滑出屏幕,固定頂端等),這些行為其實就是AppbarLayout提供給它子控件的功能。也就是說,如果我們想要讓我們的標題欄控件能夠響應滑動事件的話,就需要用AppBarLayout作為他們的父容器。

至於CollapsingToolbarLayout則是給子控件提供了折疊的功能,什么是折疊呢?往下看
不知道大家學習的時候會不會跟題主一樣,有個疑問:既然AppBarLayout已經為子控件提供了響應滑動的行為,那么為什么還需要一個CollapsingToolbarLayout?

我們先來看下,上面那動畫實現的布局代碼結構:

<AppBarLayout>  
    <CollapsingToolbarLayout app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">  
        <ImageView app:layout_collapseMode="parallax">  </ImageView>
        
        <Toolbar app:layout_collapseMode="pin">  </Toolbar>
    </CollapsingToolbarLayout>
</AppBarLayout>

CollapsingToolbarLayout作為AppBarLayout的子控件,設置了ScrollFlags的屬性值,因此它可以響應滑動事件,所以會出現上面動圖的效果。
那么,我們來嘗試下,如果去掉CollapsingToolbarLayout會怎么樣呢?

布局代碼結構:

<AppBarLayout>  
    <ImageView app:layout_scrollFlags="scroll">  </ImageView>
        
    <Toolbar app:layout_scrollFlags="scroll|exitUntilCollapsed">  </Toolbar>
</AppBarLayout>

效果:

圖片背景只是簡單的往上滑,沒有之前那種視差的效果了。而且Toolbar也跑到下面去了,那么,我們在把ImageView和Toolbar換個位置試下:

布局代碼結構:

<AppBarLayout>     
    <Toolbar app:layout_scrollFlags="scroll|exitUntilCollapsed">  </Toolbar>
    
    <ImageView app:layout_scrollFlags="scroll">  </ImageView>
</AppBarLayout>

效果:

Toolbar和ImageView不滑動了!!為什么,下面說。

很明顯的一點,ImageView和Toolbar變成了線性垂直布局的了。細心點的讀者會發現,我們上面剛提到過AppBarLayout是繼承自LinearLayout默認實現子控件垂直布局。

也就是說,AppBarLayout只是提供給它的子控件們,按照從上到下的優先級來響應子控件設置的響應行為。什么意思,如果AppBarLayout的第一個子控件沒有設置ScrollFlags屬性或者沒有設置scroll值,那么這個子控件就不會響應滑動事件,那么這個子控件下方的控件即使設置了各種響應行為,也不會有任何效果。

我們上面的代碼中,Toolbar是AppBarLayout的第一個子控件,雖然設置了scroll值,但也設置了exitUntilCollapsed值,這個的作用是,當向上滑動時,這個控件也會跟着滑出屏幕,直到它還留在屏幕內的高度達到最小高度(沒有設置好像默認就是wrap_content)時停止。

再回到我們問題來,Toolbar已經達到了它的最小高度了,所以它被固定在頂端不會動了,因此,即便在它下方的ImageView也設置了scroll屬性值,但由於是線性布局,它也就動不了了。所以也就有了CollapsingToolbarLayout。

所以,CollapsingToolbarLayout就是給這些子控件們安排具體的滑動細節,例如:ImageView要實現漸變的效果;Toolbar的標題要能夠有收縮/擴展的效果;最上面的子控件不動,下面的先滑動等等效果。這些就是由CollapsingToolbarLayout來提供的效果。

總結下,Toolbar、ImageView都是作為標題欄的元素,AppBarLayout給它們提供可以響應滑動的行為,而CollapsingToolbarLayout則是來安排誰不動,誰先動、怎么動。

如何使用

好了,這樣一來對於AppBarLayout和CollapsingToolbarLayout就有一個大概的理解了,那么下面就看看該怎么用。

AppBarLayout

Children should provide their desired scrolling behavior through setScrollFlags(int) and the associated layout xml attribute: app:layout_scrollFlags.

AppBarLayout提供了一個布局參數scrollFlags,通過在它的子控件中設置這個屬性的值,就可以實現相應的行為。使用方法就像上面官網說的,可以在xml布局文件中直接在子控件中通過設置app:layout_scrollFlags,也可以在java代碼中通過子控件實例對象調用setScrollFlags(int)來實現。

至於ScrollFlags的值一共有以下幾種:

scroll|enterAlways|enterAlwaysCollapsed|exitUntilCollapsed|snap

scroll: 想要子控件能有響應的行為,scroll是必須要設置的;也就是說,要想其他值能起作用,那么scroll值必須設置,中間用|隔開。這點很重要,網上很多文章只是介紹ScrollFlags屬性有這幾個取值,新手自己動手時往往不知道scroll是必須要的,經常就出現沒任何滑動的效果。然后就卡在這,比如題主(囧)。

enterAlways|enterAlwaysCollapsed:把這兩個放一起介紹是因為,后者要起作用必須要在前者的基礎上,也就是說兩個值都設置時后者才會起作用。至於作用其實就是當你一向下滑動屏幕時,控件就能馬上顯示出來,不必滑到頂端。

snap:當你停止滑到屏幕時,控件自動恢復原樣或者自動滑到底。

CollapsingToolbarLayout

跟AppBarLayout很像,CollapsingToolbarLayout提供了一個布局參數CollapseMode,一樣是兩種方法,xml布局文件中通過app:layout_collapseMode設置,或者在java代碼中調用setCollapseMode(int)

注意

ScrollFlags屬性只能設置在AppBarLayout的子控件上面,在孫子或曾孫子等等設置沒有效果。拿上面的例子說,CollapsingToolbarLayout是AppBarLayout的子控件,ImageView、Toolbar是AppBarLayout的孫子控件,如果你在ImageView、Toolbar控件上面設置app:layout_scrollFlags屬性值是不會起作用的,只有在CollapsingToolbarLayout設置才能起作用。

題主開始時想當然的以為在CollapsingToolbarLayout上面只設置scroll值,在ImageView、上設置snap,在Toolbar上面設置exitUntilCollapsed。這樣就可以單獨設置各自需要的效果。本來還自己這樣想是正確的,結果一直沒得到預期的效果,在這里瞎琢磨了半天(囧)。

AppBarLayout 是為其子控件提供響應屏幕滑動事件,既然要響應屏幕的滑動事件,自然要監聽除了AppBarLayout之外布局的滑動行為,所以在布局代碼里, app:layout_behavior="@string/appbar_scrolling_view_behavior" 這個屬性不要忘記設置了,這個屬性是 CoordinatorLayout 默認實現的一個滑動行為,所以這也是為什么要把 CoordinatorLayout 作為根布局的原因,只有這樣,設置 app:layout_behavior="@string/appbar_scrolling_view_behavior" 才會有效,一般這個屬性是設置在 AppBarLayout 下面的可滑動控件。當然,如果你不想這樣的話,可以去相關的 Behavior 的知識。

例如

    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.iwin.fragment01.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapse"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="bottom|center"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="centerCrop"
                android:src="@drawable/meinv3"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:minWidth="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay" />


        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|end" />

</android.support.design.widget.CoordinatorLayout>  

<!-- content_main.xml -->
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main"
    tools:context="com.iwin.fragment01.MainActivity">

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>
</android.support.v4.widget.NestedScrollView>


QQ圖片20180316094923.jpg
最近剛開通了公眾號,想激勵自己堅持寫作下去,初期主要分享原創的Android或Android-Tv方面的小知識,感興趣的可以點一波關注,謝謝支持~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM