自己实现一款安卓日历

${website.getHeaderOriginal(${article.taxonomyName})}

近日··|,苹果公司宣布··|,自7月18日至24日··|,凡在有银联云闪付标识的指定商铺··|,使用ApplePay来支付··|,即可享受低至5折优惠··|,以及高达50倍银行信用卡积分奖赏··|--。此次活动··|,除了数十家线下实体门店外··|,还有京东、携程等电商参与··|--。不过专家认为:“最好的时机已经过去了··|,微信和支付宝已经全面占领了中国的移动支付市场··|--。在中国··|,苹果支付用户的活跃度并不高··|--。”

明天就是周末了··|,在这个高温天气下··|,大家尽可能地还是少出门··|,以防中暑··|--。提前祝大家周末愉快!

本篇是 yannecer 的第二篇投稿··|,分享了一个日历开源项目··|,效果很不错··|,希望大家喜欢!

yannecer 的博客地址:

http://blog.csdn.net/y12345654321

最近写了一款日历··|,包含周日历、月日历以及滑动切换视图··|,先上效果图:

项目主要用到了自定义View··|,ViewPager··|,RecyclerView 和 NestedScrollingParent··|--。

本篇文章主要说一下月日历数据、月视图绘制以及点击日期的实现··|--。

数据部分··|,网上能找到比较完整的工具类··|,主要是根据本月和上月的天数以及本月第一天是周几来计算··|--。

首先计算上月日期: 由本月的第一天是周几和上个月的天数··|,得出上月的日期的显示

再计算本月日期:本月内的数据根据该月的天数跑循环··|--。

再计算下月计算上月日期的显示:下月的天数显示可以看本月最后一天是周几··|,根据距离一周最后一天的间隔天数··|,从1开始直接加上就可以了··|--。

这里要分情况了··|,有的月份跨5个周··|,有的月份能跨6个周··|--。计算上没有区别··|,但是显示的时候会有区别··|,为了简单··|,统一成6周··|,共42个元素··|,一月多余的用下月日期补充··|--。日期计算肯定使用

joda-time

https://github.com/JodaOrg/joda-time

天数、月份、年份计算都非常简单··|,有一点··|,这个库每周是周一开始的··|,周日历要注意一下··|--。

一月的数据:

这里简化了操作··|,项目中我把每个数据都转化成了 joda-time 中的 DateTime对象··|,方便后面操作··|--。

数据有了··|,接着就是绘制这些数据··|--。

MonthView 继承于 View··|,重写 onDraw(canva)方法··|--。首先在构造方法中根据颜色和字体大小初始化画笔:

接着就是在 onDraw(canva)方法 中绘制··|--。

我们先考虑一下我们都需要做哪些事情··|--。需要绘制公历、农历、小圆点、选中的圆环包括后面的点击操作··|,这些元素确定位置都需要一个矩形(Rect),那么就可以先在这个 View 里面绘制42个矩形··|--。四个点确定一个矩形··|,可以在纸上画一下大致的图案··|,大致画个一两行矩形··|,应该就找到规律了··|,感觉有点像以前上学时做的找规律的数学题··|--。

6行7列的一个矩形阵

有了这42个矩形··|,我们做后面的事情就简单了··|--。

绘制文字 canvas.drawText() 会发现··|,可能会出现文字不在矩形的中心··|,解决办法参看这篇博客

Android Canvas drawText实现中文垂直居中

http://blog.csdn.net/hursing/article/details/18703599

我们需要在绘制的循环里面要判断这些内容:

1、是不是本月的数据(用颜色区分本月和其他月的数据)

2、是不是今天

3、有没有选中的日期

4、显示不显示农历

其中今天和选中的日期用圆环表示··|,就需要在当天和选中的日期的矩形中绘制圆环··|--。已今天为例:

里面的一些工具类可参见文末项目地址··|--。

点击操作使用了 GestureDetector··|,这个类里面已经定义好了单级··|,双击··|,长按等操作··|,只需要我们重写相应的方法就可以··|,不用我们在去定义一个点击操作了··|--。

重写 MonthView 的 onTouchEvent(MotionEvent event)方法··|,交给 GestureDetector 处理

触摸事件交给 GestureDetector··|,当发生单击时··|,循环刚才绘制文本时的矩形··|,根据用户点击的XY坐标值判断是在哪个矩形内··|,我们就知道用户点击的是哪个日期了··|--。

