一起玩转CoordinatorLayout

作为Material Design风格的重要组件,CoordinatorLayout协调多种组件的联动,实现各种复杂的效果,在实际项目中扮演着越来越重要的角色。本篇博客将由浅到深,带你一起玩转CoordinatorLayout。

官方文档对CoordinatorLayout是这样描述的:

这里写图片描述

CoordinatorLayout是一个加强版的FrameLayout,本质是一个ViewGroup,主要有两个用途:
1.用作应用的顶层布局管理器,作为界面其他控件的父容器
2.用作相互之间有特定交互行为的控件的父容器
通过为CoordinatorLayout的子View指定不同的Behavior(默认的Behavior或自定义的Behavior),就可以实现它们之间许多复杂的交互行为,例如侧滑,移动,滑动等。Behavior在后面会详谈,最后我们再来瞅一眼源码:

public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {}

先来了解一下NestedScrolling—Android嵌套滑动机制,用来完成复杂的滑动效果。要完成这样的交互,父View需要实现 NestedScrollingParent 接口,而子View需要实现 NestedScrollingChild 接口。CoordinatorLayout其实是NestedScrollingParent的实现类,也就意味着它的子View一定会实现NestedScrollingChild接口,这样一起协同完成复杂的滑动交互。

介绍工作就到这里,接下来通过三个例子,一起学习CoordinatorLayout(协调布局)。

一.CoordinatorLayout与AppBarLayout

官方文档中对AppBarLayout是这样描述的:AppBarLayout是一个垂直的LinearLayout,只有作为CoordinatorLayout的直接子View时才能正常工作,可以通过设置layout_scrollFlags属性或setScrollFlags()方法让AppBarLayout的子View具有“滚动行为”。我们先来看一个例子,再来分析这段描述。

这里写图片描述

列表向上滑动,布局收缩;列表向下滑动,布局向下展开到一定高度,待列表完全向下滑动到起始位置,布局再次向下展开。看看怎么实现的:

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="@color/colorPrimary"android:minHeight="50dp"app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"></LinearLayout><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"></android.support.v7.widget.Toolbar></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView></android.support.design.widget.CoordinatorLayout></LinearLayout>

CoordinatorLayout中,AppBarLayout与RecyclerView竖直排列;AppBarLayout中,LinearLayout与Toolbar竖直排列。AppBarLayout的官方文档告诉我们,通过设置layout_scrollFlags属性可以让子View具有滑动行为。结合布局文件可以看到,我们给LinearLayout设置了三个属性,都代表什么意思呢:

scroll:设成这个值的效果就是该View和scrolling view形成一个整体,示例中我们滑动RecyclerView时,LinearLayout也会响应滑动。有一点特别需要我们的注意,为了其他的滚动行为生效,必须同时指定scroll和其他标记。
exitUntilCollapsed:设成这个值的效果就是该View离开屏幕时,会被折叠到最小高度。该View已完全折叠后,再向下滚动scrolling view,直到scrolling view顶部的内容完全显示后,该View才会开始向下滚动以显现出来。
enterAlways:设成这个值的效果就是当scrolling view向下滚动时,该View会一起跟着向下滚动,示例图中有所体现。
enterAlwaysCollapsed:设成这个值的效果就是当我们开始向下滚动scrolling view时,该View会一起跟着滚动直到达到其最小高度。然后当scrolling view滚动至顶部内容完全显示后,再向下滚动scrolling view,该View会继续滚动到完全显示出来。示例图中有所体现。

篇幅有限,这里就不多做演示了,大家可以自己试试,组合成不同的效果。

通过分析CoordinatorLayout我们知道它的子View一定会实现NestedScrollingChild接口,这样一起完成复杂的滑动交互,我们看到布局中有一个RecyclerView,先瞅一眼源码:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {}

Bingo!RecyclerView其实就是NestedScrollingChild的实现类,这也就解释了嵌套滑动的实现。这里如果使用NestedScrollView,然后在里面嵌套一个布局也是可以的。最后我们还为RecyclerView设置了这样一个属性:

 app:layout_behavior="@string/appbar_scrolling_view_behavior">

这是因为CoordinatorLayout包含的子视图中,带有滚动属性的View必须设置app:layout_behavior属性,设置的这个属性到底是什么呢:

android.support.design.widget.AppBarLayout$ScrollingViewBehavior

原来是AppBarLayout自带一个Behivior,直接在源码里注解声明的,这个Behivior也只能用于AppBarLayout,作用是让他根据CoordinatorLayout上的手势进行一些效果(比如收缩,滚动)。关于CoordinatorLayout与Behivior工作原理,我们后面再谈。

