最近无聊刷手机的时候, 发现小米时钟的嵌套滑动很有意思, 就试着做了下
先上对比图:

分析下小米时钟的滑动

  • 闹钟列表 向上滑动时, 时钟面 透明度上升, 快到最大滑动时逐渐显示数字时钟.

在闹钟列表向上滑动的过程中,时钟面和数字时钟的位置看起来并没有发生变化, 而且时钟面能分发到滑动信息
如果尝试用 AppBarLayout + appbar_scrolling_view_behavior , 会出现滑动信息被消耗的情况, 尝试滑动 AppBarLayout 的子view会使整体滑动,
像这样:

自定义behavior

如果用 AppBarLayout 不方便, 那我们就自己来, 先上布局:

<FrameLayout 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:background="@android:color/white"tools:context="com.jimzjy.demo.MainActivity"><com.jimzjy.networkspeedview.NetworkSpeedViewandroid:id="@+id/main_network_speed_view"android:layout_width="match_parent"android:layout_height="@dimen/top_size"android:background="@color/colorPrimary"app:speed_unit="Auto_same"/><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><Viewandroid:id="@+id/main_scrim_view"android:layout_width="match_parent"android:layout_height="@dimen/top_size"android:background="@color/colorPrimary"android:alpha="0"app:layout_behavior=".DeviceRecyclerScrollerBehavior"/><android.support.v7.widget.RecyclerViewandroid:id="@+id/main_recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/white"android:layout_marginTop="@dimen/top_size"app:layout_behavior=".MeasureRecyclerBehavior"tools:listitem="@layout/rv_item"tools:itemCount="7"/></android.support.design.widget.CoordinatorLayout>
</FrameLayout>
复制代码

Framelayout中分了两个层次, 底层 NetworkSpeedView ,再 CoordinatorLayout . CoordinatorLayout 中用一个 View 遮住
底层的 NetworkSpeedView , 一开始让 View 的 alpha 值为0, 在 CoordinatorLayout 向上滑动的过程中, 提高 alpha 值, 这样就达到了近似 NetworkSpeedView 透明度改变的效果.
为了方便看, 顶部的 text 现在还不添加

关于嵌套滑动和自定义Behavior可以看
一点见解: Android嵌套滑动和NestedScrollView
CoordinatorLayout高级用法-自定义Behavior

Behavior :

