【转】Material Design 折叠效果 Toolbar CollapsingToolbarLayout AppBarLayout

我非常喜欢Material Design里折叠工具栏的效果,bilibili Android客户端视频详情页就是采用的这种设计。这篇文章的第二部分我们就通过简单的模仿bilibili视频详情页的实现来了解下CollapsingToolbarLayout的使用。文章的第三部分介绍了CollapsingToolbarLayout与TabLayout的组合使用。

有基础的朋友可以直接跳过第一部分。

一、相关基础属性介绍

Android studio中有一个Activity模板叫ScrollingActivity,它实现的就是简单的可折叠工具栏,我们将此模板添加到项目中。

ScrollingActivity的布局代码如下

<?xml version="1.0" encoding="utf-8"?>
<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">

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

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

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

    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        >
    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:text="@string/large_text" />
</android.support.v4.widget.NestedScrollView>

<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/app_bar"
    app:layout_anchorGravity="bottom|end" />

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

AppBarLayout是一种支持响应滚动手势的app bar布局(比如工具栏滚出或滚入屏幕),CollapsingToolbarLayout则是专门用来实现子布局内不同元素响应滚动细节的布局。

与AppBarLayout组合的滚动布局(Recyclerview、NestedScrollView等)需要设置app:layout_behavior=”@string/appbar_scrolling_view_behavior”(上面代码中NestedScrollView控件所设置的)。没有设置的话,AppBarLayout将不会响应滚动布局的滚动事件。

CollapsingToolbarLayout和ScrollView一起使用会有滑动bug,注意要使用NestedScrollView来替代ScrollView。

AppBarLayout的子布局有5种滚动标识(就是上面代码CollapsingToolbarLayout中配置的app:layout_scrollFlags属性):

  1. scroll:将此布局和滚动时间关联。这个标识要设置在其他标识之前,没有这个标识则布局不会滚动且其他标识设置无效。
  2. enterAlways:任何向下滚动操作都会使此布局可见。这个标识通常被称为“快速返回”模式。
  3. enterAlwaysCollapsed:假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
  4. exitUntilCollapsed:当你定义了一个minHeight,此布局将在滚动到达这个最小高度的时候折叠。
  5. snap:当一个滚动事件结束,如果视图是部分可见的,那么它将被滚动到收缩或展开。例如,如果视图只有底部25%显示,它将折叠。相反,如果它的底部75%可见,那么它将完全展开。

CollapsingToolbarLayout可以通过app:contentScrim设置折叠时工具栏布局的颜色,通过app:statusBarScrim设置折叠时状态栏的颜色。默认contentScrim是colorPrimary的色值,statusBarScrim是colorPrimaryDark的色值。这个后面会用到。

CollapsingToolbarLayout的子布局有3种折叠模式(Toolbar中设置的app:layout_collapseMode)

  1. off:这个是默认属性,布局将正常显示,没有折叠的行为。
  2. pin:CollapsingToolbarLayout折叠后,此布局将固定在顶部。
  3. parallax:CollapsingToolbarLayout折叠时,此布局也会有视差折叠效果。

当CollapsingToolbarLayout的子布局设置了parallax模式时,我们还可以通过app:layout_collapseParallaxMultiplier设置视差滚动因子,值为:0~1。

FloatingActionButton这个控件通过app:layout_anchor这个设置锚定在了AppBarLayout下方。FloatingActionButton源码中有一个Behavior方法,当AppBarLayout收缩时,FloatingActionButton就会跟着做出相应变化。关于CoordinatorLayout和Behavior,我下一篇文章会和大家一起学习。

这一堆属性看着有点烦,大家可以新建一个ScrollingActivity模板去实验一下玩玩。

二、模仿bilibili客户端视频详情页

我们先对原界面分析一下。

界面初始,CollapsingToolbarLayout是展开状态,显示的是视频封面。我们向上滚动界面,CollapsingToolbarLayout收缩。当AppBarLayout完全折叠的时候视频av号隐藏,显示出来一个小电视图标和“立即播放”,点击则使AppBarLayout完全展开,CollapsingToolbarLayout子布局由ImageView切换为视频弹幕播放器。

额…弹幕播放器…

