原标题:仿小米日历 纵享丝滑切换的周月效果

如果你正在搞一个自动打包方案,可以学习下~

十分钟快速集成美团多渠道打包(原创)

https://www.jianshu.com/p/332525b09a88

本文作者

作者:艾米1

链接:

https://juejin.im/post/5a631efd6fb9a01ca8720f80

本文由作者授权发布。

1

概述

老规矩先贴效果图

顶部定制可切换~这里省略了一张图~

github地址,觉得有帮助的可以给个 star 呗

https://github.com/idic779/monthweekmaterialcalendarview

添加依赖

compile 'com.github.idic779:monthweekmaterialcalendarview:1.5'

具体如何使用看这里

https://github.com/idic779/MonthWeekMaterialCalendarView/blob/master/README.md

2

这个库可以做什么

这个库可以做什么?

可以控制是否允许左右滑动,上下滑动,切换年月

流畅的上下周月模式切换

自定义日历样式

基于material-calendarview 这个库实现,可以根据需求定制效果 https://github.com/prolificinteractive/material-calendarview

之前开发任务中有涉及到年月日日历的切换效果,由于是需要联动,想到的方向大概有3种,要么通过处理view的touch事件,要么是通过自定义behavior去实现,要么是通过ViewDragHelper这个神器去实现,网上比较多的是通过自定义bahavior去实现,本文使用的是第三种方法,实现的是一个可高度定制自由切换的周月日历视图,提供一种思路去实现页面联动效果。

3

实现

3.1 准备

由于重点实现的是年月切换的效果,本来想着说可以自己写一个日历组件然后再加上ViewDragHelper,应该可以实现周月联动的效果吧?

后面想了想,重点在切换那就干脆直接找个开源库稳定性好点的日历组件,所以用https://github.com/prolificinteractive/material-calendarview快4000start的库吧,ViewDragHelper,作为一个神器可以做很多的事情,官方的DrawerLayout ,BottomSheetBehavior用他来实现,为什么用它?

对于拖动某个View,如果是自己去重写touch事件的,计算滑动距离再去移动View会需要处理比较多繁琐的代码去实现。如果我们用ViewDragHelper的话能很轻易的实现这样的效果。

简单的介绍下ViewDragHelper

ViewDragHelper helper= ViewDragHelper.create( this, 1.0f, newViewDragHelper.Callback() {

@Override

publicbooleantryCaptureView(View child, intpointerId){

returntrue;

}

@Override

publicintclampViewPositionHorizontal(View child, intleft, intdx)

{

returnleft;

}

@Override

publicintclampViewPositionVertical(View child, inttop, intdy)

{

returntop;

}

@Override

publicintgetViewHorizontalDragRange(View child){

returnsuper.getViewHorizontalDragRange(child);

}

@Override

publicintgetViewVerticalDragRange(View child){

returnsuper.getViewVerticalDragRange(child);

}

@Override

publicvoidonViewPositionChanged(View changedView, intleft, inttop, intdx, intdy){

super.onViewPositionChanged(changedView, left, top, dx, dy);

}

@Override

publicvoidonViewReleased(View releasedChild, floatxvel, floatyvel){

super.onViewReleased(releasedChild, xvel, yvel);

}

});

tryCaptureView():如果返回true,则说明可以捕获该view,我们可以在这里设置捕获的条件

clampViewPositionHorizontal ()``clampViewPositionVertical(): 分别对child水平和竖直方向移动的边界进行控制,例如限制周月移动的距离可以在这里做处理

onViewPositionChanged() : 当child的位置发生移动时候会回调这个方法

onViewReleased():手指释放时候的回调

getViewHorizontalDragRange()``getViewVerticalDragRange():返回child横向或者纵向移动的范围,大于0才能捕获。

更多的可以参考鸿洋的Android ViewDragHelper完全解析 自定义ViewGroup神器

http://blog.csdn.net/lmj623565791/article/details/46858663

