前言

Android引入了Material Design设计,并且为开发者提供了design支持库,库里包含了大量的材料设计相关的新布局。其中CoordinatorLayout布局最为重要,因为它提供内部子控件之间的各种协调效果,除了Google提供的Toobar控件和滚动内容的联动效果外,用户还可以自定义不同视图之间的behavior,现在就来学习一下这些酷炫的新效果。

实现效果

实现接口

CoordinatorLayout is a super-powered android.widget.FrameLayout FrameLayout.
CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout. As a container for a specific interaction with one or more child views

Android开发文档里介绍CoordinatorLayout是FrameLayout的增强版,但是它并非继承自FrameLayout而是直接继承了ViewGroup。协调者布局通常被用作以下两种目的,作为应用程序的最高层装饰布局或者作为和一个或多个子视图有特殊交互效果的布局容器。协调者布局的交互效果都是通过behavior这种机制实现多个不同视图之间的协调一致。

Android应用的界面通常被分成两大部分,上面的是各种标题栏,下面是内容布局。如果内容布局是可滚动的内容,标题栏会因为无法跟随着内容部分滚动而遮挡内容减少内容有效展示界面。CoordinatorLayout内置的appbar_layout_behavior正好能够支持内容布局和上方的联动效果。AppBarLayout是一个继承自LinearLayout的新布局,默认情况下方向是竖直方向,它会为自己的直接子元素增加app:layout_scrollFlags效果,元素所有合法的值如下:

滚动值 效果
scroll 子视图随着外部的内容布局滚动而一起滚动
enterAlways 子视图在内容布局向下滚动时一定会出现顶部
enterAlwaysCollapsed 需要配合minHeight使用,当用户向下滚动内容时首先出现的是minHeight高度的子视图,随后内容布局滚动到和minHeight一样高的距离后在跟着滚动出其它的子视图
exitUntilCollapsed 用户向上滚动内容布局最后还会留下minHeight高度的子视图
snap 用户滚动如果子视图展示超过50%则会继续展示全部子视图,如果没超过50%,则隐藏展示的子布局

上面的AppBarLayout支持的滚动效果虽然已经可以满足部分需求,但是用户有时还需要能够精确的指定状态栏里的内容压缩(Collapse)的动画效果,压缩效果令整体的滚动切换过程更加自然,提升用户体验。CollapsingToolbarLayout布局提供了这种压缩效果,它继承于FrameLayout,内部的子视图可以按照FrameLayout的方式布局,不过需要注意的是如果用户需要为Toolbar设置固定模式,一定要把Toolbar放在CollapsingToolbarLayout的最前方,确保不会被其他子视图遮挡。和AppBarLayout类似,CollapsingoolbarLayout也通过为子视图添加属性app:layout_collapseMode来实现压缩效果:

模式值 效果
parallax 视差模式,压缩的过程中用户可以设置子视图滚动速度通常比内容布局滚动速度小,这样就能看到压缩过程了
pin 固定模式,被压缩的子视图最后被固定在顶部

app:layout_collapseParallaxMultiplier属性能够在视差模式影响滚动速度,设置的值在0~1之间,值越大表明视差效果越明显。

实现过程

最开始需要引入design设计包,在Activity的布局文件中添加CoordinatorLayout为根部局,在内部增加AppBarLayout控制顶部的滚动效果,在AppBarLayout内部增加CollapsingToolbarLayout负责压缩效果实现,最后在其内部增加需要压缩展示的ImageView和定位用的FrameLayout。下面放置支持嵌套滚动的RecyclerView做内容布局,为它设置appbar_layout_behavior让它在滚动的时候通知到AppBarLayout布局。