二.CoordinatorLayout与CollapsingToolbarLayout
CollapsingToolbarLayout(折叠布局)继承至FrameLayout,通过给它设置layout_scrollFlags,它以控制子View响应layout_behavior事件并作出相应的变化(移除屏幕或固定在屏幕顶端)。我们看一个例子:

这里写图片描述

很常见也很好看的一个界面,看看布局代码:

<?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:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="250dp"><android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginEnd="60dp"app:expandedTitleMarginStart="50dp"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY"android:src="@drawable/bg"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7" /><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin" /></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /></android.support.design.widget.CoordinatorLayout>

结合代码我们看看CollapsingToolbarLayout的使用方法:

1.AppBarLayout与Toolbar的高度一定要设置具体值,这是最后展开与固定的值
2.CollapsingToolbarLayout的属性设置:layout_scrollFlags一定是必不可少的,属性值上文提过,这里不再重复了;contentScrim设置CollapsingToolbarLayout折叠后的背景颜色;expandedTitleMarginStart 设置没有收缩时title向左填充的距离;expandedTitleMarginEnd设置收缩结束时title向左填充的距离
3.ImageView的属性设置:layout_collapseMode (折叠模式)一定是必不可少的,一共有两种模式。pin:设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上;parallax:设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和视差因子搭配使用;layout_collapseParallaxMultiplier设置视差滚动因子,值为0~1,值越大视察越大。
4.CollapsingToolbarLayout的折叠、展开状态监听: CollapsingToolbarLayout是通过实现AppBarLayout的OnOffsetChangedListener接口,根据AppBarLayout的偏移来实现子View视差移动和显示。通过调用AppBarLayout的addOnOffsetChangedListener方法监听AppBarLayout的位移,从而判断CollapsingToolbarLayout的状态。

三.CoordinatorLayout与Behavior

前面提到,CoordinatorLayout的子View之间许多复杂的交互行为是通过指定Behavior实现的。那么实现原理是什么,我们看个例子:

这里写图片描述

TextView的位置会随着Button的改变而改变,并且显示当前的坐标。其实Behavior的原理就是观察者模式的应用,被观察者就是事件源dependency,观察者就是做出改变的child。具体看看怎么实现的:

public class FollowBehavior extends CoordinatorLayout.Behavior<TextView> {public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {return dependency instanceof Button;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {child.setX(dependency.getX() + 200);child.setY(dependency.getY() + 200);child.setText("观察者:" + dependency.getX() + "," + dependency.getY());return true;}
}

1.自定义一个FollowBehavior继承自Behavior,泛型就是child的类型,也就是观察者View
2.重写构造函数,因为CoordinatorLayout源码中会通过反射调用这个构造函数
3.重写layoutDependsOn():用来确定本次交互行为中的dependent view,在上面的代码中,当dependency是Button类的实例时返回true,就可以让系统知道布局文件中的Button就是本次交互行为中的被观察者。
4.重写onDependentViewChanged:当dependent view发生变化时,这个方法会被调用,参数中的child相当于本次交互行为中的观察者,观察者可以在这个方法中对被观察者的变化做出响应,从而完成一次交互行为。

代码布局中的应用:

<?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:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_behavior=".FollowBehavior" /><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="被观察者" /></android.support.design.widget.CoordinatorLayout>btn.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_MOVE) {v.setX(event.getRawX() - v.getWidth() / 2);v.setY(event.getRawY() - v.getHeight() / 2 - getStatusBarHeight(getApplicationContext()));}return true;}});

xml布局文件中,只需指定

app:layout_behavior=“你的Behavior包含包名的类名”

CoordinatorLayout就会反射生成你的Behavior,这样自定义的Behavior就能工作了。在Activity代码中,添加OnTouchListener,获取触摸点坐标,这里竖直方向上减去了状态栏的高度。

既然熟悉了Behavior的原理,这里我在之前的例子上升级了一下。先看效果图:

这里写图片描述

折叠布局中加了一个圆形头像,并且圆形头像的大小,位置会随着列表上下滑动而改变。没有美工设计,交互是自己瞎想的,大家凑合看看。重点是掌握自定义Behavior。

这里的圆形ImageView就是我们的观察者,给它指定Behavior,从而响应手势事件。谁是被观察者呢?这里我选择的是AppBarLayout,因为上文提到过,可以通过AppBarLayout的addOnOffsetChangedListener方法监听AppBarLayout的位移,从而判断CollapsingToolbarLayout的状态。既然能够获取到这个位移,那就可以让观察者对被观察者的位移变化做出响应。看看具体实现:

