Xamarin.iOS: размытые края на закругленных углах для CAGradientLayer

Чтобы настроить внешний вид моего приложения, я реализовал настраиваемое средство визуализации для кнопок, установив для них фоновое изображение градиента. Пока все работает нормально.

Однако, когда я устанавливаю радиус угла, края выглядят очень размытыми. Я думал, что это может быть из-за разницы между координатами экрана и фактическим разрешением, но когда я применяю коэффициент (2 или 3), чтобы учесть это, он просто полностью портит форму (при этом все еще остается размытым).

Вот скриншот, сделанный на iPhone X (обратите внимание на разрешение записи и изображений):

введите описание изображения здесь

Вот код, генерирующий фон:

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);

person japhwil    schedule 26.01.2018    source источник


Ответы (1)


Я считаю, что это потому, что ContentsScale вашего gradientLayer по умолчанию имеет значение 1.0, как и масштаб контекста изображения UIGraphics. Как красноречиво говорит Кен Томасес в ответе, который более подробно рассматривает CALayer поведение рисования: «В контекст, который преобразует пространство пользователя (точки, более или менее) в пространство устройства (пиксели) ».

С CALayer вы управляете исключительно вами, вы также должны управлять этим преобразованием, если это что-то, кроме значения по умолчанию (1.0), согласно документация. В настоящее время ваш градиент вычисляется в точках, но отображается на пикселях iPhone X в формате 1: 1, что, черт возьми, выглядит размытым на этом модном экране.

После того, как вы закончите настройку 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;
person NickSpag    schedule 26.01.2018
comment
Спасибо за ответ! Вы были правы, говоря, что ContentsScale по умолчанию равен 1, но установка правильного значения (в данном случае 3) не устранила размытость. Я попытался установить его после gradientLayer.EndPoint, как вы предложили, и сразу после инициализации слоя. - person japhwil; 27.01.2018
comment
Ах! Вероятно, он не переносится в контекст UIGraphics изображения? Попробуем изменить его на 'UIGraphics.BeginImageContextWithOptions(gradientLayer.Bounds.Size, false, UIScreen.MainScreen.Scale);'? - person NickSpag; 27.01.2018
comment
Вот и все! Извините, что я так долго отвечал, у меня не было доступа к моему Mac в течение последних нескольких дней. - person japhwil; 01.02.2018
comment
Нет проблем, рад, что это сработало! Спасибо, что отметили это как ответ, я обновлю ответ, чтобы включить эту часть. - person NickSpag; 01.02.2018