Xamarin.iOS:CAGradientLayer圆角模糊问题

3
为了自定义我的应用程序的外观,我已经为按钮实现了自定义渲染器,在它们上面设置了渐变背景图像。到目前为止,这个功能运作良好。
然而,当我设置圆角时,边缘看起来非常模糊。我认为这可能是由于屏幕坐标和实际分辨率之间的差异造成的,但是当我应用一个因子(2或3)来适应它时,它只会完全破坏形状(仍然模糊)。
这里是一个截图,拍摄于iPhone X上(请注意条目和图像的分辨率):

enter image description here

这是生成背景的代码:
private UIImage CreateGradientBackground(Color startColor, Color endColor)
{
    var gradientLayer = new CAGradientLayer();
    if (Control == null)
        return null;
    gradientLayer.Bounds = Control.Bounds;
    gradientLayer.CornerRadius = (Control.Bounds.Width < Control.Bounds.Height) ? 
        Control.Bounds.Width / 2 : 
        Control.Bounds.Height / 2;
    gradientLayer.Colors = new CGColor[] { startColor.ToCGColor(), endColor.ToCGColor() };
    gradientLayer.StartPoint = new CGPoint(0, 0.5);
    gradientLayer.EndPoint = new CGPoint(1, 0.5);

    UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
    if (UIGraphics.GetCurrentContext() == null)
        return null;
    gradientLayer.RenderInContext(UIGraphics.GetCurrentContext());
    UIImage image = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();

    return image;
}

这是如何应用的(适用于各种不同的状态):
Control.SetBackgroundImage(gradientBackground, UIControlState.Normal);

有人知道如何修复这个问题吗?
非常感谢!
解决方案(感谢NickSpag!):
1:在渐变层上设置适当的内容比例尺:
gradientLayer.ContentsScale = UIScreen.MainScreen.Scale;

2:获取正确的图像上下文:

UIGraphics.BeginImageContextWithOptions(gradientLayer.Bounds.Size, false, UIScreen.MainScreen.Scale);
1个回答

2
我认为问题出在您的gradientLayer的ContentsScale默认为1.0,就像“UIGraphics”图像上下文的比例一样。正如Ken Thomases在一个更深入地涉及CALayer绘图行为的答案中所说:“上下文中有一个隐含的变换,将用户空间(点,或多或少)转换为设备空间(像素)。”
对于CALayer,您必须管理除默认值(1.0)以外的任何变换,根据苹果的文档。当前,您的渐变是在点中计算的,但以1:1的方式显示在iPhone X的像素上,这在那个时髦的屏幕上看起来模糊不清。
在设置完gradientLayer.EndPoint后,我建议添加以下内容:
gradientLayer.ContentsScale = UIScreen.MainScreen.Scale;

并且像这样为UIGraphics图像上下文指定比例:

UIGraphics.BeginImageContextWithOptions(gradientLayer.Bounds.Size, false, UIScreen.MainScreen.Scale);

对于Xamarin.Mac或macOS,如下所示。不认为您需要指定除当前之外的上下文:

gradientLayer.ContentsScale = NSScreen.MainScreen.BackingScaleFactor;

谢谢你的回答!你关于ContentsScale默认为1是正确的,但将其设置为正确的值(在这种情况下为3)并没有解决模糊问题。我尝试了在gradientLayer.EndPoint之后以及初始化图层后立即设置它。 - japhwil
1
啊!可能没有传递到 UIGraphics 图像上下文?让我们尝试将其更改为 'UIGraphics.BeginImageContextWithOptions(gradientLayer.Bounds.Size, false, UIScreen.MainScreen.Scale);' - NickSpag
搞定了!抱歉回复晚了,过去几天我没有使用我的 Mac。 - japhwil
没问题,很高兴它起作用了!感谢您将其标记为答案,我会更新答案以包含该部分。 - NickSpag

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