class DeviceRecyclerScrollerBehavior(ctx: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<View>(ctx, attrs) {//顶部文字的高度private val mTopText = ctx.resources.getDimension(R.dimen.top_text_size)//总共需要上移的高度private val mTotalOffsetY = ctx.resources.getDimension(R.dimen.top_size) - mTopTextoverride fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: View, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {return (axes and ViewCompat.SCROLL_AXIS_VERTICAL) != 0}override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: View, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {/*判断是否要消耗 dydy > 0 上移, dy < 0 下移向上,如果已经达到向上最大滑动/向下,内部的 RecyclerView 还可以下滑 . 则不消耗*/val toCost = (dy > 0 && coordinatorLayout.scrollY < mTotalOffsetY)|| (dy < 0 && coordinatorLayout.scrollY > 0 && !target.canScrollVertically(-1))if (toCost) {coordinatorLayout.scrollBy(0, dy)//改变透明度child.alpha = coordinatorLayout.scrollY / (mTotalOffsetY - mTopText)consumed[1] = dy}}
}class MeasureRecyclerBehavior(ctx: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<RecyclerView>(ctx, attrs) {private val mTopText = ctx.resources.getDimension(R.dimen.top_text_size)override fun onMeasureChild(parent: CoordinatorLayout?, child: RecyclerView?, parentWidthMeasureSpec: Int, widthUsed: Int, parentHeightMeasureSpec: Int, heightUsed: Int): Boolean {//测量大小, 让 RecyclerView 的高度 = CoordinatorLayout的高度 - 顶部text的高度child?.measure(parentWidthMeasureSpec, View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(parentHeightMeasureSpec) - mTopText.toInt(), View.MeasureSpec.EXACTLY))return true}
}
复制代码

通过 MeasureRecyclerBehavior 测量 RecyclerView 的高度(设定准确值), 而不是根据父布局, 就不会出现向上滑动时感觉底下少一块的情况,像这样:

DeviceRecyclerScrollerBehavior 会设置消耗滑动距离, 以及修改透明度

处理顶部的 TextView

因为顶部的 TextView 不随着 CoordinatorLayout 的滑动而滑动, 所以把顶部的 TextView 放到 FrameLayout(直接在 Coordinator上面) :

<FrameLayout xmlns:android><com.jimzjy.networkspeedview.NetworkSpeedView/><CoordinatorLayout/><TextViewandroid:id="@+id/main_top_text"android:layout_width="match_parent"android:layout_height="@dimen/top_text_size"android:gravity="center_vertical|center_horizontal"android:text="100 | 100"android:textSize="22sp"android:textColor="@android:color/white"android:alpha="0"/>
</FrameLayout>
复制代码

因为 TextView 不是 CoordinatorLayout 的子 View , 所以就不能通过 behavior 来设置它的 alpha 了.
那就通过设置监听, 每次滑动都会调用 CoordinatorLayout 的 scrollTo() ( scrollBy() 内部调用的也是scrollTo() ), 所以继承 CoordinatorLayout , 覆写 scrollTo() , 写个回调监听就好了.

class ReCoordinatorLayout(ctx: Context, attrs: AttributeSet?) : CoordinatorLayout(ctx, attrs) {private val mTopText = ctx.resources.getDimension(R.dimen.top_text_size)private val mTop = ctx.resources.getDimension(R.dimen.top_size)private val mTopOffsetY = mTop - mTopTextprivate val mAlphaChangeStart = mTopOffsetY - mTopTextprivate var mShowText: ((alpha: Float) -> Unit)? = nullconstructor(ctx: Context) : this(ctx, null)override fun scrollTo(x: Int, y: Int) {var sY = y//防止滑动过多when {sY < 0 -> sY = 0sY > mTopOffsetY -> sY = mTopOffsetY.toInt()}if (sY != scrollY) super.scrollTo(x, sY)when {sY > mAlphaChangeStart -> mShowText?.invoke((sY - mAlphaChangeStart) / mTopText)sY <= mAlphaChangeStart -> mShowText?.invoke(0f)}}//设置回调函数fun setShowtext(showText: (alpha: Float) -> Unit) {this.mShowText = showText}
}
复制代码

在 scrollTo 中调用回调函数 mShowText() 来设置 alpha 值.

设置回调函数

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)... ...main_coordinator_layout.setShowtext { main_top_text.alpha = it }}
复制代码

总结

GitHub地址
总的来说实现的还是比较粗糙的, 但是这样非常简单

Android仿小米时钟嵌套滑动(NestedScroll, 自定义behavior)相关推荐

  1. android高仿小米时钟,Android小米时钟 Android仿小米时钟效果

    想了解Android仿小米时钟效果的相关内容吗,jane_dxj在本文为您仔细讲解Android小米时钟的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Android,时钟,下面大家一起来 ...

  2. Android仿小米时钟

    最近在学自定义View,看到小米时钟这个效果,很想去了解一下是界面是如何绘制以及秒针,分针,时针是如何转动的,还有那个弧形颜色渐变效果.这是我参照Github上的效果弄的,Github地址:高仿小米时 ...

  3. Android仿豆瓣FM卡片滑动

    最近公司项目要做一个跟豆瓣FM卡片式滑动的效果,看看效果图: 卡片的滑动和伸缩功能都已做好测试跟豆瓣FM 1:1还原 package org.android.mygdttst.douban;impor ...

  4. android 仿小米日历 周视图 月视图切换

    android 仿小米日历,周视图左右滑动,月视图左右滑动,周视图月视图无缝切换: http://download.csdn.net/detail/chen352602412/9556162 插播广告 ...

  5. Android仿抖音上下滑动切换视频

    Android仿抖音上下滑动切换视频 https://www.jianshu.com/p/af9c0e46725d  自从各大直播平台可以滑动切换直播间后,公司就出了一大波需求,还要配合各种收费,各种 ...

  6. android高仿小米时钟,Android高仿小米时钟

    今日科技快讯 昨日,小米科技正式发布首款自主芯片松果澎湃S1和搭载澎湃S1芯片的小米5C手机.从立项做到量产结束,小米芯片用了28个月.S1的CPU为八核64位处理器,主频达2.2GHz,处理高计算量 ...

  7. android仿小米日历,实现一个仿小米日历控件

    先看效果图: 效果图 根据效果,我们可以看到,要实现该控件,需要具备: 容器以及触摸事件处理 周日历布局以及选择,切换上下周处理 月日历布局以及选择,切换上下月处理 首先说说容器 对于其他使用者来说, ...

  8. Android仿今日头条图片滑动退出效果

    资源下载(2C币) 逛CSDN的时候,看到几篇写仿今日头条图片滑动退出效果的文章,闲着无聊便想着也给自己项目加上,实现的思路有很多种,本着就近原则选了一篇与自己思路相近的文章结合自己的实践总结一下. ...

  9. android仿小米运动,仿小米运动的运动记录界面

    [实例简介] 仿小米运动的运动记录界面,可用. [实例截图] [核心代码] MISportsConnectWidget-master └── MISportsConnectWidget-master ...

最新文章

  1. vue 动态修改后端请求_vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单...
  2. 记录最近的一些遇到的前端面试题
  3. Python内存管理以及垃圾回收机制
  4. 【数据结构与算法】双链表V2.0的Java实现
  5. Java中一个线程只有六个状态。至于阻塞、可运行、挂起状态都是人们为了便于理解,自己加上去的。...
  6. visual studio 使用快捷方法2
  7. C++指针参数如何传递内存?
  8. 服务器设置系统盘分页,服务器设置系统盘分页
  9. Java核心技术 卷1
  10. SQL Server 数据库作业(备份、同步)
  11. NCE3.21 Danile Mendoza 丹尼尔.门萨多 -句子成分分析
  12. ios手机号和邮箱(支付宝账号)脱敏
  13. 关注IT精英:微利时代如何赚大钱 (转载)
  14. face to face
  15. SCI、EI论文检索,引用格式
  16. [AHK]为通达信画线工具中的文字注释功能增加热键
  17. 在3DMAX中为动画添加根骨骼运动
  18. 网络信息安全技术的学习感悟
  19. 怎样区分图片的实际像素、分辨率和尺寸大小
  20. 微信小程序上传图片到服务器总是失败_微信小程序上传图片过大导致请求失败的解决方法...

热门文章

  1. 区块链 10 年低谷与荣光
  2. matlab中desolve,MATLAB考试题的.doc
  3. 电子邮件是internet应用中最广泛的服务项目,通常采用的传输协议是?
  4. SAP-FICO-KSS2成本划分错误
  5. plantuml使用
  6. java导出pdf文件并下载_java根据模板生成pdf文件并导出
  7. Java中的Connection赋值为null与conn.close
  8. DOM第一天作业--世纪佳缘登录框--pink老师
  9. 【yolov5】检测效果测试
  10. oracle是否支持gb18030,将oracle字符集改成GB18030