Xamarin.iOS:CAGradientLayer圆角上的模糊边缘

时间:2018-01-26 22:17:03

标签: c# iphone xamarin.forms xamarin.ios

要自定义我的应用程序的外观,我已经为按钮实现了自定义渲染器,在它们上设置了渐变背景图像。到目前为止,这工作正常。

但是,当我设置角半径时,边缘看起来非常模糊。我认为这可能是由于屏幕坐标和实际分辨率之间的差异,但是当我应用一个因子(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 个答案:

答案 0 :(得分:2)

我相信它是因为您的gradientLayer ContentsScale默认为1.0,而且&#39; UIGraphics&#39;图像上下文的比例。正如Ken Thomases在answer中雄辩地说,更深入地了解CALayer绘图行为:&#34;在用户空间转换的上下文中存在隐式转换(点,或多或少)到设备空间(像素)。&#34;

对于您独家管理的CALayer,除了默认值(1.0)之外,您还必须管理该转换,而不是Apple documentation。目前,您的渐变是以点数计算的,但是以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;
相关问题