0

我有以下问题。

假设我有自己的图像视图类(为方便起见,我修剪了所有代码,只包含导致问题的代码)。该类继承自UIView并覆盖drawRect. 这是我的drawRect样子(代码在 Xamarin 中,但很容易理解)

public override void Draw(RectangleF rect)
    {
        base.Draw(rect);
        CGContext context = UIGraphics.GetCurrentContext();
        if (Image != null)
        {
            var imageRect = getAspectFillRect(rect, Image.Size);
            context.DrawImage(imageRect, Image.CGImage);
        }
        else
        {
            this.BackgroundColor.SetFill();
            context.FillRect(this.Bounds);
        }
    }

此代码只是通过计算将使用此代码行以方面填充模式显示图像的矩形来Image模拟 's aspect fill 选项的方式将图像设置为属性UIImageViewgetAspectFillRect(rect, Image.Size);

我也有UICollectionView自定义布局和自定义单元格。每个UICollectionViewCellUI 都在一个 xib 文件中定义,在那里我设置了所有必要的约束,在那里我还有用于显示图像的自定义视图。对于界面生成器中的该视图,我已将内容模式设置为“Aspect Fill”。自定义UICollectionViewLayout是以单元格扩展的方式进行的(您将很快看到该示例)。所以单元格内的图像也应该缩放,并且因为我设置了“Aspect Fill”选项,它不应该调用drawRect我的自定义视图,而应该只是缩放已经绘制的内容。但事实并非如此!

看这里看演示发生了什么的视频。您可能会看到里面的图像没有与细胞一起生长。问题是,在drawRect我的自定义的单元格扩展动画开始之前UIView,使用 rect 调用该动画最终将在动画之后建立。所以我得到了一个生涩的动画。在我的自定义布局代码中,我只是LayoutIfNeeded在更新单元格的约束后调用。我不打电话setNeedsDisplay,所以我不明白为什么打电话给我drawRect

对于实验,我用 替换了我的自定义图像视图UIImageView,我将它的内容模式设置为“Aspect Fill”,然后看这里发生了什么。是的!有效。所以我想问题不在于自定义UICollectionView布局,而在于我的自定义图像绘制类。

我应该考虑什么?我应该如何处理这种情况?有任何想法吗?谢谢!

4

1 回答 1

0

DrawRect只要系统“感觉”它应该调用它,就会调用它。不管你打电话SetNeedsDisplay不打电话。

现在,设置ContentModeScaleAspectFill并不意味着DrawRect不会调用。事实上,来自 Apple文档

无需每次都重绘视图的内容,您可以使用此属性来指定要缩放内容(有或没有失真)或将它们固定到视图上的特定位置。

这意味着,如果您不想自己绘制内容的麻烦,只需设置ContentMode属性即可。在您的示例中,您正在使用DrawRect绘图。

现在,在动画开始之前DrawRect调用的事实,但带有(或?)的目标值意味着这些属性的目标值是在更改完成之前设置的。在动画期间,这些属性不会改变。期间注意。' 或'的值不会随着正在进行的转换的所有值而改变。它只知道“开始”和“结束”。BoundsFrameBoundsFrame

DrawRect如果在动画开始之前没有被调用,而是在动画结束之后被调用,你的应用会发生什么?好吧,单元格将随其子视图一起调整大小,但您的图像将在整个动画过程中保持较小,并在动画完成后捕捉到大尺寸。所以这是一种或另一种方式。

解决方案:

  • 使用 UIImageView。
  • 如果您确实需要使用自定义视图,请在其上使用 UIImageView 来显示您的图像。
  • 在自定义 CALayer 上绘制图像并将该图层添加到自定义视图的图层上。
于 2014-09-25T15:28:23.113 回答