为什么 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
    }
}

你们也照样做。