<?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:orientation="vertical"tools:context="com.example.design.CoordinatorActivity"><!--顶部支持滚动的布局--><android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"android:fitsSystemWindows="true"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.CollapsingToolbarLayout
            app:layout_scrollFlags="scroll|exitUntilCollapsed"app:contentScrim="@color/colorPrimary"android:layout_width="match_parent"android:layout_height="match_parent"><ImageView
                android:scaleType="centerCrop"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.9"android:src="@drawable/mountain"android:layout_width="match_parent"android:layout_height="200dp" /><FrameLayout
                android:id="@+id/layout"android:layout_gravity="bottom|center_horizontal"app:layout_collapseMode="parallax"android:layout_width="match_parent"android:layout_height="100dp"></FrameLayout></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><!--内容展示布局--><android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"app:layout_behavior="@string/appbar_scrolling_view_behavior"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v7.widget.RecyclerView><!--TitleBar--><android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"app:theme="@style/ThemeOverlay.AppCompat.Dark"app:title=""app:layout_anchor="@id/layout"android:layout_width="match_parent"android:layout_height="54dp"></android.support.v7.widget.Toolbar><!--顶部向下展示的title--><TextView
        android:id="@+id/textview"android:textSize="25sp"android:textColor="@color/colorAccent"android:background="@color/colorPrimary"android:textStyle="bold"android:gravity="center"app:layout_behavior="@string/share_behavior"android:text="@string/name_list"android:layout_width="match_parent"android:layout_height="50dp" /><!--跟随压缩缩放的圆形图片--><com.example.design.widget.CircleImageView
        android:id="@+id/image"android:scaleType="centerCrop"app:layout_behavior="@string/drawable_behavior"android:layout_gravity="center_horizontal"android:layout_marginTop="150dp"android:src="@drawable/waterfall"android:layout_width="80dp"android:layout_height="80dp" /><android.support.design.widget.FloatingActionButton
        android:id="@+id/floatButton"android:src="@drawable/ic_camera_black_24dp"android:background="@color/colorAccent"android:layout_gravity="bottom|right"android:layout_margin="15dp"android:layout_width="wrap_content"android:layout_height="wrap_content" /></android.support.design.widget.CoordinatorLayout>

通过上面的布局就可以实现简单的顶部压缩效果展示,现在考虑顶部从上向下出现的标题如何实现。从上向下这个动画效果完全可以使用属性动画translationY来实现,不过如何获得压缩动画的执行状态呢,上面设置了Toolbar锚点在CollapsingToolbarLayout里的FrameLayout上,Toolbar会随着FrameLayout的压缩过程逐渐改变自己的位置信息,可以为Title布局增加自定义Behavior监听Toolbar的位置更新信息,在Toolbar改变的过程中更新Title布局的位置。自定义Behavior需要扩展自CoordinatorLayout.Behavior泛型类,其中的泛型就是需要改变的布局类型,title布局类型是TextView类型,所以这个Behavior实现如下:

 public static final class MessageBehavior extends CoordinatorLayout.Behavior<TextView> {// 记录Toolbar的顶部位置private int start = 0;// 构造函数public MessageBehavior() {}public MessageBehavior(Context context, AttributeSet attrs) {super(context, attrs);}// 判断dependency的类型@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {return dependency instanceof Toolbar;}// 当被依赖的对象也就是被监听的对象,这里就是Toolbar改变时回调,设置title布局的translationY@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {if (start == 0) {start = (int) dependency.getY();}float ratio = dependency.getY() / start;child.setY(-child.getMeasuredHeight() * ratio);return true;}
}

在Behavior中将被监视的视图称作Dependency,也就是依赖视图,根据依赖视图做更新的视图称作Child,setY查看源码会发现其实就是通过设置translationY来实现视图的滚动。

再来思考如何实现图片的跟随缩放效果,上面通过Toolbar获取压缩效果执行状态ratio,现在可以根据这个ratio设置图片的位置和大小,实现代码如下:

public static final class DrawableBehavior extends CoordinatorLayout.Behavior<ImageView> {private int start = 0;private int startX = 0;private int startY = 0;private int endX = CommonUtils.dp2px(10);private int endY = CommonUtils.dp2px(10);private int endSize = CommonUtils.dp2px(30);private int startSize = 0;public DrawableBehavior() {}public DrawableBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {return dependency instanceof Toolbar;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {if (start == 0) {start = (int) dependency.getY();startX = (int) child.getX();startY = (int) child.getY();startSize = CommonUtils.dp2px(80);}float ratio = dependency.getY() / start;// 设置图片的位置child.setX(startX + (1 - ratio) * (endX - startX));child.setY(startY + (1 - ratio) * (endY - startY));// 设置图片的宽高child.getLayoutParams().width = (int) (startSize + (1 - ratio) * (endSize - startSize));child.getLayoutParams().height = (int) (startSize + (1 - ratio) * (endSize - startSize));child.requestLayout();return true;}
}

查看所有实现代码请点击查看代码。

CoordinatorLayout布局和自定义Behavior相关推荐

  1. 红橙Darren视频笔记 CoordinatorLayout:实现自定义behavior

    效果: 目标:利用CoordinatorLayout实现自定义behavior ,顶部的TitleBar和底部的ActionBar实现能够随着手势自由显示和隐藏 activity中使用了recycle ...

