RecyclerView的重构之路(五)

目标

本篇是RecyclerView的重构之路系列文章的第五篇, 讲解的是IDouban项目 电影详情界面展示以及相关控件的使用:CollapsingToolbarLayout, CoordinatorLayout, AppBarLayout, Toolbar

效果动图

动态效果图

注意,其中这些转场动画效果以及详情信息界面动画效果,都是Android MD(Material Design)自带的动画效果。只需要几个步骤就能实现。

实现步骤

本篇重点有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, 专门应对2中case:

  • 作为App或者chrome布局的顶层布局
  • 作为容器,用于和某个或某几个view的相互交互
    从字面意思理解,是一个协调者布局, 查看源码发现是个ViewGroup
public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {

使用的时候跟其他控件无区别, 作为xml布局的最外层标签使用。
注意,在本作的CoordinatorLayout中使用了 属性: fitsSystemWindows, 至于这个有什么作用,看图可知答案。

左边为true,右边为false对比图

上面的不同点是在 状态栏fitsSystemWindows=true表示该CoordinatorLayout中的内容会扩展到状态栏底部,并且状态栏变为透明。false表示不可以扩展到状态栏。

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本质是线性布局, 并实现许多MD特性, 即手势滚动。需要跟CoordinatorLayout搭配使用,否则没有效果。 在使用过程中,需要在其嵌套子类中添加 属性app:layout_scrollFlags.
Flags包括:
scroll: 所有想滚动出屏幕的view都需要设置这个flag- 没有设置这个flag的view将被固定在屏幕顶部。

enterAlways: 这个flag让任意向下的滚动都会导致该view变为可见,启用快速“返回模式”。

enterAlwaysCollapsed: 顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。

exitUntilCollapsed: 同样顾名思义,这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。

注意一点:所有使用scroll flag的view都必须定义在没有使用scroll flag的view的前面,这样才能确保所有的view从顶部退出,留下固定的元素。

经常会听得到 ActionBarAppBarToolbar, 这里给出官方的说明。

ActionBar

历史的产物, Android 3.0 Android 推了 ActionBar这个控件, 可以简单理解为顶部标题栏。可以显示标题,菜单以及图片 Logo之类的。有自己一套的写法,但是google在推出MD设计之后就慢慢抛弃了这种设计。

AppBar

换了马甲,叫AppBar, 来看下App Bar的MD结构图。注意App Bar仅仅是MD概念上的东西, SDK里是没有AppBar这个类的。

App Bar设计结构图

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概念上的东西,而不是实实在在存在的类(相关布局类是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来做,现在使用AppBarLayout + ToolBar来做,而且能实现更加丰富、酷炫的效果。

参考:

AppBarLayout
Android的材料设计兼容库
ToolBar详解(手把手教程)强烈推荐

实现目标(一) 上下滑动隐藏、显示图片

布局结构图

对应的实体效果如下:


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" 已经说明。

AppBarLayout

它是什么,前文做了说明。它如何使用,这里嵌套控件: CollapsingToolbarLayout, 一个可以伸缩的控件。这里需要注意,android:layout_height="256dp" 高度就是前文图片中的红色部分,可以按照自己需求调整。注意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:
 ... ... 
 **/

要实现可折叠的效果, 需要使用到CollapsingToolbarLayout, 其中嵌套2个ViewImageViewToolbar
注意其中的属性:

  • app:contentScrim="?attr/colorPrimary", 这个表示AppBarLayout滑动过程中, 标题栏的颜色, 如修改为app:contentScrim="#00ff00", 测试结果会变成绿颜色。

  • app:expandedTitleMarginStart="48dp", 表示,AppBarLayout展开后, 标题左边距的大小。

  • app:layout_scrollFlags="scroll|exitUntilCollapsed", 此属性必须要有。已经在上述 讲解AppBarLayout有过说明。

  • app:layout_collapseMode="parallax", 折叠模式是视差模式, 并且设置视差因子为0.7
    这个怎么理解呢?

视差模式效果
无视差模式效果

最大区别在于,有视差的,上滑过程中,电影海报中的“泰山归来”是慢慢被覆盖的效果。而没有视差的,上滑过程中, 电影海报是整体往上慢慢顶出去。

详细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是电影详情界面的下部分内容, 主要是TabLayout & ViewPager。 那其中关键的属性是:
app:layout_behavior="@string/appbar_scrolling_view_behavior" , 这是CoordinatorLayout 内嵌套中必须要有的属性, 这里使用默认的behavior。

CoordinatorLayout并不知道FloatingActionButton或者AppBarLayout的内部工作原理 - 它只是以Coordinator.Behavior的形式提供了额外的API,该API可以使子View更好的控制触摸事件与手势以及声明它们之间的依赖,并通过onDependentViewChanged()接收回调。

可以使用 CoordinatorLayout.DefaultBehavior(你的View.Behavior.class)注解或者在布局中使用app:layout_behavior="com.example.app.你的View$Behavior"属性来定义view的默认行为。framework让任意view和CoordinatorLayout结合在一起成为了可能。

实现目标(二) 点击电影某个Item后的动画效果

这个是什么呢? MD现在提供了Activity之间一种顺滑过度动画。仔细看动图。


动态效果图

当点击泰山归来这部电影, 在跳转之前,电影图片会扩展到整个界面上部分,当扩展完成的时候,就顺畅转到电影详情界面。这个效果该如何实现呢?
上文,在讲解到 CollapsingToolbarLayout的时候,有意忽略了 android:transitionName="cover"
这个就是我们的女主角, 属性android:transitionName 表示我们使用过渡动画的名称,cover随意取。 这里使用的是MD中的 共享元素的过渡。

在跳转代码中需要添加如下代码:

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那样的转场动画,启动方式,需要按照上述代码编写。其中, ActivityCompat, ActivityOptionsCompat是为了向下兼容, 也可以考虑使用ActivityOptions; makeSceneTransitionAnimation方法中的参数:

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

sharedElement表示需要共享动画的view, 这里是电影海报Imageview, sharedElementName对应在电影详情界面的布局文件中属性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学习之Activity过渡动画

github代码

欢迎大家fork IDouban源码,觉得好,顺手点下星星。嗯,让我有动力完成这系列的文章。

RecyclerView的重构之路(六)

参考文档

AppBarLayout
Android的材料设计兼容库
ToolBar详解(手把手教程)强烈推荐
Android 5.0学习之Activity过渡动画
Demos the new Android Design library
Android 官方开发者blog

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容