RecyclerView的重構(gòu)之路(五)

目標(biāo)

本篇是RecyclerView的重構(gòu)之路系列文章的第五篇, 講解的是IDouban項目 電影詳情界面展示以及相關(guān)控件的使用:CollapsingToolbarLayout, CoordinatorLayout, AppBarLayout, Toolbar

效果動圖

動態(tài)效果圖

注意,其中這些轉(zhuǎn)場動畫效果以及詳情信息界面動畫效果,都是Android MD(Material Design)自帶的動畫效果。只需要幾個步驟就能實現(xiàn)。

實現(xiàn)步驟

本篇重點有2個, 如gif圖展示
1 上下滑動隱藏&顯示圖片
2 點擊 泰山歸來 Item后的動畫效果
在講解具體的步驟之前,先來簡單看下上述幾個控件說明。

控件說明

CoordinatorLayout

/**
 * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}.
 *
 * <p>CoordinatorLayout is intended for two primary use cases:</p>
 * <ol>
 *     <li>As a top-level application decor or chrome layout</li>
 *     <li>As a container for a specific interaction with one or more child views</li>
 * </ol>
 **/

CoordinatorLayout是一個super-powered FrameLayout, 專門應(yīng)對2中case:

  • 作為App或者chrome布局的頂層布局
  • 作為容器,用于和某個或某幾個view的相互交互
    從字面意思理解,是一個協(xié)調(diào)者布局, 查看源碼發(fā)現(xiàn)是個ViewGroup
public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {

使用的時候跟其他控件無區(qū)別, 作為xml布局的最外層標(biāo)簽使用。
注意,在本作的CoordinatorLayout中使用了 屬性: fitsSystemWindows, 至于這個有什么作用,看圖可知答案。

左邊為true,右邊為false對比圖

上面的不同點是在 狀態(tài)欄, fitsSystemWindows=true表示該CoordinatorLayout中的內(nèi)容會擴展到狀態(tài)欄底部,并且狀態(tài)欄變?yōu)橥该?。false表示不可以擴展到狀態(tài)欄。

AppBarLayout

AppBarLayout繼承圖

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

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

This view depends heavily on being used as a direct child within a CoordinatorLayout. If you use AppBarLayout within a different ViewGroup, most of it's functionality will not work.

也就是說AppBarLayout本質(zhì)是線性布局, 并實現(xiàn)許多MD特性, 即手勢滾動。需要跟CoordinatorLayout搭配使用,否則沒有效果。 在使用過程中,需要在其嵌套子類中添加 屬性app:layout_scrollFlags.
Flags包括:
scroll: 所有想滾動出屏幕的view都需要設(shè)置這個flag- 沒有設(shè)置這個flag的view將被固定在屏幕頂部。

enterAlways: 這個flag讓任意向下的滾動都會導(dǎo)致該view變?yōu)榭梢姡瑔⒂每焖佟胺祷啬J健薄?/p>

enterAlwaysCollapsed: 顧名思義,這個flag定義的是何時進入(已經(jīng)消失之后何時再次顯示)。假設(shè)你定義了一個最小高度(minHeight)同時enterAlways也定義了,那么view將在到達這個最小高度的時候開始顯示,并且從這個時候開始慢慢展開,當(dāng)滾動到頂部的時候展開完。

exitUntilCollapsed: 同樣顧名思義,這個flag時定義何時退出,當(dāng)你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。

注意一點:所有使用scroll flag的view都必須定義在沒有使用scroll flag的view的前面,這樣才能確保所有的view從頂部退出,留下固定的元素。

經(jīng)常會聽得到 ActionBar,AppBar, Toolbar, 這里給出官方的說明。

ActionBar

歷史的產(chǎn)物, Android 3.0 Android 推了 ActionBar這個控件, 可以簡單理解為頂部標(biāo)題欄??梢燥@示標(biāo)題,菜單以及圖片 Logo之類的。有自己一套的寫法,但是google在推出MD設(shè)計之后就慢慢拋棄了這種設(shè)計。

AppBar

換了馬甲,叫AppBar, 來看下App Bar的MD結(jié)構(gòu)圖。注意App Bar僅僅是MD概念上的東西, SDK里是沒有AppBar這個類的。

App Bar設(shè)計結(jié)構(gòu)圖

The app bar, formerly known as the action bar in Android, is a special kind of toolbar that’s used for branding, navigation, search, and actions.
The nav icon at the left side of the app bar can be:

  1. A control to open a navigation drawer.
  1. An up arrow for navigating upward through your app’s hierarchy.
  2. Omitted entirely if no navigation is required from this screen.

The title in the app bar reflects the current page. It can be an app title, page title, or a page filter.

Icons on the right side of the app bar are app-related actions. The menu icon opens the overflow menu, which contains secondary actions and menu items like help, settings, and feedback.

Toolbar

可能大家會混淆 AppBar & Toolbar, 如上所說,AppBar 是MD概念上的東西,而不是實實在在存在的類(相關(guān)布局類是AppBarLayout.java), Toolbar才是實體類上替代ActionBar的類。

