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

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

一、相关基础属性介绍

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

ScrollingActivity.gif

ScrollingActivity的布局代码如下

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: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: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:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:layout_collapseMode="pin"

app:popupTheme="@style/AppTheme.PopupOverlay" />

android:layout_width="match_parent"

android:layout_height="match_parent"

app:layout_behavior="@string/appbar_scrolling_view_behavior"

>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="@dimen/text_margin"

android:text="@string/large_text" />

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" />

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属性):

scroll:将此布局和滚动时间关联。这个标识要设置在其他标识之前,没有这个标识则布局不会滚动且其他标识设置无效。

enterAlways:任何向下滚动操作都会使此布局可见。这个标识通常被称为“快速返回”模式。

enterAlwaysCollapsed:假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。

exitUntilCollapsed:当你定义了一个minHeight,此布局将在滚动到达这个最小高度的时候折叠。

snap:当一个滚动事件结束,如果视图是部分可见的,那么它将被滚动到收缩或展开。例如,如果视图只有底部25%显示,它将折叠。相反,如果它的底部75%可见,那么它将完全展开。

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

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

off:这个是默认属性,布局将正常显示,没有折叠的行为。

pin:CollapsingToolbarLayout折叠后,此布局将固定在顶部。

parallax:CollapsingToolbarLayout折叠时,此布局也会有视差折叠效果。

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

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

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

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

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

哔哩哔哩Android客户端视频详情页.gif

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

额...弹幕播放器...

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

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

xmlns:app="http://schemas.android.com/apk/res-auto"

android:id="@+id/coordinatorLayout"

android:layout_width="match_parent"

android:layout_height="match_parent">

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: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">

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"/>

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">

android:id="@+id/videoview"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:id="@+id/danmaku"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:layout_collapseMode="pin"

app:popupTheme="@style/AppTheme.PopupOverlay" >

android:id="@+id/playButton"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center"

android:visibility="gone">

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_gravity="center_horizontal"

android:src="@mipmap/ic_play_circle_filled_white_48dp"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#ffffff"

android:text="立即播放"

android:layout_gravity="center_vertical"

/>

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" />

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

#FA7199

因为我们要实现沉浸式状态栏,所以就需要先把整个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)方法使工具栏展开。

CollapsingToolbarLayout状态监听演示.gif

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

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

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

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

android:startColor="#33000000"

android:endColor="#00000000"

android:angle="270" />

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

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

android:layout_width="match_parent"

android:layout_height="40dp"

android:background="@drawable/gradient"

android:fitsSystemWindows="true"

/>

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

有无渐变遮罩层的对比.jpg

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

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

模仿哔哩哔哩视频详情页.gif

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

三.CollapsingToolbarLayout与TabLayout

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

CollapsingToolbarLayout与TabLayout.gif

来看下CollapsingToolbarLayout里的代码

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:id="@+id/app_bar"

android:layout_width="match_parent"

android:layout_height="250dp"

android:fitsSystemWindows="true"

android:theme="@style/AppTheme.AppBarOverlay">

android:id="@+id/toolbar_layout"

android:layout_width="match_parent"

android:layout_height="match_parent"

app:titleEnabled="false"

android:fitsSystemWindows="true"

app:contentScrim="@color/colorPrimary"

app:statusBarScrim="@android:color/transparent"

app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

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"

android:src="@drawable/girl2"/>

android:layout_width="match_parent"

android:layout_height="40dp"

android:background="@drawable/gradient"

android:fitsSystemWindows="true" />

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="96dp"

android:minHeight="?attr/actionBarSize"

android:gravity="top"

app:layout_collapseMode="pin"

app:title="hello"

app:popupTheme="@style/AppTheme.PopupOverlay"

app:titleMarginTop="15dp"

/>

android:id="@+id/tablayout"

android:layout_width="match_parent"

android:layout_height="45dp"

android:layout_gravity="bottom" />

android:id="@+id/viewpage"

android:layout_width="match_parent"

android:layout_height="wrap_content"

app:layout_behavior="@string/appbar_scrolling_view_behavior">

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的用法。

就是这些。 []~( ̄▽ ̄)~*