B站很早就开源了一个弹幕引擎,还起了个狂拽酷炫吊炸天的名字叫“烈焰弹幕使 ”(一看就是二次元程序猿们的作品→_→),源码在github上,项目名叫DanmakuFlameMaster

来我们先看修改完成的布局。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

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

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:contentScrim="?attr/colorPrimary"
        app:statusBarScrim="@android:color/transparent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <!--封面图片-->
        <ImageView
            android:id="@+id/imageview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:src="@drawable/diqiu"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.7"
            android:fitsSystemWindows="true"/>

        <!--视频及弹幕控件-->
        <FrameLayout
            android:id="@+id/video_danmu"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.7"
            android:fitsSystemWindows="true"
            android:visibility="gone">
            <VideoView
                android:id="@+id/videoview"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <!--哔哩哔哩开源的弹幕控件-->
            <master.flame.danmaku.ui.widget.DanmakuView
                android:id="@+id/danmaku"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </FrameLayout>

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

            <!--自定义带图片的立即播放按钮-->
            <android.support.v7.widget.ButtonBarLayout
                android:id="@+id/playButton"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:visibility="gone">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/ic_play_circle_filled_white_48dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#ffffff"
                    android:text="立即播放"
                    android:layout_gravity="center_vertical"
                   />
            </android.support.v7.widget.ButtonBarLayout>

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

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

<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="@mipmap/ic_play_circle_filled_white_48dp"
    app:layout_anchor="@id/app_bar"
    app:layout_anchorGravity="bottom|end" />

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

我把colorPrimary的色值修改成了B站的“少女粉”,播放的图标是从网上找的。

<color name="colorPrimary">#FA7199</color>

因为我们要实现沉浸式状态栏,所以就需要先把整个activity设置成状态栏透明模式。然后在布局文件中,把CollapsingToolbarLayout里要实现沉浸式的控件设置上android:fitsSystemWindows=”true”,如果没有设置,则子布局会位于状态栏下方,未延伸至状态栏。

布局并不算复杂,接下来先实现无弹幕播放时的功能,。

我们需要监听CollapsingToolbarLayout的折叠、展开状态。唉我去,官方并没有提供现成的方法(⊙_⊙?)。

查看源码,可以看到CollapsingToolbarLayout是通过实现AppBarLayout的OnOffsetChangedListener接口,根据AppBarLayout的偏移来实现子布局和title的视差移动以及ContentScrim和StatusBarScrim的显示。那么我们也可以通过调用AppBarLayout的addOnOffsetChangedListener方法监听AppBarLayout的位移,判断CollapsingToolbarLayout的状态。

先写一个枚举定义出CollapsingToolbarLayout展开、折叠、中间,这三种状态。

 private CollapsingToolbarLayoutState state;

 private enum CollapsingToolbarLayoutState {
    EXPANDED,
    COLLAPSED,
    INTERNEDIATE
}

接下来对AppBarLayout进行监听,判断CollapsingToolbarLayout的状态并实现相应的逻辑。

为了让大家对状态看着更直观,我在修改状态值的时候把title一起进行了修改。

使用CollapsingToolbarLayout的时候要注意,在完成CollapsingToolbarLayout设置之后再调用Toolbar的setTitle()等方法将没有效果,我们需要改为调用CollapsingToolbarLayout的setTitle()等方法来对工具栏进行修改。(具体原因各位亲去看下CollapsingToolbarLayout源码就知道了 ( ˙-˙ ) )

AppBarLayout  app_bar=(AppBarLayout)findViewById(R.id.app_bar);
app_bar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

        if (verticalOffset == 0) {
            if (state != CollapsingToolbarLayoutState.EXPANDED) {
                state = CollapsingToolbarLayoutState.EXPANDED;//修改状态标记为展开
                collapsingToolbarLayout.setTitle("EXPANDED");//设置title为EXPANDED
            }
        } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
            if (state != CollapsingToolbarLayoutState.COLLAPSED) {
                collapsingToolbarLayout.setTitle("");//设置title不显示
                playButton.setVisibility(View.VISIBLE);//隐藏播放按钮
                state = CollapsingToolbarLayoutState.COLLAPSED;//修改状态标记为折叠
            }
        } else {
            if (state != CollapsingToolbarLayoutState.INTERNEDIATE) {
                if(state == CollapsingToolbarLayoutState.COLLAPSED){
                    playButton.setVisibility(View.GONE);//由折叠变为中间状态时隐藏播放按钮
                }
                collapsingToolbarLayout.setTitle("INTERNEDIATE");//设置title为INTERNEDIATE
                state = CollapsingToolbarLayoutState.INTERNEDIATE;//修改状态标记为中间
            }
        }
    }
});

