使用CALayer将对angular横幅/徽章添加到UITableViewCell的angular落
我试图绘制装饰UITableViewCell在我的表视图与文字横幅看起来像一个邮票,对angular线在整个单元格的左上angular。
我可能完全在错误的地方做这个,但我重写-layoutSubviews
添加图层。 我尝试在-drawRect:
做这-drawRect:
但是当表格呈现时(即,图层在图像视图下方,随后添加图像视图),横幅最终由表视图的-drawRect:
覆盖。
我真的很难得到这个math正确的。 我计算过,假设条幅从单元的顶部开始40点,从左侧开始40点,正好在-45°处,斜边是56点。 所以我做了CALayer 56点宽,然后旋转它-45º,这是有效的。 问题在于细胞内的位置……它坐在牢房里,而不是靠在它的边缘上。
而不是我应用试验和错误,以得到这个在正确的地方,有人可以帮我的math? 显然我需要移动图层并旋转它。
感觉像anchorPoint是我需要在这里,但似乎实际上移动层,所以我必须错过(没有双关语的意思)。
- (void)layoutSubviews { [super layoutSubviews]; self.imageView.frame = CGRectMake(10, 10, 50, 50); if (self.hasBanner) { CALayer *banner = [CALayer layer]; banner.backgroundColor = [UIColor colorWithRed:.5f green:.5f blue:.5f alpha:1.f].CGColor; banner.frame = CGRectMake(0, 40-15, 56, 15); banner.anchorPoint = CGPointMake(0, 1); // this just makes it worse banner.transform = CATransform3DMakeRotation(-45.0 / 180.0 * M_PI, 0.0, 0.0, 1.0); [self.layer addSublayer:banner]; } }
图层应该去哪里?
我们来画一个图表:
我们可以走得更远,做点什么,但是我们在这里停下来。 很明显,横幅的中间点应该在(20,20)
。 我们可以告诉核心animation做到这一点。
定位图层
从四个单独的步骤来考虑它:
- 设置图层的大小
- 确定图层中的哪个点是方便的参考点
- 设置参考点的位置
- 围绕参考点旋转图层
这些对应于四个属性: bounds
, anchorPoint
, position
和transform
。
您不想触摸frame
属性,因为它的值是从 bounds
, position
, transform
和anchorPoint
派生的。 如果您尝试设置frame
,则CALayer将尝试反转transform
,将其应用于您指定的矩形,然后设置bounds
和position
。 这可能不会给你想要的结果,所以你最好完全忽略它 – 不要那么混淆。
(有关更多信息,请参阅“ 核心animation指南” ,特别是“ 图层对象定义其自己的几何graphics”一节 。)
在代码中,我们将:
- 将
bounds
设置为矩形0, 0, width, height
。 (我故意留给你的width
– 它将不得不超过56)。 - 将
anchorPoint
设置为点anchorPoint
。 换句话说,在层的宽度的一半,在层的顶部。 - 将
position
设置到点20, 20
。 - 设置
transform
旋转45°。
顺便说一下,在下面的代码中,我设置了affineTransform
而不是transform
,只是因为它对于简单的2-D变换稍微方便一些。
何时设置图层
你是正确的, -drawRect:
是创build和添加图层的错误地方。 该方法应该绘制到视图(它的CGContext
)的内容,但别无其他。
layoutSubviews
可以正常工作,但会比你期望的更频繁地被调用,而且你不想每次创build和添加一个新的图层。
看起来你只需要设置一次图层的几何graphics,而不再触摸它。 为什么不只是当你的hasBanner
属性被改变时创build或销毁图层?
@interface MyTableViewCell () @property (nonatomic) BOOL hasLayer; @property (nonatomic) CALayer* bannerLayer; @end - (void)setHasBanner:(BOOL)hasBanner { if (hasBanner != _hasBanner) { _hasBanner = hasBanner; if (hasBanner) { CALayer* banner = [CALayer layer]; banner.backgroundColor = [UIColor colorWithRed:.5f green:.5f blue:.5f alpha:1.f].CGColor; banner.bounds = CGRectMake(0, 0, 56, 15); banner.anchorPoint = CGPointMake(0.5, 0); banner.position = CGPointMake(20, 20); banner.affineTransform = CGAffineTransformMakeRotation(-45.0 / 180.0 * M_PI); // Add the layer to the view, and remember it for later [self.layer addSublayer:banner]; self.bannerLayer = banner; } else { // Remove the layer from the view, and discard it [self.bannerLayer removeFromSuperlayer]; self.bannerLayer = nil; } } }