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

简介

先上个小米日历的图,让大家知道要做一个什么效果:


这是小米日历的效果,在用户操作列表的时候,将日历折叠成周视图,扩大列表的显示区域,同时也不影响日历部分的功能使用,有趣且实用。

下面利用 CoordinateLayout.Behavior,简单实现一个类似的效果。

日历控件

我并不打算自己再写一个日历控件。原本想用原生的 CalendarView,但是 CalendarView 不支持周视图,可自定义程度也不高。

在 GitHub 搜了一下,决定使用 MaterialCalendarView。这个库比较流行,它支持周月视图的切换,符合 Material Design,也可以自定义显示效果。

引入该库,在布局文件中使用:

<com.prolificinteractive.materialcalendarview.MaterialCalendarViewandroid:id="@+id/calendar"android:layout_width="match_parent"android:layout_height="wrap_content"app:mcv_showOtherDates="all" />

切换视图代码如下:

calendarView.state().edit()    .setCalendarDisplayMode(CalendarMode.WEEKS)    .commit();

Behavior

写代码之前,还有些东西需要先了解一下。

用 CoordinatorLayout 作为根布局,就可以协调它子控件之间的联动效果,至于如何联动,是由它的内部类 Behavior 实现的。在布局中,对子控件配置 app:layout_behavior 属性,实现对应的联动效果。所以这里我们需要自定义日历和列表的两个 Behavior。

Behavior 有两种实现联动的方式。一种是通过建立依赖关系,一种是通过 RecyclerView 或 NextedScrollView 的嵌套滑动机制,后面都会讲到。我们要先分析想要实现的效果,确定各个子控件之间的依赖关系,避免循环依赖等错误。

另外,由于 CoordinatorLayout 的布局类似于 FrameLayout,所以还需要考虑摆放控件位置的问题。

折叠效果

大家可能有看过 RecyclerView 和 AppBarLayout 联动的效果,这种效果需要给 RecyclerView 配置 Behavior:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

但为什么只要给 RecyclerView 配不用给 AppBarLayout 配?看一下 AppBarLayout 的源码就知道了,它默认已经给自己配了:

@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)

看它 Behavior 源码发现,它继承了 ViewOffsetBehavior。ViewOffsetBehavior 的作用是方便改变控件的位置和获取偏移量。所以这里我再偷个懒,把源码里的 ViewOffsetBehavior 直接拷出来用了。

我们自定义两个 Behavior,列表控件的 CalendarScrollBehavior 和日历控件的 CalendarBehavior,都继承 ViewOffsetBehavior。

CalendarScrollBehavior

在 Behavior 中,通过 layoutDependsOn 方法来建立依赖关系,一个控件可以依赖多个其他控件,但不可循环依赖。当被依赖的控件属性发生变化时,会调用 onDependentViewChanged 方法。

为了降低复杂程度,我将所有折叠操作都放到 CalendarBehavior 里做,而 CalendarScrollBehavior 里面做一件事,就是把列表置于日历之下。参考了源码 ScrollingViewBehavior,CalendarScrollBehavior 代码如下:

public 

这里没有用到 onDependentViewChanged 方法,所有联动操作都将通过嵌套滑动机制实现。

CalendarBehavior

接下来是本文的重点,我们使用的嵌套滑动机制,主要涉及到以下几个方法:

  • onStartNestedScroll

  • onNestedPreScroll

  • onStopNestedScroll

  • onNestedPreFling

当 RecyclerView 或 NestedScrollView 滑动时,CoordinatorLayout 的子控件 Behavior 可以接收到对应的回调。看方法名应该大概知道它的用途了,下面都会提到。

onStartNestedScroll 的返回值决定是否接收嵌套滑动事件。我们判断,只要是上下滑动,就接收:

@Override

onNestedPreScroll 这个方法是在准备滚动之前调用的,它带有滚动偏移量 dy。

@Override

我们要做的,就是在恰当的时候,消费掉这个偏移量,转化成折叠的效果。

分析一下这个折叠效果。滚动时,日历也向上滚动,最多到当前选中日期那一行,滚动范围和当前选中日期有关。向上移动是负值,所以日历的滚动范围是从 0 到 -calendarLineHeight * (weekOfMonth - 1),减 1 是因为要多留一行显示星期的标题。列表的滚动范围则是固定的,最多向上移动 5 倍的日历行高,也就是从 0 到 -calendarLineHeight * 5。

判断偏移量是否在这个范围内,用 ViewOffsetBehavior 的 setTopAndBottomOffset 方法来改变控件位置。所以还要拿到 CalendarScrollBehavior 进行操作。参数 target 是触发嵌套滑动的控件,在这里就是 RecyclerView,通过 target.getLayoutParams()).getBehavior() 就可以拿到 CalendarScrollBehavior 了。

折叠过程中,要将偏移量消费掉,这就用到了 consumed 这个参数,它是一个长度为 2 的数组,存放的是要消费掉的 x 和 y 轴偏移量。

最终代码如下:

@Override

现在我们可以把布局参数配一下,看一下效果了,布局如下:

<?xml  version="1.0" encoding="utf-8"?>

在选中其他日期的时候,记得通知 Behvior 选中的是该月的第几个星期:

