使用CALayer将对角横幅/徽章添加到UITableViewCell的角落

d11*_*wtq 2 iphone uitableview ios

我正在尝试在我的表格视图中绘制装饰UITableViewCell,文本横幅看起来像一个邮票,对角线横跨单元格的左上角.

我可能完全在错误的地方做这件事,但我要-layoutSubviews重新添加图层.我试着这样做-drawRect:但是当表格呈现时,横幅最终被表格视图的imageView所覆盖(即图层位于图像视图下方,因为稍后会添加图像视图).

我真的很难为此得到正确的数学.我已经计算过,假设横幅从距离单元顶部40个点开始,距左边40个点,正好在-45º角度,斜边将是56个点.所以我将CALayer宽56点,然后旋转-45º,这是有效的.问题是细胞内的位置......它坐在细胞内,而不是靠在它的边缘.

而不是我应用试验和错误来把它放在正确的地方,有人可以帮助我数学吗?显然我需要移动图层旋转它.

感觉就像我在这里需要的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];
    }
}
Run Code Online (Sandbox Code Playgroud)

横幅坐在错误的地方

Kur*_*vis 7

图层应该去哪里?

我们画一个图:

在此输入图像描述

我们可以更进一步做一些触发,但让我们停在这里.很明显,横幅的中间顶点应该是(20,20).我们可以告诉Core Animation这样做.

定位图层

根据四个单独的步骤来考虑它:

  1. 设置图层的大小
  2. 确定图层中的哪个点是方便的参考点
  3. 设置该参考点的位置
  4. 围绕参考点旋转图层

这些对应于四个属性:bounds,anchorPoint,position,和transform.

你不想碰的frame属性,因为它的价值来源于bounds,position,transform,和anchorPoint.如果您尝试设置frame,CALayer将尝试反转transform,将其应用于您给出的矩形,然后设置boundsposition.这可能无法给出你想要的结果,所以你最好完全忽略它 - 这样就不那么混乱了.

(有关更多信息,请参阅核心动画指南,特别是图层对象定义自己的几何部分.)

在代码中,我们将:

  1. 设置bounds为矩形0, 0, width, height.(我故意离开width你 - 它必须超过56.)
  2. 设置anchorPoint到这一点0.5, 0.换句话说,沿着层的宽度的一半,并且在层的顶部.
  3. 设置position到这一点20, 20.
  4. 设置transform为旋转45°.

顺便说一句,在下面的代码中,我设置的是affineTransform而不是transform,只是因为它对于简单的2-D转换来说稍微方便一些.

何时设置图层

你是对的,这-drawRect:是创建和添加图层的错误位置.该方法应该吸引视图(内容CGContext)的内容,但不做任何其他事情.

layoutSubviews 会工作,但它会比你想象的更频繁地被调用,并且你不想每次都创建和添加一个新层.

看起来您只需要设置一次图层的几何图形,而不再需要再次触摸它.为什么不在hasBanner更改属性时创建或销毁图层?

@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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)