使用CALayer将对角横幅/徽章添加到UITableViewCell的角落 [英] Use a CALayer to add a diagonal banner/badge to the corner of a UITableViewCell

查看:108
本文介绍了使用CALayer将对角横幅/徽章添加到UITableViewCell的角落的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to draw decorate a UITableViewCell in my table view with a text banner that looks like a stamp, diagonally across the top left corner of the cell.

我可能完全在错误的地方做这个,但我要重写 -layoutSubviews 来添加图层。我尝试在 -drawRect:中进行此操作,但当表格呈现时,横幅最终被表格视图的imageView覆盖(即图层位于图像视图下方,如图像视图稍后添加。)

I'm probably doing this in the wrong place entirely, but I'm overriding -layoutSubviews to add the layer. I tried to do it in -drawRect: but the banner ends up covered by the table view's imageView as the table renders (i.e. the layer is underneath the image view, as the image view is added later).

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

I'm really struggling to get the math right for this. I've calculated that, assuming the banner begins at 40 points from the top of the cell and 40 points from the left, angled at exactly -45º, the hypotenuse would be 56 points. So I'm making a CALayer 56 points wide, then rotating it -45º, which works. The problem is the position within the cell... it's sitting way out into the cell, instead of hard up against the edges of it.

而不是我申请试验和在正确的地方得到这个错误,有人可以帮我数学吗?显然我需要移动图层旋转它。

Rather than me apply trial and error to get this in the right place, can somebody help me with the math? Obviously I need to move the layer and rotate it.

感觉就像我在这里需要的anchorPoint,但这似乎实际上是层,所以我必须错过这一点(没有双关语)。

It feels like anchorPoint is what I need here, but that seems to actually move the layer around, so I must be missing the point (no pun intended).

- (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];
    }
}

推荐答案

图层应该放在哪里go?



让我们绘制一个图表:

Where should the layer go?

Let's draw a diagram:

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

We could go further and do some trig, but let's stop here. It's pretty obvious that the middle-top point of the banner should be at (20,20). We can tell Core Animation to do exactly that.

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

Think of it in terms of four separate steps:


  1. 设置图层的大小

  2. 确定图层中的哪个点是方便的参考点

  3. 设置参考点的位置

  4. 围绕参考点旋转图层

  1. Set the size of the layer
  2. Decide what point in the layer is a convenient reference point
  3. Set the position of that reference point
  4. Rotate the layer around the reference point

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

These correspond to four properties: bounds, anchorPoint, position, and transform.

你不想触摸 frame 属性,因为它的值派生自 界限 position transform anchorPoint 。如果您尝试设置框架,CALayer将尝试反转转换,将其应用于您提供的矩形,然后设置边界位置。这可能无法给出你想要的结果,所以你最好完全忽略它 - 不那么混乱。

You don't want to touch the frame property, because its value is derived from the bounds, position, transform, and anchorPoint. If you try to set the frame, CALayer will try to invert the transform, apply that to the rect you gave, and then set the bounds and position. That may not give the results you want, so you're better off just ignoring it entirely -- less confusing that way.

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

(For more information, see the Core Animation Guide, specifically the section Layer Objects Define Their Own Geometry.)

在代码中,我们将:


  1. 界限设置为矩形 0,0,宽度,高度。 (我故意将宽度留给你 - 它必须超过56个。)

  2. 设置 anchorPoint 到点 0.5,0 。换句话说,在图层宽度的中间位置,在图层的顶部。

  3. 位置设置为 20,20

  4. 设置转换旋转45°。

  1. Set bounds to the rect 0, 0, width, height. (I'm deliberately leaving width to you -- it's going to have to be more than 56.)
  2. Set anchorPoint to the point 0.5, 0. In other words, halfway along the width of the layer, and at the top of the layer.
  3. Set position to the point 20, 20.
  4. Set transform to rotate by 45°.

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

By the way, in the code below, I'm setting the affineTransform instead of the transform, just because it's slightly more convenient for simple 2-D transformations.

你是正确的 -drawRect:是创建和添加图层的错误位置。该方法应该吸引视图的内容(它的 CGContext )但是 nothing else。

You're correct that -drawRect: is the wrong place to create and add layers. That method should draw into the content of the view (its CGContext) but do nothing else.

layoutSubviews 会起作用,但它会比你想象的更频繁地被调用,你不想要每次创建和添加一个新图层。

layoutSubviews will work, but it will get called more often than you might expect, and you don't want to create and add a new layer each time.

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

It looks like you just need to set the layer's geometry once, and never touch it again. Why not just create or destroy the layer when your hasBanner property is changed?

@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;
        }
    }
}

这篇关于使用CALayer将对角横幅/徽章添加到UITableViewCell的角落的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