一款安卓日历(二)
来源:互联网 发布:java 多线程 编辑:程序博客网 时间:2024/06/15 23:29
接上篇博客一款安卓日历(一),这篇文章主要介绍日历滑动切换的细节。
项目地址:https://github.com/yannecer/NCalendar
月视图和周视图滑动切换,是自定义的MWCalendar
继承LinearLayout
,实现了NestedScrollingParent
接口,消费了RecyclerView
的滑动距离,实现整体上滑,在滑动过程中根据条件判断是否显示周视图WeekCalendar
,用OverScroller
实现滚动。
关于NestedScrollingParent
和RecyclerView
的嵌套滑动,网上已经有比较详细的资料,这里不再复制粘贴,只讲一下实现细节,我主要参考了Hongyang
的照片文章Android NestedScrolling机制完全解析 带你玩转嵌套滑动。
MWCalendar
MWCalendar
是一个继承LinearLayout
,并实现NestedScrollingParent
的容器,里面包含了一个月视图MonthCalendar
和一个RecyclerView
,WeekCalendar
是在xml
加载完后以参数的方式传进去的,目的是为了使MWCalendar
和 WeekCalendar
同在一个RelativeLayout
中方便处理切换,RecyclerView
向上滑动时,让NestedScrollingParent
消耗掉RecyclerView
的上滑距离,当向上滑动到只剩一个行高的时候,NestedScrollingParent
停止滑动,由RecyclerView
继续滑动。这里主要说onStartNestedScroll()
,onStopNestedScroll()
,onNestedPreScroll()
和onMeasure()
这四个方法。
@Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { boolean hiddenMonthCalendar = dy > 0 && getScrollY() < rowHeigh * 5; boolean showMonthCalendar = dy < 0 && getScrollY() >= 0 && !ViewCompat.canScrollVertically(target, -1); if (hiddenMonthCalendar || showMonthCalendar) { scrollBy(0, dy); consumed[1] = dy; } }
这个方法在滑动时调用,用来判断月视图和周视图的切换,dy>0
向上滑,且滑动距离getScrollY()<rowHeigh * 5(月视图共6个行高)
时,需要月视图向上滑,滑动距离为rowHeigh * 5
。
@Override public void onStopNestedScroll(View target) { int scrollY = getScrollY(); if (scrollY == 0 || scrollY == rowHeigh * 5) { return; } if (STATE == OPEN) { if (scrollY > 100) { startScroll(scrollY,rowHeigh * 5 - scrollY,300); } else { startScroll(scrollY, -scrollY, 300); } } if (STATE == CLOSE) { if (scrollY < rowHeigh * 5 - 100) { startScroll(scrollY, -scrollY, 300); } else { startScroll(scrollY, rowHeigh * 5 - scrollY, 300); } } } ----------- private void startScroll(int startY,int dy,int duration) { mScroller.startScroll(0, startY, 0, dy, duration); invalidate(); }
这个方法是停止滑动手松开的时候调用,在这个方法中根据状态判断是上滚还是下滚,再根据已滑动的距离getScrollY()
和总的滑动距离得到需要利用mScroller
滚动的距离。
@Override public void computeScroll() { int scrollY = getScrollY(); if (scrollY == 0) { STATE = OPEN; weekCalendar.setVisibility(INVISIBLE); } else if (scrollY == 5 * rowHeigh) { STATE = CLOSE; weekCalendar.setVisibility(VISIBLE); } else { int weekRow = monthCalendar.getCurrentMothView().getWeekRow(); weekCalendar.setVisibility(scrollY >= weekRow * rowHeigh ? VISIBLE : INVISIBLE); } if (mScroller.computeScrollOffset()) { scrollTo(0, mScroller.getCurrY()); invalidate(); } }
computeScroll()
方法,在执行mScroller.startScroll()
后调用,实时调用并绘制界面,所以可以在这个方法中判断周视图和月视图哪个应该显示。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); rowHeigh = monthCalendar.getRowHeigh(); ViewGroup.LayoutParams params = recyclerView.getLayoutParams(); params.height = getMeasuredHeight() - rowHeigh; }
在NestedScrollingParent
中如果不重写onMeasure()
方法,会出现上滑的过程中,下面的部分是空白的,原因是整体View
测量的时候,测量的结果适应屏幕的大小,在上滑的过程中并没有重新测量,上滑的时候整体View
一起整体上滑,View
的高度还是那么高,向上滑出一部分,下面的就变成空白了。所以我们需要做的就是在View
测量的时候,给RecyclerView
加高,这样上滑的时候也是正常显示,这个加高不是随便加的,必须是停止滑动的时候正好能显示RecyclerView
的全部数据,这样就可以计算得到,加高的部分是正常的高度减去上面一行的高度,强行把RecyclerView
加高已补充上滑出去的那部分视图。
这就是处理滑动切换视图的主要方法和逻辑,完成项目参见:https://github.com/yannecer/NCalendar
- 一款安卓日历(二)
- 一款安卓日历(一)
- 自己实现一款安卓日历
- 安卓日历
- 安卓日历
- 安卓自定义日历控件
- 安卓自定义日历控件
- 安卓、苹果日历同步
- 安卓自定义日历选择器
- 安卓自定义日历选择器
- JS日历(二)
- 安卓自定义日历滑动的日历控件
- 分享一款jquery日历控件(超赞)
- 一款安卓记账软件的开发
- outlook与安卓手机同步日历
- 安卓日历、时间弹出框
- 安卓简单日历的实现
- 安卓简单日历的实现
- Git配置多账号
- C++里仿函数的用法
- ORB特征检测算法
- mysql linux不区分大小写
- 单片机学习资料
- 一款安卓日历(二)
- TCP三次握手和四次挥手详解
- 创建swift颜色类
- js动态拼接标签,样式丢失的解决方法
- Java中System.currentTimeMills的几个常见用法
- sql查询重复数据
- 滑动监听,当上拉时上面标题栏逐渐显示出来
- 适配Android N (7.0)需要解决的问题汇总
- 安卓在布局中控件显示在最上层