3.2 如何实现

既然选择ViewDragHelper要实现周月联动呢,我们来理一理要实现的效果,在月视图的时候,能够把下面的recyclerView上移拖到到周视图的高度,上移过程如果超过一定距离就默认滚动到周视图。 在周视图的的时候又能把recyclerView下移拖动到月视图的高度位置,下移过程如果超过一定距离就默认滚动到月视图。

3.2.1 整体分析

整个页面是由顶部的周名字的View、周模式的MaterialCalendarView、月模式的MaterialCalendarView和最下面的recyclerView组成 需要注意的是MaterialCalendarView 这个库原来是有周名字还有顶部显示日期的,需要注意的是这里稍微做了下修改把这些给隐藏掉了,具体可以看MaterialCalendarView.setTopbarVisible()。并且做了下修改增加了获得单行的高度方法MaterialCalendarView.getItemHeight() ,即为周模式时显示的高度。

3.3 具体实现

拖动前处理 整个页面只有recyclerView ,月模式下如果向上拖动时候如果recyclerView不是滚动到了顶部的话那么就不允许拖动,相关代码

@Override

publicbooleantryCaptureView(View child, intpointerId){

return!mDragHelper.continueSettling( true)

&&child == mRecyclerView && !animatStart

&& isAtTop(mRecyclerView) &&

!ViewCompat.canScrollVertically(mRecyclerView, - 1);

}

限制recyclerView移动的高度在周模式和月模式之间

@Override

publicintclampViewPositionVertical(View child, inttop, intdy){

//决定竖直方向上能移动的距离为 finalWeekModeHeight到finalMonthModeHeight

inttopBound = finalWeekModeHeight;

intbottomBound = finalMonthModeHeight;

intnewTop = Math.min(Math.max(top, topBound), bottomBound);

returnnewTop;

}

在onMeasure获得初始的一些数据值,包括周模式的高度,月模式的高度,最大移动的距离,单行的高度

@Override

protectedvoidonMeasure(intwidthMeasureSpec, intheightMeasureSpec){

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

calendarItemHight = mCalendarViewMonth.getItemHeight();

calendarWeekHight = calendarItemHight;

if(defaultStopHeight == 0) {

defaultStopHeight = getCurrentItemPosition(CalendarDay.today()) * calendarItemHight;

}

calendarMonthHight = mCalendarViewMonth.getMeasuredHeight();

weekViewHight = mTopWeekView.getMeasuredHeight();

finalMonthModeHeight = weekViewHight + calendarMonthHight;

finalWeekModeHeight = calendarItemHight + weekViewHight;

maxOffset = calendarMonthHight - calendarItemHight;

}

然后在onlayout()把布局里的View绘制到对应的位置上面

最大移动的距离defaultStopHeight在选中日期时候就会通过 getCurrentItemPosition()计算出它点击所在的行数再调用setStopItemPosition()就可以得到要停止下来的高度,

接下来说下最关键的地方既然是周月联动我们发现在拖动recyclerView视图的时候我们会不停回调onViewPositionChanged()这个方法,我们在这个方法里面就可以根据recyclerView移动的距离来移动对应的月视图.

//滑动处理

privatevoidHandlerOffset(View changedView, intleft, inttop, intdx, intdy){

//获取日历相对手指移动的相对距离 dy向上移动小于0

transY = transY + dy;

if(transY > 0) {

transY = 0;

}

if(transY < -calendarMonthHight - calendarItemHight) {

transY = -calendarMonthHight - calendarItemHight;

}

floatabstransY = Math. abs(transY);

if(dy < 0) {

//如果上滑动,并且滑向动的绝对值距离在超过calendarHight-defaultStopHeight

// 并且小于可以滑动的距离calendarHight-calendarItemHight之间的话

if(abstransY >= (calendarMonthHight - defaultStopHeight) && abstransY < calendarMonthHight - calendarItemHight) {

if(!animatStart) {

mCalendarViewMonth.setTranslationY(getOffset(( int) mCalendarViewMonth.getTranslationY() + dy, calendarItemHight - defaultStopHeight));

}

}

}

if(dy > 0) {

if(abstransY < maxOffset

&& currentMode.equals(Mode.WEEK)) {

mCalendarViewWeek.setVisibility(INVISIBLE);

}

if(abstransY < maxOffset) {

mCalendarViewMonth.setTranslationY(getOffset(( int) mCalendarViewMonth.getTranslationY() + dy, 0));

}

}

}