new OnDateSelectedListener() {

效果如下:


星期标题

上面效果可以看到,显示星期的标题也一起向上移动了,而且 MaterialCalendarView 是没办法隐藏这个标题的。

没办法,只好自己写一个星期标题的控件盖在上面,简单写了一个 WeekTitleView,代码就不贴了,在布局里加上:

<?xml  version="1.0" encoding="utf-8"?>

效果如下:

平滑切换视图

接下来处理周月视图切换的问题。

当嵌套滑动结束时会回调 onStopNestedScroll 方法,可以在这里根据当前控件的位置,判断是否要切换视图。当滑动到最上面的时候切换为周视图,其余的情况都是月视图:

@Override

效果如下:


MaterialCalendarView 的视图切换会有一点点卡顿,但还是能接受的。

惯性滑动

上面效果可以看出一个问题,当滑动到一半的时候松手,应该要恢复到完整视图的位置。这里包含了,快速滑动后惯性滑动到指定位置的效果,和没有快速滑动时,往就近的指定位置滑动这两种效果。

我们可以从 onNestedPreFling 拿到滑动速度,方法的返回值决定了是否进行惯性嵌套滑动:

@Override

在 onStopNestedScroll 里判断并执行滚动。由于我们的滚动折叠效果是在 onNestedPreScroll 实现的,所以要想办法触发这个方法。通过源码可以知道,onNestedPreScroll 是在 dispatchNestedPreScroll 里调用的,前提是 startNestedScroll 为 true。所以可以这样触发:

recyclerView.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, TYPE_TOUCH);recyclerView.dispatchNestedPreScroll(0, dy, new int[2], new int[2], TYPE_TOUCH);

最终 onStopNestedScroll 的完整代码如下:

@Override

到这里,自定义 Behavior 就算完成了。

效果

看一下最终的效果:


这种实现方式的优点是代码量少,用起来方便。使用了 MaterialCalendarView 并且没有修改它的源码,意味着支持它的所有功能。

希望通过本文,大家对 Behavior 有一个大概的了解。

项目地址:https://github.com/NanBox/NestedCalendar

大家都在看

Android防护相关知识点扫盲

怎样在Android面试中聊聊多线程

对于 Flutter 你应该了解的那些特性

RxJava 3.X来袭,请做好准备~

欢迎前往安卓巴士博客区投稿,技术成长于分享

期待巴友留言,共同探讨学习

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

  1. layui totalRow 多层嵌套json_鹏华资产40亿产品兑付追踪:中招嵌套结构 或踩雷非标-基金频道...

    经济观察报 记者 洪小棠工商银行(601398,股吧)代销,业绩比较基准,在投资者眼中看起来"稳稳的"资管产品,却发生了逾期事件. 10月份以来,有多位投资者向经济观察报记者反映自 ...

  2. layui totalRow 多层嵌套json_湖南全杨多层板价格

    湖南全杨多层板价格 家具板厂家对于家具板的干湿度的要求非常严格,并不是家具板越干燥越好,当然湿度大了容易发霉,干了容易开裂.通过这些方法,我们都可以判断出家具板的干燥程度如何,它会直接影响家具板*** ...

  3. 纵享丝滑滑动切换的周月日历,水滴效果,丰富自定义日历样式,仿小米日历(ViewDragHelper实现)...

    本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发 老规矩先贴效果图 github地址,觉得有帮助的可以给个 star 呗 github.com/idic779/mo ...

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. 神舟台式计算机图片,扩展性媲美台式机!神舟战神K780G拆机图赏
  2. ptyhon时间处理
  3. 鸿蒙升级变动,天天吹鸿蒙,视频向你展示鸿蒙升级后到底有什么变化
  4. nginx配置中proxy_redirect的作用(转)
  5. 【Time系列一】datetime的妙用
  6. 基于特征的文法分析以及概述自然语言处理
  7. ArrayList源码阅读
  8. 史上最全macos安装xgboost教程
  9. ambari 2.7 下安装httpfs
  10. 使用GoodSync备份服务器文件
  11. Miracle密码算法开源库(二)源码分析 :mralloc.c、mrarth0.c
  12. 第 4 篇、Linux操作基础 | 计算机组成
  13. 中国企业数智化价值不高,主要是因为三个问题
  14. TCL L32F2510E 安装第三方软件方法
  15. AI写作机器人-ai文章生成器在线
  16. 基于Java web的电动车销售平台 毕业设计-附源码201524
  17. 【C语言】运算符优先级
  18. 晶圆在低温探针台中的安装方式——Cyanoacrylate粘合剂
  19. Selenium.Chrome相关配置及用法
  20. Android 调用系统照相机拍照和录像

热门文章

  1. F9-sersync推送数据rsync拉取数据
  2. 黄聪:wordpress教程
  3. C#学习基本概念---xcopy(复制文件和目录树)
  4. thing php官网,Thinkphp5企业官网,php后台管理框架
  5. android 底部选项,Android:底部的选项卡
  6. golang slice分割和append copy还是引用
  7. 【BUG提交】freemarker 使用Struts2标签问题
  8. 最新pvz服务器补偿码,阴阳师:补偿来了!大量活动导致服务器崩溃,现已修复且下发补偿...
  9. centos6.3安装Samba及权限
  10. 到底他怎么赚钱了啊?看来看去也看不出他赚钱了,看来经济头脑有限啊