如何防止UIImageView蒙版的裁剪

4

我想要在一个图片视图上应用聊天气泡遮罩,并且我希望遮罩图片可以自适应图片视图的尺寸。这是我用来创建和应用遮罩的代码:

let mask = CALayer()
let maskImage = UIImage(named: "chatGif")!
mask.contents = maskImage.CGImage
mask.frame = CGRectMake(0, 0, imageView.frame.width, imageView.frame.height)
imageView.layer.mask = mask
imageView.layer.masksToBounds = true

这是我的遮罩:

enter image description here

但这是我得到的结果:

enter image description here

当我给遮罩图像添加切片时(即创建可调整大小的端部插图),我得到了这个:

enter image description here

我制作了一个最小化的项目来演示问题,并将其放在这里

我不理解为什么我的遮罩图像的右侧和底部会被裁剪。遮罩的框架和边界与图像视图的相匹配,而用于遮罩的图像实际上比图像视图要小,因此如果有什么问题,我希望它不要覆盖整个图像视图,而是被部分裁剪。

请问有人能解释这里发生了什么吗?我该如何防止这种行为?

编辑:我已经对此进行了更多的尝试,当我将遮罩的大小设置为与maskImage的大小相匹配时,结果变得更加合理:

let mask = CALayer()
let maskImage = UIImage(named: "chatGif")!
mask.contents = maskImage.CGImage
mask.frame = CGRectMake(0, 0, maskImage.size.width, maskImage.size.height)
imageView.layer.mask = mask
imageView.layer.masksToBounds = true

我得到的结果是:

enter image description here

或者使用遮罩资源进行切片,可以得到J.Hunter的答案中所示的图像。但这仍然不是我想要的,因为遮罩没有被拉伸以填充imageView,周围的大部分区域被遮蔽掉了,这不应该发生,但至少我能够理解在这种情况下正在发生什么。我将遮罩的框架设置为小于imageView的框架大小,因此它显然不能填满整个区域。

然而,我希望将遮罩的框架设置为与imageView相匹配的尺寸,这样我在最后一个截图中可以看到的遮罩的右侧和底部边缘将与imageView的右侧和底部边缘对齐。如果我打印出遮罩的框架、边界和contentsRect,它们正是我期望的:框架和边界与imageView相匹配,contentsRect(0.0, 0.0, 1.0, 1.0)。我理解一个CALayer将显示其内容的一部分,基于contentsRect,因此除非该矩形小于1.0x1.0,否则应该显示整个内容图像,对吗?但为什么我看到的不是这样的结果呢?


也许这个线程可以帮助你。 - J.Hunter
很遗憾,我无法使用CGImageCreateWithMask方法,因为在我的实际项目中,我正在使用FLAnimatedImageView来显示gif图像,所以遮罩必须位于UIImageView层而不是UIImage层。 - NewShelbyWoo
2个回答

0

好的,我终于搞清楚了发生了什么。我在创建的示例项目中添加了与我的实际项目相同的调试打印语句,并发现我设置蒙版时imageView的框架比我预期的大得多,并不是它最终的显示大小。这很有道理,因为在示例项目中,我在viewDidLoad中设置了蒙版,在任何子视图被布置之前。

当我在我的实际项目中打印值时,我没有意识到这一点,因为我的UIImageViewUITableViewCell中,因此它未初始化的大小与Storyboard中的占位符大小相同,后者并不比最终大小大太多,所以它看起来不明显过大。

现在,如果我能把我过去4个小时的时间拿回来就好了。

编辑:澄清一下,如果在图像视图的最终布局大小设置之后运行初始代码,则其可以正常工作。因此,您应该在viewDidLayoutSubviews中设置蒙版,或者如果它是表格/集合单元格,则可以在layoutSubviews中检查框架大小是否已更改。


我也遇到了同样的问题,你是怎么解决的? - Mohamad Shaker
我更新了我的解决方案。在最终大小设置后,您只需运行初始代码即可。 - NewShelbyWoo
谢谢,我在将遮罩应用于uicollectionViewCell内的imageView时遇到了同样的问题,但是通过在cellForItemAt函数中调用cell.setNeedsLayout()和cell.layoutIfNeeded()并重写我的自定义单元格中的layoutIfNeeded方法来解决它。 - Mohamad Shaker

0
我下载了你的演示项目并重写了一些代码,像这样:

override func viewDidLoad() { super.viewDidLoad()
let mask = CALayer()
let maskImage = UIImage(named: "chatGif")!
print("image size is \(maskImage.size)")
mask.contents = maskImage.CGImage
mask.frame = CGRect(origin: CGPointZero, size: maskImage.size)
imageView.layer.mask = mask
imageView.layer.masksToBounds = true

}

你的maskImage图像大小为(39.5, 32.5)。看起来你的chatGif.png有问题。

快照输入图像描述


这是我在 chatGif 资源上分片得到的结果,与调用 resizableImageWithCapInsets 相同。当你这样做然后获取 maskImage 的大小时,那个大小是资产的最小大小。如果你查看 chatGif.png 文件,你会发现它是 294x174。我想要的是将 mask frame 大小设置为 imageView frame 大小,并使 mask 缩放到该大小而不是更大。我会在我的问题中更新更多信息。 - NewShelbyWoo
@NewShelbyWoo 这让我感到困惑。我用Photoshop打开chatGif.png并检查通道,一切看起来都没问题。 - J.Hunter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接