CoreText初探——iOS日历的年历视图

独奏

技术分享|2014-11-3|最后更新: 2023-2-23|
type
status
date
slug
summary
tags
category
icon
password
最近的一个项目要实现一个类似iOS日历的效果,首页是一个年历,要显示每个月份的日期,如果有提醒任务的话需要加一个红圈提醒。
notion image
效果图
iOS的年历中每年都是一个3*4的格子,可以无限滑动的。首先想到的这里就是使用UICollectionView来实现,每年作为一个section,每个section有12个cell。
但是每个cell内要显示该月的日期,这里的布局就成了问题了。如果每个cell内使用lable来显示日期的话,一屏有12个cell就意味着要有365个lable,这么多view必然会对流畅性产生影响。所以最终决定只能使用CoreText来进行月cell内的日期布局了。下面是遇到的几个问题,一一说一下思路

文字纵向对齐

首先想到的问题就是文字对齐的问题,比如日期1、8、15、22、29要在一列上面对齐,最初的想法是使用等宽字体来显示,这样显示出来的效果就是1、8,15的1、22的第一个2、29的2对齐。但是观察iOS的日历发现其对齐是居中对齐的,也就是1、8是和15、22、29的中间对齐的,如图2。
notion image
图二
所以使用等宽字体是不行的,后来经过测试发现:一个空格的宽度恰好是数字宽度的一半。这样我们就可以通过空格控制文字的纵向居中显示了。
因此,文字的格式就变成了如下格式(-表示空格):
说明:
  • 四个空格表示两个数字字符
  • 7-就可以这种写法就可以让7在14的中间的上方
  • 每个日期之间间隔为两个空格——即一个数字的宽度

CoreText排版问题

文本格式问题解决了,接下来就是使用CoreText进行排版了。CoreText排版实际就是在- (void)drawRect:(CGRect)rect方法里面通过设置NSAttributedString的attribute属性进行控制文字格式的。关于这个的资料比较多,我就不详细说明了。下面只列举一下我用到的一些属性
我只是设置一下字体和行间距,至于NSAttributeString有哪些属性,可以再网上找到很全面的文档,这里就不列举了。

特殊日期标注

如[图一]所示,如果当前日期有事件,需要用红圈标注。这个显然是要获取到这个日期的文字所在位置的。先看代码
代码一
代码二
这里我把需要标注的日期统一加一个tagCharacter属性,来标注出来,然后再绘图的时候,逐字检查,如果发现这个属性,就计算这个文字的位置,在该位置画一个圆。这里要注意的就是由于日期的数字位数不同,所以根据位数计算圆的位置。因此我在添加属性的时候,属性值我给的就是数字位数

总结

以上问题就是我在做这个日历的年历视图时遇到的问题,实际上主要还是对CoreText的运用,由于这是本人第一次真正使用CoreText,所以题目就叫做《CoreText初探》,希望我的这篇总结能够对你有所帮助

参考