public class FollowBehavior extends CoordinatorLayout.Behavior<ImageView> {private int width, height, top, left;public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {return dependency instanceof AppBarLayout;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {if (dependency.getY() == 0) {width = child.getWidth();height = child.getHeight();top = child.getTop();left = child.getLeft();}float percent = Math.abs(dependency.getY()) / SixActivity.scrollRange;float yPercent = (float) (percent * 0.85);child.setY(top * (1 - yPercent));child.setX(left + 300 * percent);CoordinatorLayout.LayoutParams layoutParams =(CoordinatorLayout.LayoutParams) child.getLayoutParams();layoutParams.width = (int) (width * (1 - percent * 3 / 4));layoutParams.height = (int) (height * (1 - percent * 3 / 4));child.setLayoutParams(layoutParams);return true;}
}

具体分析一下onDependentViewChanged这个方法,AppBarLayout的折叠范围scrollRange是通过 appBarLayout.getTotalScrollRange()获取到的,这里我设置成了静态常量;当AppBarLayout完全展开,没有折叠时,获取到ImageView的基本属性;当AppBarLayout状态改变时,同时改变ImageView的坐标与大小,达到示例效果。使用时很简单,直接在CoordinatorLayout的XML布局加上即可。

    <de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/img"android:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="center"android:layout_marginTop="-340dp"android:src="@drawable/head"app:layout_behavior=".FollowBehavior" />

关于CoordinatorLayout的用法到这里差不多也就结束了,希望能对你有所帮助,如有不足与错误的地方随时向我提问,我会认真采纳。项目源码已经同步上传到我的github上,欢迎star,fork,提issues,一起进步!

https://github.com/18722527635/AndroidArtStudy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

离散数学图论旅行规划问题_2020年MathorCup高校数学建模挑战赛——C 题 仓内拣货优化问题...

下面的链接是精华版思路&#xff0c;亮点是对第六问的探讨。高度概括一下&#xff1a;第一问曼哈顿&#xff0c;第二问用免疫&#xff0c;三问增加任务单&#xff0c;四问增加拣货员&#xff0c;五问改变复核台&#xff0c;六问亮点来探讨~ 有点皮MathorCup C题 仓内拣货优化问…

【VBA编程】10.自定义集合

自定义集合类型&#xff0c;类似于变量声明&#xff0c;只是要将Dim关键字和New collection关键字搭配起来使用&#xff0c;其语法描述如下&#xff1a;其中集合名的命名方式同于标准变量的命名 Dim 集合名 As New collection 对于已经定义的集合对象&#xff0c;可以使用集合的…

git fork clone 区别_Working with Git | Git 与 GitHub

关于各位好&#xff0c;这里是 Chinas Prices Project 项目的知乎专栏。关于 CPP 项目&#xff0c;您可以在这篇文章里了解到更多的信息。若您对这个项目感兴趣&#xff0c;我们非常欢迎您与我们交流您的想法与见解。在一个团队的成员同时为一个项目进行开发工作时&#xff0c;…

舒适的路线(codevs 1001)

题目描述 DescriptionZ小镇是一个景色宜人的地方&#xff0c;吸引来自各地的观光客来此旅游观光。Z小镇附近共有N(1<N≤500)个景点&#xff08;编号为1,2,3,…,N&#xff09;&#xff0c;这些景点被M&#xff08;0<M≤5000&#xff09;条道路连接着&#xff0c;所有道路都…

PHP_Smarty

模板 数据与表现层的标签分离 smarty是PHP 与 HTML代码的分离 小型模板类 $smarty 的工作流程&#xff1a; 把需要显示的全局变量&#xff0c;赋值塞到对象内部的属性上&#xff0c;一个数组中.编译模板&#xff0c;把{$标签},解析成相应的<?php echo 代码引入编译后的PHP文…

读中文_挑战来了!康辉喊你读中文十级绕口令!

文章来源&#xff1a;央视频汉语桥木甬读桶不读涌&#xff0c;月农读脓不读胧。米更读粳不读梗&#xff0c;日青读晴不读睛。米宗读粽不读综&#xff0c;言丁读订不读钉。土竟读境不是镜&#xff0c;土平读坪不是评。耳令读聆不读岭&#xff0c;火登读灯不读澄。言甬读诵不读蛹…

ios 自定义键盘

由于项目需要&#xff0c;需要自定义键盘。ios系统键盘会缓存键盘输入&#xff0c;并保存在系统目录下的文件里&#xff0c;并且是明文存储&#xff0c;存在帐号密码泄漏风险。在别人代码基础上修改了下&#xff0c;美化了下界面&#xff0c;去掉了字符输入&#xff0c;加了点击…

【GOF23设计模式】迭代器模式

【GOF23设计模式】迭代器模式 来源&#xff1a;http://www.bjsxt.com/ 一、【GOF23设计模式】_迭代器模式、JDK内置迭代器、内部类迭代器 1 package com.test.iterator;2 /**3 * 自定义的迭代器接口4 */5 public interface MyIterator {6 void first(); //将游标指向第…

51单片机50个实例代码_【附代码】51单片机电子密码锁教程

简介大家好&#xff0c;这篇文章的内容是关于如何用51单片机来制作一个电子密码锁的教程&#xff0c;通过这篇教程可以让刚入门的朋友了解矩阵键盘、LCD1602的使用方法&#xff0c;以及密码输入和修改的程序介绍&#xff0c;我会对每个部分进行详细的介绍。首先我们来看一下这个…

8数据提供什么掩膜产品_博硕能为你提供什么产品?

自动喷漆设备应用于线条、木门、橱柜、楼梯、套房家具、办公家具、木饰面板、外墙保温装饰一体板板等产品领域&#xff0c;针对NC、PU、UV、水性漆和氟碳漆等不同种类的油漆&#xff0c;进行自动化喷涂和干燥作业。自动喷漆设备有多种规格型号&#xff0c;分为不同的喷涂方式。…

jsp页面验证码(完整实例)

项目结构如下&#xff0c;MyEclipse中新建一个Web Project&#xff0c;取名servlet 1、src下new一个servlet类 package com.servlet;import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOExcept…

开源oa_圈子哥推荐一款基于 Spring Boot 开发 OA 开源产品,学习/搞外快都是不二选择!...

点击上方蓝字关注「程序员的技术圈子」今天圈子哥给大家推荐一套Spring Boot 开发 OA系统&#xff0c;系统功能齐全&#xff0c;不管是用来学习或者搞外快都是不错的选择&#xff0c;clone下来吧&#xff01;办公自动化(OA)是面向组织的日常运作和管理&#xff0c;员工及管理者…

Libevent初探

Libevent 是一个用C语言编写的、轻量级的开源高性能网络库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b;源代码相当精炼、易读&am…

特别慢_背什么都特别慢,该怎么提高记忆力?

考研是一项全方位的比拼&#xff0c;除了每天进行知识点的复习&#xff0c;还要做题、总结&#xff0c;最后还得进行背诵记忆&#xff0c;其实什么科目都需要背的&#xff0c;就算数学&#xff0c;该记的概念和公式也是要记忆的&#xff0c;因为会做题更快&#xff0c;提高效率…

第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...

3.1 万亿级数据洪峰下的分布式消息引擎 前言 通过简单回顾阿里中间件(Aliware)消息引擎的发展史&#xff0c;本文开篇于双11消息引擎面临的低延迟挑战&#xff0c;通过经典的应用场景阐述可能会面临的问题 - 响应慢&#xff0c;雪崩&#xff0c;用户体验差&#xff0c;继而交易…

Linux目录结构和常用命令

一、Linux目录结构 你想知道为什么某些程序位于/bin下&#xff0c;或者/sbin&#xff0c;或者/usr/bin&#xff0c;或/usr/sbin目录下吗&#xff1f;例如&#xff0c;less命令位于/usr/bin目录下。为什么没在/bin中&#xff0c;或/sbin&#xff0c;或/usr/sbin目录中&#xff1…

挂载nfs文件系统_综合架构-day38-NFS服务补充

1.如何让nfs永久挂载-2种方法开机自启动文件1.vim /etc/rc.d/rc.local需要修改执行权限chmod x /etc/rc.d/rc/localmount -t nfs 172.16.1.31:/upload/ /mnt/2.vim /etc/fstab172.16.1.31:/upload /mnt nfs defaults 0 02.exportfs 加载配置生效&#xff0c;等价于优雅重启[15:…

A Neural Algorithm of Artistic Style

本系列文章由 yhl_leo 出品&#xff0c;转载请注明出处。 文章链接&#xff1a; http://blog.csdn.net/yhl_leo/article/details/53931536 1. 资源 Paper: A Neural Algorithm of Artistic StyleTensorFlow version in GitHub: anishathalye/neural-styleCaffe version in GitH…

CSS布局奇淫技巧之--各种居中

居中是我们使用css来布局时常遇到的情况。使用css来进行居中时&#xff0c;有时一个属性就能搞定&#xff0c;有时则需要一定的技巧才能兼容到所有浏览器&#xff0c;本文就居中的一些常用方法做个简单的介绍。 注&#xff1a;本文所讲方法除了特别说明外&#xff0c;都是兼容I…

手写数字识别中多元分类原理_广告行业中那些趣事系列:从理论到实战BERT知识蒸馏...

导读&#xff1a;本文将介绍在广告行业中自然语言处理和推荐系统实践。本文主要分享从理论到实战知识蒸馏&#xff0c;对知识蒸馏感兴趣的小伙伴可以一起沟通交流。摘要&#xff1a;本篇主要分享从理论到实战知识蒸馏。首先讲了下为什么要学习知识蒸馏。一切源于业务需求&#…