里面写了一些回调··|,方便在 ViewPager 中跳转到相应的月份··|--。剩下的操作放到了 ViewPager 中完成··|,如果不是本月就跳转再设置选中的日期··|,如果是本月··|,就直接设置选中的日期:

在 doClickEvent(DateTime dateTime, int currentItem)方法 中··|,得到当前的 MonthView ··|,设置选中日期 monthView.setSelectDateTime(dateTime); 

而在 setSelectDateTime(DateTime dateTime) 中就是赋值和重绘页面:

这样在 onDraw(Canvas canvas) 中 mSelectDateTime!=null··|,就会绘制选中的圆环了··|--。

MonthView 没有重写 onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法··|,是因为这个 MonthView 是放在继承自 ViewPager 的 MonthCalendar 中使用的··|,只需在布局文件中设置 MonthCalendar 的 layout_width 和 layout_height 即可:

月视图和周视图滑动切换··|,是自定义的 MWCalendar 继承 LinearLayout··|,实现了 NestedScrollingParent接口··|,消费了 RecyclerView 的滑动距离··|,实现整体上滑··|,在滑动过程中根据条件判断是否显示周视图 WeekCalendar··|,用 OverScroller 实现滚动··|--。

关于 NestedScrollingParent 和 RecyclerView 的嵌套滑动··|,网上已经有比较详细的资料··|,这里不再复制粘贴··|,只讲一下实现细节··|,我主要参考了Hongyang的照片文章

Android NestedScrolling机制完全解析 带你玩转嵌套滑动

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

MWCalendar 是一个继承 LinearLayout··|,并实现 NestedScrollingParent 的容器··|,里面包含了 一个月视图 MonthCalendar 和 一个RecyclerView··|,WeekCalendar 是在 xml 加载完后以参数的方式传进去的··|,目的是为了使 MWCalendar 和 WeekCalendar 同在一个 RelativeLayout 中方便处理切换.

RecyclerView 向上滑动时··|,让 NestedScrollingParent 消耗掉 RecyclerView 的上滑距离··|,当向上滑动到只剩一个行高的时候··|,NestedScrollingParent 停止滑动··|,由 RecyclerView 继续滑动··|--。这里主要说 onStartNestedScroll(),onStopNestedScroll(),onNestedPreScroll() 和 onMeasure() 这四个方法··|--。

这个方法在滑动时调用··|,用来判断月视图和周视图的切换··|,dy>0 向上滑··|,且滑动距离 getScrollY()

这个方法是停止滑动手松开的时候调用··|,在这个方法中根据状态判断是上滚还是下滚··|,再根据已滑动的距离 getScrollY() 和总的滑动距离得到需要利用 mScroller 滚动的距离··|--。

computeScroll() 方法··|,在执行 mScroller.startScroll() 后调用··|,实时调用并绘制界面··|,所以可以在这个方法中判断周视图和月视图哪个应该显示··|--。

在 NestedScrollingParent 中如果不重写 onMeasure()方法··|,会出现上滑的过程中··|,下面的部分是空白的··|,原因是 整体View 测量的时候··|,测量的结果适应屏幕的大小··|,在上滑的过程中并没有重新测量··|,上滑的时候 整体View 一起整体上滑··|,View 的高度还是那么高··|,向上滑出一部分··|,下面的就变成空白了··|--。

所以我们需要做的就是在 View 测量的时候··|,给 RecyclerView 加高··|,这样上滑的时候也是正常显示··|,这个加高不是随便加的··|,必须是停止滑动的时候正好能显示 RecyclerView 的全部数据··|,这样就可以计算得到··|,加高的部分是正常的高度减去上面一行的高度··|,强行把 RecyclerView 加高已补充上滑出去的那部分视图··|--。

完整项目参见:

https://github.com/yannecer/NCalendar

每天学习累了··|,看些搞笑的段子放松一下吧··|--。关注最具娱乐精神的公众号··|,每天都有好心情··|--。

如果你有好的技术文章想和大家分享··|,欢迎向我的公众号投稿··|,投稿具体细节请在公众号主页点击“投稿”菜单查看··|--。

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

${website.getFooterOriginal(${article.taxonomyName})}

发布者 :利升国际官网_利升国际官方网站_利升国际唯一网址 - 分类 利升国际娱乐官网