月视图的移动我们是通过setTranslationY来移动的,为了防止滑动时候过快通过getOffset()限制一下它滑动的最大距离。

在松开手指的时候我们在onViewReleased()做相关状态的改变,如果滑动的距离超过一定的值就把当前视图置为月模式还是周模式

@Override

publicvoidonViewReleased(View releasedChild, floatxvel, floatyvel){

intmoveY = finalMonthModeHeight - mRecyclerView.getTop();

//周模式距离滑动为一行的高度,超过就滑动到周位置

intweekdistance = calendarItemHight;

//最大滑动距离

intmaxDistance = calendarMonthHight;

if(currentMode == Mode.MONTH) {

//如果滑动距离超过当前选中项和最大滑动距离之间的距离

if(moveY > weekdistance && moveY < maxDistance) {

//变为周模式

setMode(Mode.WEEK);

} elseif(moveY <= weekdistance) {

//变为月模式

setMode(Mode.MONTH);

}

} else{

//周模式下距离顶部选中日期的距离小于最大滑动距离-10的话就让它变为月模式

if(moveY > maxOffset - 10) {

//变为周模式

setMode(Mode.WEEK);

} elseif(moveY <= maxOffset - 10) {

//变为月模式

setMode(Mode.MONTH);

}

}

}

需要注意的是在onInterceptTouchEvent()如果是月模式并且可以拖动的时候, 底部的recyclerView是不允许滑动的

if(currentMode == Mode.MONTH&& canDrag) {

setRecyclerViewCanScroll( false);

}

4

还可以怎么用

接下来说下你可以怎么去定制?如果你想替换项目中的月和周视图的话,不想用Material-calendarview 。

https://github.com/prolificinteractive/material-calendarview

很简单,只需要你自己的周月视图必须有一个方法获得单行日历的高度(例如我的库中的MaterialCalendarView.getItemHeight() ),然后把这个月视图和周视图,分别在MonthWeekMaterialCalendarView里面按照顺序放到对应位置即可。

然后再setListener()里面设置相关的回调处理,例如日期选中或者月份切换的回调等。

好的大工告成。

源码地址:

https://github.com/idic779/monthweekmaterialcalendarview返回搜狐,查看更多

责任编辑:

