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