A standard toolbar for use within application content.
A Toolbar is a generalization of {@link ActionBar action bars} for use
within application layouts. While an action bar is traditionally part of an
{@link android.app.Activity Activity's} opaque window decor controlled by the framework,
a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy.
An application may choose to designate a Toolbar as the action bar for an Activity
using the {@link android.support.v7.app.AppCompatActivity#setSupportActionBar(Toolbar)
setSupportActionBar()} method.

簡單一點, 以前是用ActionBar來做,現(xiàn)在使用AppBarLayout + ToolBar來做,而且能實現(xiàn)更加豐富、酷炫的效果。

參考:

AppBarLayout
Android的材料設(shè)計兼容庫
ToolBar詳解(手把手教程)強烈推薦

實現(xiàn)目標(biāo)(一) 上下滑動隱藏、顯示圖片

布局結(jié)構(gòu)圖

對應(yīng)的實體效果如下:


xiangqin-01.png

詳細xml 01

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

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/movie_collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/movie_image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:transitionName="cover"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/movie_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    
    省略下部線性布局
</android.support.design.widget.CoordinatorLayout>  

上述布局,挨個看:
CoordinatorLayout 以及 屬性 android:fitsSystemWindows="true" 已經(jīng)說明。

AppBarLayout

它是什么,前文做了說明。它如何使用,這里嵌套控件: CollapsingToolbarLayout, 一個可以伸縮的控件。這里需要注意,android:layout_height="256dp" 高度就是前文圖片中的紅色部分,可以按照自己需求調(diào)整。注意theme的選擇。

CollapsingToolbarLayout

/**
 * CollapsingToolbarLayout is a wrapper for {@link Toolbar} which implements a collapsing app bar.
 * It is designed to be used as a direct child of a {@link AppBarLayout}.
 * CollapsingToolbarLayout contains the following features:
 ... ... 
 **/

要實現(xiàn)可折疊的效果, 需要使用到CollapsingToolbarLayout, 其中嵌套2個View, ImageView, Toolbar。
注意其中的屬性:

  • app:contentScrim="?attr/colorPrimary", 這個表示AppBarLayout滑動過程中, 標(biāo)題欄的顏色, 如修改為app:contentScrim="#00ff00", 測試結(jié)果會變成綠顏色。

  • app:expandedTitleMarginStart="48dp", 表示,AppBarLayout展開后, 標(biāo)題左邊距的大小。

  • app:layout_scrollFlags="scroll|exitUntilCollapsed", 此屬性必須要有。已經(jīng)在上述 講解AppBarLayout有過說明。

  • app:layout_collapseMode="parallax", 折疊模式是視差模式, 并且設(shè)置視差因子為0.7
    這個怎么理解呢?

視差模式效果
無視差模式效果

最大區(qū)別在于,有視差的,上滑過程中,電影海報中的“泰山歸來”是慢慢被覆蓋的效果。而沒有視差的,上滑過程中, 電影海報是整體往上慢慢頂出去。

詳細xml 02

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.design.widget.TabLayout
            android:id="@+id/movie_sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabGravity="fill"
            app:tabMode="fixed" />

        <android.support.v4.view.ViewPager
            android:id="@+id/movie_viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

以上xml是電影詳情界面的下部分內(nèi)容, 主要是TabLayout & ViewPager。 那其中關(guān)鍵的屬性是:
app:layout_behavior="@string/appbar_scrolling_view_behavior" , 這是CoordinatorLayout 內(nèi)嵌套中必須要有的屬性, 這里使用默認的behavior。

CoordinatorLayout并不知道FloatingActionButton或者AppBarLayout的內(nèi)部工作原理 - 它只是以Coordinator.Behavior的形式提供了額外的API,該API可以使子View更好的控制觸摸事件與手勢以及聲明它們之間的依賴,并通過onDependentViewChanged()接收回調(diào)。

可以使用 CoordinatorLayout.DefaultBehavior(你的View.Behavior.class)注解或者在布局中使用app:layout_behavior="com.example.app.你的View$Behavior"屬性來定義view的默認行為。framework讓任意view和CoordinatorLayout結(jié)合在一起成為了可能。

實現(xiàn)目標(biāo)(二) 點擊電影某個Item后的動畫效果

這個是什么呢? MD現(xiàn)在提供了Activity之間一種順滑過度動畫。仔細看動圖。


動態(tài)效果圖

當(dāng)點擊泰山歸來這部電影, 在跳轉(zhuǎn)之前,電影圖片會擴展到整個界面上部分,當(dāng)擴展完成的時候,就順暢轉(zhuǎn)到電影詳情界面。這個效果該如何實現(xiàn)呢?
上文,在講解到 CollapsingToolbarLayout的時候,有意忽略了 android:transitionName="cover"
這個就是我們的女主角, 屬性android:transitionName 表示我們使用過渡動畫的名稱,cover隨意取。 這里使用的是MD中的 共享元素的過渡。

在跳轉(zhuǎn)代碼中需要添加如下代碼:

Intent intent = new Intent(context, MovieDetailActivity.class);

Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, mMovieImage, "cover").toBundle();
ActivityCompat.startActivity(activity, intent, bundle);

都知道啟動某個Activity方法很簡單, startActivity(Intent intent) , 但是要有MD那樣的轉(zhuǎn)場動畫,啟動方式,需要按照上述代碼編寫。其中, ActivityCompat, ActivityOptionsCompat是為了向下兼容, 也可以考慮使用ActivityOptions; makeSceneTransitionAnimation方法中的參數(shù):

public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,        
View sharedElement, 
String sharedElementName) 
{... ...}

sharedElement表示需要共享動畫的view, 這里是電影海報Imageview, sharedElementName對應(yīng)在電影詳情界面的布局文件中屬性value。

    <ImageView
                android:id="@+id/movie_image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:transitionName="cover" />

詳細的可以參考這篇blog:Android 5.0學(xué)習(xí)之Activity過渡動畫

github代碼

歡迎大家fork IDouban源碼,覺得好,順手點下星星。嗯,讓我有動力完成這系列的文章。

RecyclerView的重構(gòu)之路(六)

參考文檔

AppBarLayout
Android的材料設(shè)計兼容庫
ToolBar詳解(手把手教程)強烈推薦
Android 5.0學(xué)習(xí)之Activity過渡動畫
Demos the new Android Design library
Android 官方開發(fā)者blog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容