android 仿美团日历,仿小米日历 纵享丝滑切换的周月效果相关推荐

  1. 让你的小米5纵享丝滑,可能是最快的小米5rom

    小米5刷原生7.1.1 ROM.配合xposed框架模块,非常的流畅!用纵享丝滑形容真不为过. 此标题是根据我的多次刷机实践得来的结果.话不多说先上几张GIF. 下面我上资源和教程: 首先手机要解锁刷 ...

  2. 纵享丝滑滑动切换的周月日历,可流畅滑动高度定制,仿小米日历,基于 material-calendarview

    monthweekmaterialcalendarview 项目地址:idic779/monthweekmaterialcalendarview  简介:纵享丝滑滑动切换的周月日历,可流畅滑动高度定制 ...

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

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

  4. 纵享丝滑滑动切换的周月日历,水滴效果,丰富自定义日历样式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QF0ojEiz-1650020556182)(https://user-gold-cdn.xitu.io/2018/2/ ...

  5. android 涂鸦 卡顿,涂鸦框架的优化——解决绘制时的卡顿问题,纵享丝滑

    前言 V5.5: 增加优化绘制的选项,可优化绘制速度和性能,纵享丝滑. boolean optimizeDrawing = true; // 是否优化绘制,建议开启,可优化绘制速度和性能. Doodl ...

  6. 推荐 9 个 GitHub 上练手项目(在线考试、仿美团、仿抖音、仿B站、仿头条...)

    GitHub项目推荐 推荐的这几个 GitHub 项目并不是简单的 XX 管理系统,我会从下面这些方向推荐几个入门级别但是不那么 Low 的项目. "我自己是一名从事了6年web前端开发的老 ...

  7. 为什么ios系统比android系统流畅,为什么iOS系统能做到流畅丝滑,而Android系统却永远做不到?...

    原标题:为什么iOS系统能做到流畅丝滑,而Android系统却永远做不到? 现在的智能手机,已经分为安卓手机阵营和苹果手机两种,也就是说市面上的智能手机要么搭载Android系统要么搭载苹果的iOS系 ...

  8. 仿魅族日历,乐视日历,小米日历等效果

    http://download.csdn.net/detail/floraily/9683549

  9. android 仿美团联动,仿美团弹出分类选择框(左右两个listview联动)

    [实例简介] 左边产品大类,选择某一类后在右边展开其中的小类,用两个listview联动实现 [实例截图] [核心代码] 1535269showPopWindow └── showPopWindow ...

  10. Android 软键盘丝滑切换(一)

    在开发app中,软键盘弹出会有卡顿,闪一下的现象,会影响体验效果.为了实现微信软键盘与表情面板流畅的切换效果,查看了好多例子,查阅的很多资料,换了几种实现方式,都达不到流畅切换的效果,最终结合资料,参 ...

最新文章

  1. 选择大于努力?某程序员吐槽:自己毕业去了百度,技术不如自己的室友去了快手,如今股票1500万!...
  2. 苹果APPLE最新MI芯片笔记本安装第三方内核扩展
  3. Redis --数据类型 [1]
  4. mysql date compare_SQLDataCompare下载
  5. 20以内的素数编码C语言,用C语言 输出100以内的素数,
  6. python字典数据类型笔记_python笔记2-数据类型:元组、字典常用操作
  7. 贴吧备份到本地浏览html,获取贴吧对应页html及写入文件
  8. java socket php_Web架构(二)PHP Socket与Java ServerSocket交互
  9. 百度排名批量查询_一篇文章告诉你如何快速实现百度霸屏?
  10. systemctl重新加载_CentOS7利用systemctl添加自定义系统服务【转】
  11. 贝多芬交响曲全集(转)
  12. Pytorch聊天机器人
  13. 几何学在计算机中的应用,探析坐标几何的应用意义及其在计算机中的实现
  14. solr7.4-DIH
  15. linux 在沙盒中运行,Linux容器的细粒度沙盒策略执行方法与流程
  16. 交友项目【手机号登录注册功能】实现
  17. android拼图游戏报告,拼图游戏报告分析报告.doc
  18. 日知录(15):记药盒的串口通信
  19. 计算机编程语言排行榜—TIOBE世界编程语言排行榜(2020年11月份最新版)
  20. QPSO---收缩扩张系数的选择方案(未完待续)

热门文章

  1. php 全等 性能,在PHP中,相等(==)和全等(===)的含义是一样的。
  2. 万恶之源的hello world
  3. 高质量WordPress下载站模板5play主题源码
  4. 解决visio对象在word中显示不全的问题
  5. 微信小程序获取手机号码(仅前端部分
  6. Apple Store的错误
  7. PHP编程中 @符号的作用
  8. 奥城大学计算机科学专业,我是学工程专业本科毕业,托福70分,GRE1020分,都很低,我想去美国留学马上走,...
  9. mysql左连接和右连接_MYSQL 左连接与右连接
  10. 架构师如何练习演讲和表达能力