然后对播放按钮设置监听,点击则调用AppBarLayout的setExpanded(true)方法使工具栏展开。

哔哩哔哩客户端的title是固定不动的,可以调用CollapsingToolbarLayout的setTitleEnabled(false)方法实现。

视频播放时,调用 NestedScrollView的setNestedScrollingEnabled(false)方法可以使AppBarLayout不响应滚动事件。

细心的朋友可能发现了哔哩哔哩客户端为了避免视频封面图片颜色过浅影响状态栏信息的显示,加了一个渐变的不透明层。

实现渐变遮罩层很简单。先在res/drawable文件夹下新建了一个名为gradient的xml文件,其中代码如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <gradient
        android:startColor="#33000000"
        android:endColor="#00000000"
        android:angle="270" />

</shape>

shape节点中,可以通过android:shape来设置形状,默认是矩形。gradient节点中angle的值270是从上到下,0是从左到右,90是从下到上。起始颜色#33000000是20%不透明度的黑色,#00000000表示全透明。

然后在CollapsingToolbarLayout里的ImageView代码下面加上一个自定义view,背景设置为上面的渐变效果。

<View
   android:layout_width="match_parent"
   android:layout_height="40dp"
   android:background="@drawable/gradient"
   android:fitsSystemWindows="true"
/>

一般状态栏的高度大概在20dp左右,我为了让渐变效果比较自然,并且不过多影响图(mei)片(zi),把高度设置成了40dp。(状态栏能看清了,妹子脸也没黑,挺好 (?? . ??) )

我省略了弹幕播放的相关实现,接下来只要在播放按钮监听中写出封面图片的隐藏、视频和弹幕弹幕控件的显示初始化及播放逻辑,在AppBarLayout的三种状态监听中根据是否视频在播放写出其他相应逻辑就好了,感兴趣的朋友可以下载哔哩哔哩的“烈焰弹幕使”源码DanmakuFlameMaster玩玩。

B站点击追番或投硬币后会出现一个类似Snackbar的提示控件,可以通过我上一篇文章没时间解释了,快使用Snackbar!——Android Snackbar花式使用指南来实现,欢迎感兴趣的朋友去看看。

真的不是我懒得上代码了,真的…(基友:赶紧的,开黑了。 我:等等我,马上来!\(≧▽≦)/)

三.CollapsingToolbarLayout与TabLayout

CollapsingToolbarLayout与TabLayout组合使用的效果也不错。

来看下CollapsingToolbarLayout里的代码

<android.support.design.widget.CollapsingToolbarLayout
    android:id="@+id/collapsingtoolbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:titleEnabled="false"
    app:contentScrim="@color/colorPrimary"
    app:statusBarScrim="@android:color/transparent"
    app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        app:layout_collapseMode="parallax"
        app:layout_collapseParallaxMultiplier="0.7"
        android:fitsSystemWindows="true"/>
     <View
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@drawable/gradient"
        android:fitsSystemWindows="true" />
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="96dp"
        app:titleMarginTop="15dp"
        android:gravity="top"
        app:layout_collapseMode="pin"
        app:title="hello"
        app:popupTheme="@style/AppTheme.PopupOverlay"
       />
    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_gravity="bottom"/>
</android.support.design.widget.CollapsingToolbarLayout>

TabLayout没有设置app:layout_collapseMode,在CollapsingToolbarLayout收缩时就不会消失。

CollapsingToolbarLayout收缩时的高度是Toolbar的高度,所以我们需要把Toolbar的高度增加,给TabLayout留出位置,这样收缩后TabLayout就不会和Toolbar重叠。

Toolbar的高度增加,title会相应下移。android:gravity=”top”方法使Toolbar的title位于Toolbar的上方,然后通过app:titleMarginTop调整下title距顶部高度,这样Toolbar就和原来显示的一样了。



