为什么 CALayer 蒙版没有居中并偏离几个像素?
Why is CALayer mask not centered and off by a few pixels?
我有以下代码:
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);
}
产生以下结果:
“视图”是一个完美居中的 UIImageView。
数字“1”正好在中间。在这里你可以看到遮罩没有完全居中。
这里的图片是标准资源中的心形图标,不是自定义图片。 (例如,如果用在按钮中,那么它就会完美居中)。
在发布之前,我已经尝试了所有可能的设置框架和边界的组合,遮罩总是偏离中心几个像素。
其他人在这里报告了类似的问题,但没有解决方案:
这让我相信蒙版的应用方式存在错误。谁能证实一下?
屏蔽没有错误。这是至关重要的东西,是所有绘图的基础。如果有错误,整个界面都会被破坏。该错误在您的代码中。
这基本上只是时间问题。在您了解它们实际是什么之前,不要谈论任何框架或边界。
为了演示,我将逆向工作:首先我将向您展示我的代码的结果,然后我将向您展示代码。这是结果。我从一个故事板开始,它有一个以自动布局为中心的正方形,所以你知道我没有作弊:
现在我 运行 应用程序并在整个屏幕上叠加一个带有居中心脏图像蒙版的渐变层:
如您所见,心脏完全在正确的位置。它的居中位置与黄色正方形的意义完全相同,这就是它出现在正方形中央的原因。
现在是代码。请注意 assembly 工作仅在 viewDidLoad
中完成一次,但所有 measurement 工作都是在我们进行实际测量时完成的一起工作,即在viewDidLayoutSubviews
。这是 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
}
}
你们也照样做。
我有以下代码:
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);
}
产生以下结果:
“视图”是一个完美居中的 UIImageView。
数字“1”正好在中间。在这里你可以看到遮罩没有完全居中。
这里的图片是标准资源中的心形图标,不是自定义图片。 (例如,如果用在按钮中,那么它就会完美居中)。
在发布之前,我已经尝试了所有可能的设置框架和边界的组合,遮罩总是偏离中心几个像素。
其他人在这里报告了类似的问题,但没有解决方案:
这让我相信蒙版的应用方式存在错误。谁能证实一下?
屏蔽没有错误。这是至关重要的东西,是所有绘图的基础。如果有错误,整个界面都会被破坏。该错误在您的代码中。
这基本上只是时间问题。在您了解它们实际是什么之前,不要谈论任何框架或边界。
为了演示,我将逆向工作:首先我将向您展示我的代码的结果,然后我将向您展示代码。这是结果。我从一个故事板开始,它有一个以自动布局为中心的正方形,所以你知道我没有作弊:
现在我 运行 应用程序并在整个屏幕上叠加一个带有居中心脏图像蒙版的渐变层:
如您所见,心脏完全在正确的位置。它的居中位置与黄色正方形的意义完全相同,这就是它出现在正方形中央的原因。
现在是代码。请注意 assembly 工作仅在 viewDidLoad
中完成一次,但所有 measurement 工作都是在我们进行实际测量时完成的一起工作,即在viewDidLayoutSubviews
。这是 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
}
}
你们也照样做。