一款安卓日历(二)
2017-06-27 16:49
309 查看
接上篇博客一款安卓日历(一),这篇文章主要介绍日历滑动切换的细节。
项目地址:https://github.com/yannecer/NCalendar
月视图和周视图滑动切换,是自定义的
关于
这个方法在滑动时调用,用来判断月视图和周视图的切换,
这个方法是停止滑动手松开的时候调用,在这个方法中根据状态判断是上滚还是下滚,再根据已滑动的距离
在
这就是处理滑动切换视图的主要方法和逻辑,完成项目参见:https://github.com/yannecer/NCalendar
项目地址: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
相关文章推荐
- 自己实现一款安卓日历
- 一款安卓日历(一)
- iOS开发一款小巧简洁的日历控件
- 安卓精品源码,android日历在线选座微博主页抽屉菜单原生指纹源码
- 一款不错的JS版日历控件My97DatePi…
- My97 DatePicker一款好用的日历控件
- 自己整理的一款日历插件Calendar.js
- 为什么没有一款框架完善做到安卓、ISO、小程序、Web同步
- 一款灵活好用的日历控件Kalendae
- jquery.fullCalendar官方文档翻译(一款小巧好用的日程管理日历, 可集成Google Calendar)
- 安卓自定义日历选择器
- 手机同步专家是winmo123.com开发的一款运行在windows2000/xp/server2003/vista/server2008/7的一款手机同步软件y--p手机单机游戏下载安卓 免费
- 一款形似Win10日历风格的日期时间选择器
- My97 DatePicker一款好用的日历控件
- jquery.fullCalendar官方文档翻译(一款小巧好用的日程管理日历, 可集成Google Calendar)
- 安卓宝典(一款用于安卓开发学习的免费的安卓应用)
- 一款基于jQuery日历插件的开发过程
- C#安卓自学示例(3)日历
- 一款简单的安卓浏览器的设计
- Andy - 又一款速度流畅的免费安卓 Android 模拟器 (支持手机无线控制电脑模拟器)