CollapsingToolbarLayout还可以和Palette搭配使用,但是我感觉在实际使用中有些坑,因为CollapsingToolbarLayout中的图片不确定,Palette从图片中获取到的色彩很可能不是你想要的。

感兴趣的朋友可以自己查下Palette的用法。

时间: 2024-12-12 11:31:50

【转】Material Design 折叠效果 Toolbar CollapsingToolbarLayout AppBarLayout的相关文章

[Material Design] MaterialButton 效果进阶 动画自动移动进行对齐效果

做 Android 动画效果一段时间了,感觉深深喜欢上了钻研特效.在手机上显示自己的特效是一件很不错的事情. 废话不多说,前面几天我发布了:[Material Design] 教你做一个Material风格.动画的按钮(MaterialButton) 在其中我讲解了我对 Android L 中 Material 效果的按钮的动画实现方式,今天的文章将基于其上进行进阶讲解新的特效. 在 MaterialButton 中的特效原理是:用户点击时启动一个动画,该动画是在点击位置画颜色渐变同时半径变大的

Material Design主题与ToolBar讲解

1.Material Design 的主题 Material Design 的主题有: @android:style/Theme.Material (dark version) @android:style/Theme.Material.Light (light version) @android:style/Theme.Material.Light.DarkActionBar 与之对应的Compat Theme: Theme.AppCompat Theme.AppCompat.Light Th

Android Material Design初步认识

Android M新控件有很多,Toolbar,TabLayout,AppBarLayout,NavigationView,CoordinatorLayout,CollapsingToolbarLayout等等.写出这篇文章纯粹因为本人记忆力不行,特意来此记录,如有不对的地方,还请帮忙纠正! 如果想快速的认识怎么用以上控件,Google推出的Android Studio已经把整个Material整合成一个Model,大家直接Create New Project就能很直观的知道怎么用了~下面这张图

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

打造极致Material Design动画风格Button

======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:http://blog.csdn.net/qiujuer/article/details/42471119 --学之开源,用于开源:初学者的心态,与君共勉! ================================

Android动画最新最全详解包含Material Design动画

以前写动画也是零零种种,需要的时候就查API或找现成的,不够系统.现在通过学习将Android整个动画体系勾勒出来,做到有的放矢. 安卓框架提供了2个动画系统:属性动画(Android 3.0)和View动画.这两种动画系统都是可行的,但是,在一般情况下,属性动画是首选的方法,因为它是更灵活,提供更多的功能.除了这两个系统,你可以利用Drawable动画,它允许你一帧一个的加载显示Drawable资源.所以总体来说Android API提供了三类的动画: - Tween动画或View动画(API

Material Design之利用CollapsingToolbarLayout轻松实现知乎日报新闻详情页顶部效果(带banner的toolbar伸缩折叠效果)

我们都知道CoordinatorLayout+AppBarLayout可以轻松实现滚动隐藏ToolBar的效果,今天我们要讲的是CollapsingToolbarLayout+ CoordinatorLayout+AppBarLayout实现带Banner的Toolbar折叠效果----向上滚动时,Banner会随着滚动手势向上收缩至隐藏,Banner上 的文字(实际上是CollapsingToolbarLayout上的文字)会逐渐缩小最后显示在Toolbar上,向下滚动时,Banner会逐渐显

Android开发实战之拥有Material Design风格的折叠布局

关于折叠布局,也许你并不陌生,最新版的陌陌,或者一些其他的社交APP都有一个折叠布局.折叠布局,让我们的APP更加具有交互性,同时也更加美观,先来展示一下效果图: 这是我个人做的一个APP主界面,可以看到,在滑动的时候,大标题随着拉动变为小标题,同时移动位置,并且有一张图片,随滑动淡出屏幕.如果你了解过Material Design,那么这个看似复杂的效果就很容易实现,都是用到这个desigon依赖库中的组件属性而完成的. 首先加入依赖库: compile 'com.android.suppor

Android Material Design之CollapsingToolbarLayout使用

CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承至FrameLayout,给它设置layout_scrollFlags,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView.Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端). 使用CollapsingToolbarLayout: <android.support.design.wid