使用UIViewContentModeScaleAspectFill调用自定义UIView drawRect

时间:2014-09-25 13:15:55

标签: ios uiview xamarin drawrect uiviewcontentmode

我有以下问题。

假设我有自己的图像视图类(为了方便我修剪所有代码,只包含导致问题的代码)。该类继承自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方面填充选项的方式将图像集绘制为UIImageView属性。代码行getAspectFillRect(rect, Image.Size);

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

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

对于实验,我将自定义图片视图替换为UIImageView,我将其内容模式设置为" Aspect Fill"和LOOK HERE发生了什么。 YEAH!有效。所以我认为问题不在自定义UICollectionView布局中,而是在我的自定义图像绘制类中。

我应该考虑什么?我该如何处理这个案子?有任何想法吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

只要系统“感觉”它应该调用它,就会调用

DrawRect。无论你是否致电SetNeedsDisplay

现在,将ContentMode设置为ScaleAspectFill并不意味着DrawRect 不会被调用。事实上,来自Apple docs here

  

不是每次都重新绘制视图的内容,而是可以使用   此属性指定您要缩放内容(或者   有或没有扭曲)或将它们固定在   图。

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

现在,{<1}}在动画开始之前被称为这一事实,但DrawRect(或Bounds?)的目标值意味着在更改完成之前设置这些属性的目标值。在动画期间,这些属性不会更改。在期间注意FrameBounds的值不会在正在进行的转换的所有值中发生变化。它只知道“开始”和“结束”。

如果在动画开始前Frame 被调用,但在动画播放结束后调用,您的应用会发生什么?好吧,单元格会随着子视图一起调整大小,但是在整个动画中你的图像会保持很小并且在动画完成后会捕捉到大尺寸。所以它是这样或那样的。

解决方案:

  • 使用UIImageView。
  • 如果确实需要使用自定义视图,请使用UIImageView显示图像。
  • 在自定义CALayer上绘制图像,并在自定义视图的图层上添加该图层。