  2. CoordinatorLayout高级用法-自定义Behavior

    在新的support design中,CoordinatorLayout可以说是最重要的一个控件了,CoordinatorLayout给我们带来了一种新的事件的处理方式--behavior,你是不是还 ...

  3. Android仿小米时钟嵌套滑动(NestedScroll, 自定义behavior)

    最近无聊刷手机的时候, 发现小米时钟的嵌套滑动很有意思, 就试着做了下 先上对比图: 分析下小米时钟的滑动 闹钟列表 向上滑动时, 时钟面 透明度上升, 快到最大滑动时逐渐显示数字时钟. 在闹钟列表向 ...

  4. Android自定义Behavior出现This graph contains cyclic dependencies

    最近刚开始学习使用CoordinatorLayout,并且自定义Behavior,因为项目要求,要在webview滑动的时候,headview要跟着滑动改变自身大小,并且要使webview在headv ...

  5. Android CoordinatorLayout 自定义Behavior 高仿美团商家详情界面 实现页面内容复杂联动效果

    内容如题 效果如下 顺带涉及到: Scroller+Handler 实现View自动滑动 View属性动画 触摸事件分发机制 ConstraintLayout约束布局 emmmm 实现参考: Cons ...

  6. layui totalRow 多层嵌套json_自定义 Behavior,实现嵌套滑动、平滑切换周月视图的日历...

    使用 CoordinateLayout 可以协调它的子布局,实现滑动效果的联动,它的滑动效果由 Behavior 实现.以前用过小米日历,对它滑动平滑切换日月视图的效果印象深刻.本文尝试用自定义 Be ...

  7. 自定义Behavior的艺术探索-仿UC浏览器主页

    出处:http://www.jianshu.com/p/f7989a2a3ec2 前言&效果预览 最近几个周末基本在研究CoordinatorLayout控件和自定义Behavior当中,这期 ...

  8. 自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页

    前言 记得两年前的时候,曾写过自定义 behavior 的文章 自定义 Behavior -仿新浪微博发现页的实现,到现在差不多有一万多的阅读量吧. image 今天,对该 behavior 进行升级 ...

  9. android安卓定义,安卓自定义Behavior

    自定义Behavior,最外层布局必须是CoordinatorLayout 实现的效果,上滑隐藏TextView,下滑显示TextView 效果如下: GIF.gif public class Bot ...

  10. 自定义Behavior第一学-仿QQ朋友圈头部沉浸式效果

    第一次学习如何通过自定义Behavior实现一些比较好看的效果.我们先来看看效果. 接下来我们来贴上代码,首先是布局文件,最外面是CoordinatorLayout,里面嵌套一个NestedScrol ...

最新文章

  1. java怎么打开_java开不了怎么办?java怎么打开?
  2. Android开发笔记之:Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)
  3. php重载,PHP重载基础知识回顾
  4. python3 scarpy
  5. volatile的作用
  6. 【Python selenium自动化环境配置】4步搞定ChromeDriver版本选择
  7. 信息学奥赛一本通(1016:整型数据类型存储空间大小)
  8. UVA 11584 Partitioning by Palindromes (字符串区间dp)
  9. manjaro 搜狗输入法_Manjaro日常使用 之一:日常办公
  10. solidwork 侵权 证据_电子商务法复习题
  11. Python入门--函数传递过程中实参的变化
  12. Server Application Error(IIS)
  13. RT_thread 临界区保护
  14. 【荔枝派zero】usb虚拟串口实现
  15. 第一天之导入Vuetify的坑
  16. 基于cefsharp的浏览器应用开发(支持XP系统)
  17. CCF 俄罗斯方块(满分代码 + 解题思路 + 技巧总结)201604 - 2
  18. 【算法学习笔记】6:SAT问题的一些经典求解策略
  19. Chrome浏览器源代码编译安装Dark Reader插件
  20. 计算机网络题库——第4章 网络层

热门文章

  1. Metasploit -- 各类密码破解
  2. numpy创建单位矩阵和对角矩阵
  3. Verilog中$finish、$stop的使用与区别
  4. apache 启动失败 查看日志
  5. 怎么查看当前服务器的运行环境,如何查看Apache服务器运行状态
  6. pytorch动态调整学习率之Poly策略
  7. java架构师线下培训,万分膜拜!
  8. 谷歌的天敌竟然是亚马逊:从开放7-Mic阵列授权说起
  9. 【进阶】QQ聊天机器人--群聊机器人篇
  10. Mediawiki 使用