android 伸缩工具栏,看,这个工具栏能伸缩折叠——Android CollapsingToolbarLayout使用介绍...相关推荐

  1. VS2008工具栏看不到配置管理器或者解决方案配置

    Vs2008工具栏看不到配置管理器或者解决方案配置,很不方便,看不出来是是Debug还是Release.解决方法如下: 1.工具-选项-项目和解决方案-常规,勾选显示高级生成配置. 2.如果第一步没有 ...

  2. ATL 实现定制的 IE 浏览器栏、工具栏和桌面工具栏

    下载源代码 关键字:Band,Desk Band,Explorer Band,Tool Band,浏览器栏,工具栏,桌面工具栏 一.引言 最近,由于工作的要求,我需要在 IE 上做一些开发工作.于是在 ...

  3. 计算机菜单右侧桌面,桌面工具栏怎么还原?工具栏在右边怎么办

    新手们在使用电脑的过程中总有这样那样的问题出现,尽管是很简单的问题,但是对于新手来说,一时也想不到对策,桌面工具栏怎么还原的问题则是其中一个再简单不过的问题了.工具栏在右边怎么办.工具栏怎么还原,这一 ...

  4. MFC对话框如何使用工具栏并修改工具栏的背景颜色与自绘对话框统一(二)

    写这篇文章只是为了解决我上一篇文章遗留的一个问题,本来觉得这个问题可以不用管,但是在我写的程序中发现并不能置之不理,先来重现这个问题 工具栏有一部分没有绘上 看红色框包围的地方,是背后 VS2010 ...

  5. 为学Android,我看了这些书

    刚刚开始新的学习生活时,很容易走错方向,然后,这意味着不知道该学习什么,不知道该怎样学习,很显然,我写下这句话意味着我走过这样的路,为此,就付出了不小的代价,浪费了很多时间.       这篇文章当然 ...

  6. Android开发必看知识,不看后悔

    Android开发必看知识,不看后悔 打包为大家奉上最实用最给力的资源,不看你绝对后悔. 最强大的UI特效 奇艺高清UI界面源代码 http://www.eoeandroid.com/thread-1 ...

  7. Android图片爬虫,看妹纸神器项目源码,ListView单张图片查看

    Android图片爬虫,看妹纸神器项目源码 刚自学完安卓,国庆7七天花了6天纯手写入门级app,从集成图片爬虫到整个项目结束真是一步一个坑. 整个项目没有用框架,都是手写纯属练手,项目中主要用到的技术 ...

  8. 安卓开发贴吧!Android高级工程师必看系列,建议收藏

    缘起 经过近十年的发展,Android技术优化日新月异,如今Android 10.0 已经发布,Android系统性能也已经非常流畅,可以在体验上完全媲美iOS.到了各大厂商手里,改源码.自定义系统, ...

  9. android客户端框架,最新的一版,通用Android 客户端架构设计,只有你还没看过

    客户端架构设计 客户端设计 目的是整体设计客户端App,架构上打好铺垫. Android客户端架构设计 主要从以下几个方面进行设计:MVP设计风格.整体架构.日志系统.网络系统.本地存储.Test模块 ...

最新文章

  1. 禁止解析PHP、限制user_agent、php相关配置
  2. CloudCC CRM:物联网必将成为CRM的推动力
  3. 再分享一个竞品分析报告
  4. 爆料称配备更大屏幕尺寸的Apple Silicon版iMac仍在研发中
  5. Enterprise Library:DAAB + OLEDB/ODBC操作Access数据库
  6. 苹果CMSv10自适应短视频原创挖片网高端手机+电脑模板
  7. 使用TreeMap对要签名做排序ASCII码排序
  8. vivo+android+root,vivo手机怎么获取root权限?vivo手机一键ROOT教程
  9. ftp断点下载工具,推荐6款好用的ftp断点下载工具,怎么使用
  10. 局域网内两台电脑ping不通
  11. MySql查询某个时间段内的数据(前一周、前三个月、前一年等)
  12. python爬虫案例:抓取网易新闻
  13. irc 开源软件_前4个开源IRC客户端
  14. windows多用户“同时”远程连接
  15. Linux软件集成开发环境
  16. 无人驾驶汽车发展史大事纪实
  17. 广州如何下载公积金的缴交证明和个人信息表
  18. WPS整段缩进(类似代码格式)
  19. 如何在ubuntu终端输入密码显示星号
  20. Python 可迭代对象与迭代器的对比

热门文章

  1. 计算机网络有限制,计算机网络中软件限制策略的应用规则有哪些
  2. C语言打印等腰三角形
  3. python技术开发证书_python+证书
  4. rocketmq 重复消费_RocketMQ的十二个特性,你都知道吗「下」
  5. window mysql安全设置_mysql安全配置方案
  6. java word 读取excel数据_在Java中实现读写操作Word、Excel等文件
  7. python tk messagebox_tkMessageBox
  8. linux mint有没有服务器版,Linux Mint 20“Ulyana”正式版发布
  9. 5/29 c的结构体变量
  10. vue小项目总结与笔记【五】——一个轮播图插件vue-awesome-swiper