专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
郭霖  ·  Android Studio 中的 ... ·  4 天前  
鸿洋  ·  AndroidManifest中配置的各种信息解读 ·  3 天前  
鸿洋  ·  画了10张图,带你搞定RecyclerVie ... ·  4 天前  
郭霖  ·  一文了解 Gradle 的文件api ·  1 周前  
鸿洋  ·  掌握这17张图,掌握RecyclerView ... ·  6 天前  
51好读  ›  专栏  ›  鸿洋

Android 仿小米开源日历 SuperCalendar

鸿洋  · 公众号  · android  · 2017-07-19 07:30

正文

本文作者


本文由神奇的小蘑菇投稿。

神奇的小蘑菇的博客地址:

http://www.jianshu.com/u/0c3ec6ad316e


1
简介


博主现在工作在一家教育公司,最近公司的产品狗扔过来一个需求,说要做一个可以周月切换的课表,可以展示用户在某一天的上课安排。接到这个任务之后我研究了很多的日历控件,并且抽出了一个calenderlib。


先看一下最后的项目中的效果:


  • 月模式



  • 周模式




看到本篇文章的同学估计也是实验课或者项目需求中需要一个日历表,当我接到这个需求的时候,当时脑子压根连想都没想,这么通用的控件,GitHub上一搜一大堆不是嘛。


可是等到真正做起来的时候,扎心了老铁,GitHub上的大神居然异常的不给力,都是实现了基本功能,能够滑动切换月份,找实现了周月切换功能的开源库很难。


终于我费尽千辛万苦找到一个能够完美切换的项目时,你周月切换之后的数据乱的一塌糊涂啊!!!


算了,自己撸一个!!!


项目链接 

https://github.com/MagicMashRoom/SuperCalendar


  • 如果你感觉到对你有帮助,欢迎star

  • 如果你感觉对代码有疑惑,或者需要修改的地方,欢迎issue


主要特性


  • 日历样式完全自定义,拓展性强

  • 左右滑动切换上下周月,上下滑动切换周月模式

  • 抽屉式周月切换效果

  • 标记指定日期(marker)

  • 跳转到指定日期


2
思路



  • Calendar的绘制由CalendarRenderer完成,IDayRenderer实现自定义的日期效果,CalendarAttr中存储日历的属性。

  • 首先看一下Calendar的代码,Calendar主要是初始化Renderer和Attr,然后接受View的生命周期

  • 在OnDraw的时候调用Renderer的onDraw方法,在点击事件onTouchEvent触发时,调用Renderer的点击处理逻辑



然后看一下CalendarRenderer的代码,Renderer承担了Calendar的绘制任务,首先renderer根据种子日期seedDate填充出Calendar包含的Date数据,calendar中持有一个6*7二维数组来存放日期数据。


然后在onDraw的时候通过IDayRenderer来完成对日历的绘制。当点击日期改变了日期的状态时,首先改变对应日期的状态State,然后重绘Calendar。



调用Renderer的draw方法时使用dayRenderer.drawDay(canvas , weeks[row].days[col]),dayRenderer是一个接口,在lib中有一个DayView 的抽象类实现该接口。 


其中的drawDay方法完成了对该天到calendar的canvas上的绘制



使用继承自ViewPager的MonthPager来存放calendar的view



使用CalendarViewAdapter为MonthPager填充calendar的实例



  • 日历在切换周月时切换日历中填充的数据

  • 在月模式切换成周模式时,将当前页的seedDate拿出来刷新本页数据,并且更新指定行数的周数据,然后得到seedDate下一周的周日作为下一页的seedDate,刷新下一页的数据,并且更新指定行数的周数据。上一页同理

  • 也是说假设我当前选择的是6月12号周日,处于日历的第二行,也是说下一页的seedDate是6月19号,然后刷新6月19号所在周的数据到选定的第二行。

  • 当切换周月时,把三页的数据都会重新刷新一遍,以保证数据的正确性。




使用CoordinateLayout的特性来做周月模式切换


(1)RecyclerViewBehavior



(2)MonthPagerBehavior 当recyclerView滑动式,MonthPager做相应的变化。



使用IDayRender来实现自定义的日历效果


DayView实现IDayRenderer,我们新建一个CustomDayView继承自DayView,在里面作自定义的显示



3
 使用方法


(1)XML布局


新建XML布局


RecyclerView的layout_behavior为com.ldf.calendar.behavior.RecyclerViewBehavior



(2)自定义日历样式


新建CustomDayView继承自DayView并重写refreshContent 和 copy 两个方法



新建CustomDayView实例,并作为参数构建CalendarViewAdapter



(3)初始化View


目前来看 相比于Dialog选择日历 我的控件更适合于Activity/Fragment在Activity的onCreate   或者Fragment的onCreateView  你需要实现这两个方法来启动日历并装填进数据



使用此方法回调日历点击事件




使用此方法初始化日历标记数据




使用此方法给MonthPager添加上相关监听




重写onWindowFocusChanged方法,使用此方法得知calendar和day的尺寸



大功告成,如果还不清晰,请下载DEMO


4
Download


Step 1. Add it in your root build.gradle at the end of repositories:


allprojects {
    repositories {
    ...
    maven { url 'https://www.jitpack.io' }
    }
}


Step 2. Add the dependency


dependencies {
    compile 'com.github.MagicMashRoom:SuperCalendar:v1.3.1'
}


如果你有想学习的文章直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递文章链接即可。


欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号: