为啥 CALayer 蒙版没有居中并偏离几个像素?
Posted
技术标签:
【中文标题】为啥 CALayer 蒙版没有居中并偏离几个像素?【英文标题】:Why is CALayer mask not centered and off by a few pixels?为什么 CALayer 蒙版没有居中并偏离几个像素? 【发布时间】:2021-03-20 18:34:24 【问题描述】:我有以下代码:
public override void ViewWillAppear(bool animated)
base.ViewWillAppear(animated);
var gradient = new CAGradientLayer();
gradient.Frame = view.Bounds;
gradient.Colors = colors;
var mask = new CALayer();
mask.Frame = view.Bounds;
mask.Contents = view.Image.CGImage;
mask.ContentsGravity = CALayer.GravityCenter;
gradient.Mask = mask;
view.Layer.AddSublayer(gradient);
产生以下结果:
“view”是一个完美居中的 UIImageView。
数字“1”正好在中间。在这里你可以看到蒙版没有完全居中。
这里的图片是来自标准资源的心形图标,它不是自定义图片。 (例如,如果在按钮中使用,那么它会完美居中)。
在发布之前,在设置框架和边界时,我已经尝试了所有可能的组合,但蒙版总是偏离中心几个像素。
其他人在这里报告了类似的问题,但没有解决方案:Gradient Color over Template Image in Swift 4
这让我相信蒙版的应用方式存在错误。谁能确认一下?
【问题讨论】:
“遮罩的应用方式存在错误” 没有。相信我。 @matt 这样的简单代码怎么会产生不正确的结果呢?即使使用了 CALayer.GravityCenter ,看起来面具也没有居中。或者这里有一些关于如何设置 Frames 的极端情况? 您没有显示足够的代码来重现该问题,甚至没有解释您要做什么,因此无法提供进一步的帮助。我只是说,除非您首先假设 您 犯了错误,否则您不会弄清楚这一点。 @matt 唯一的另一件事是带有居中 UIImageView 和居中标签的故事板。我不确定我是否可以将它上传到这里的某个地方。 例如,您可能正在等效于 viewDidLoad 执行此操作。但这为时过早,没有已知的帧。正如我所说,没有足够的代码和明确的目标,问题是没有意义的。 【参考方案1】:屏蔽没有错误。这是至关重要的东西,是所有绘画的基础。如果有错误,整个界面就会被破坏。错误在您的代码中。
这基本上只是时间问题。在您知道它们实际上是什么之前,不要谈论任何框架或边界。
为了演示,我将向后工作:首先我将向您展示我的代码的结果,然后我将向您展示代码。这是结果。我从一个以自动布局为中心的正方形故事板开始,所以你知道我没有作弊:
现在我运行应用程序并在整个屏幕上叠加一个带有居中心形图像蒙版的渐变层:
如您所见,心脏位于完全正确的位置。它的居中与黄色正方形的含义完全相同,这就是为什么它在正方形中显示为居中。
现在是代码。请注意,组装工作只在viewDidLoad
中完成一次,但所有测量工作都是在我们有实际测量要使用时完成的,即在@987654326 @。这是 Swift 但你应该不难翻译(C# 或其他):
class ViewController: UIViewController
let gradient : CAGradientLayer =
let g = CAGradientLayer()
g.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
return g
()
let mask = CALayer()
let image : UIImage =
let im = UIImage(systemName: "heart.fill")!
return im
()
override func viewDidLoad()
super.viewDidLoad()
self.view.layer.addSublayer(gradient)
mask.contents = image.cgImage
mask.contentsGravity = .center
gradient.mask = mask
override func viewDidLayoutSubviews()
gradient.frame = view.bounds
mask.frame = gradient.bounds
去吧,照样做。
【讨论】:
所以我开始了一个新项目,它确实有效!我试图弄清楚为什么它会产生与我的情况不同的结果,结果证明是因为我在 ViewWillAppear 中这样做了,这显然为时过早。我将我的代码移到 ViewDidAppear 并且它有效。我没有意识到 ViewWillAppear 可能为时过早。并且图像仅偏离了几个像素。谢谢! 在我看来 viewDidAppear 可能太晚了——用户可以看到绘图跳转。这就是我使用 viewDidLayoutSubviews 的原因。以上是关于为啥 CALayer 蒙版没有居中并偏离几个像素?的主要内容,如果未能解决你的问题,请参考以下文章