美文网首页
记一次CATextLayer的使用心得

记一次CATextLayer的使用心得

作者: flightlessBirdT | 来源:发表于2018-09-06 16:40 被阅读81次

今天优化代码的时候发现了一个好玩的事情。

需求是实现一个头部显示value值的Slider控件。这个Slider我们是自己绘制的一个UIControl对象,它的trackline和thumbIcon都是我们用layer绘制上去的,因为Calayer本身具有隐性动画,所以最后的效果和系统几乎是完全一致。

一开始的时候,我就直接用UILabel来绘制这个value。然后将label的size,font以及color等属性暴露给调用者,后来想想size直接放在外面不大好,毕竟别人想调用一个可以显示数值的Slider还需要关心label的大小?

于是就在实现文件中声明了一个变量,给定了一个宽度(一个我认为足够大的值),但是因为字体的大小不固定,所以label的高度没法确定。一开始想的是在font的set方法中用[valueLabel sizetofit]来计算出label的height。后来我查到了一个UIFont的属性lineHeight,lineHeight可以根据不同font值计算出合适的高度,这个值你只需要调用lineHeight的getter方法就可以拿到了,不用计算,非常方便。例如:

UIFont *font0 = [UIFont systemFontOfSize:15];
UILabel *label0 = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, font0.lineHeight;)];

UIFont *font1 = [UIFont systemFontOfSize:25];
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, font1.lineHeight)];

这样高度的问题是解决了,但是调试的时候发现动画有问题。

因为要实现一个thumb顶部显示滑动值的文本效果,且希望当其他操作事件更改了滑动值的时候,Slider上需要有一个滑动的动画,thumb自然没有问题,但是对于UILabel来说,我尝试了UIView的基本动画,通过[CATransition animationDuration]拿到Calayer的隐式动画时间来设置UIView的显性动画。但是效果看起来不大好。你会发现,UIView动画的执行会比Calayer稍微慢了那么一点点。整个效果看起来就会有点不连续的感觉。

解决这个问题有两种思路:

  1. 研究Calayer隐式动画的曲线 找出和UIView动画的区别 然后解决
  2. 换掉UILabel 用CATextLayer来绘制文本

我觉得1的复杂度有点深,所以选择了2。不过关于CATextLayer,也是有一些坑的,花了我快半个小时才将这个效果弄好。

首先CATextLayer的几个属性比较特别:

  • CATextLayer的string属性是一个id类型,但是注释中明确的告诉你,要渲染的文本应该是NSString或NSAttributedString中的一种类型。
/* The text to be rendered, should be either an NSString or an
 * NSAttributedString. Defaults to nil. */

@property(nullable, copy) id string;
  • CATextLayer的font属性是一个CFTypeRef类型。你可以传入一个CTFontRef或者CTFontRef类型,或者直接传入一个字体的名称。默认是Helvetica。font属性仅仅用于当字符串类型是NSAttributedString时。
/* The font to use, currently may be either a CTFontRef, a CTFontRef,
 * or a string naming the font. Defaults to the Helvetica font. Only
 * used when the `string' property is not an NSAttributedString. */

@property(nullable) CFTypeRef font;
  • CATextLayer的fontSize是一个CGFloat类型
/* The font size. Defaults to 36. Only used when the `string' property
 * is not an NSAttributedString. Animatable (Mac OS X 10.6 and later.) */

@property CGFloat fontSize;
  • foregroundColor用于绘制text的颜色,默认是不透明的白色,仅仅用于string不是一个NSAttributedString类型时
/* The color object used to draw the text. Defaults to opaque white.
 * Only used when the `string' property is not an NSAttributedString.
 * Animatable (Mac OS X 10.6 and later.) */

@property(nullable) CGColorRef foregroundColor;
  • text的绘制位置,居中,居右等,类似于UILabel的textAlignment
/* Describes how individual lines of text are aligned within the layer
 * bounds. The possible options are `natural', `left', `right',
 * `center' and `justified'. Defaults to `natural'. */

其次换成了CATextLayer之后,我将font和fontSize以及foregroundColor属性暴露了出去,因为之前可以通过UIFont的lineHeight属性直接拿到UILabel对于不同字体自适应的高度值,所以这里没有用UIFont后,就换成了sizeWithAttributes:或者sizeWithFont:方法来搞定。

后来codeReview的时候,我觉得完全可以和以前一样,直接将UIFont和UIColor暴露给外部,因为在UIFont的set方法中,通过CGFontCreateWithFontName((__bridge CFStringRef)labelFont.fontName)labelFont.pointSize就可以拿到对应的CATextLayer的font和fontSize的属性,内部声明两个变量记录就好了。因为调用者其实应该是更熟悉UIFont的,而且只传一个属性简便的多。对于UIColor,set方法中取出它的CGColor就好,之前设置的暴露参数都不用修改,只需要内部做一下改动。

相关文章

网友评论

      本文标题:记一次CATextLayer的使用心得

      本文链接:https://www.haomeiwen.com/subject/dkixgftx.html