3

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

我可能完全在错误的地方执行此操作,但我正在覆盖-layoutSubviews添加图层。我试图这样做,-drawRect:但横幅最终被表格视图的 imageView 覆盖,因为表格呈现(即图层位于图像视图下方,因为稍后添加了图像视图)。

我真的很难得到正确的数学。我计算过,假设横幅从单元格顶部的 40 点和左侧的 40 点开始,角度正好为 -45º,则斜边将为 56 点。所以我正在制作一个 56 点宽的 CALayer,然后将其旋转 -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];
    }
}

横幅坐错了位置

4

1 回答 1

8

该层应该去哪里?

我们画一个图:

在此处输入图像描述

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

定位图层

可以从四个独立的步骤来考虑它:

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

这些对应于四个属性:boundsanchorPointpositiontransform

您不想触摸该frame属性,因为它的值是boundspositiontransform和派生的anchorPoint。如果您尝试设置frame,CALayer 将尝试反转transform,将其应用于您提供的 rect ,然后设置boundsand position。这可能不会给出你想要的结果,所以你最好完全忽略它——这样就不会那么混乱了。

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

在代码中,我们将:

  1. 设置bounds为 rect 0, 0, width, height。(我故意留给width你——它必须超过 56 岁。)
  2. 定点。anchorPoint_ 0.5, 0换句话说,沿着图层宽度的一半,在图层的顶部。
  3. 定点。position_20, 20
  4. 设置transform为旋转 45°。

顺便说一句,在下面的代码中,我设置了affineTransform而不是transform,只是因为它对于简单的二维转换更方便一些。

何时设置图层

您是对的,这-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;
        }
    }
}
于 2013-02-03T06:25:20.297 回答