Xamarin 为 iOS 形成渐变帧渲染器

Xamarin forms gradient frame renderer for iOS

我正在为 Xamarin.Forms 框架控件创建自定义渲染器以启用渐变背景等扩展功能。

现在我可以在 iOS 上以某种方式工作,但我也在研究 android 版本。

首先,我尝试重写默认帧渲染器中的 SetupLayer 方法 see here,并在那里添加一个子层

我让它工作的方法是覆盖 Draw 方法并向框架视图添加子层并将框架层背景设置为 UIColor.Clear。

我遇到的问题是我将控件放在框架内,并且渐变以某种方式褪色,就像正在进行一些图层混合一样。类似 0.5 的不透明度。

关于如何让后面的图层(渐变)完全不透明有什么建议吗?

我做错了吗?

提前致谢。

更新: 我已经从示例中删除了不必要的代码,以免造成混淆,我面临的问题是了解图层混合在 iOS 中的工作方式,如顶部-层与添加的渐变层混合,看起来比普通帧更褪色。

 //not working
 private void SetupLayer()
    {  
 *** 
 var gl = new CAGradientLayer
        {
            StartPoint = new CGPoint(0, 0),
            EndPoint = new CGPoint(1, 1),
            Frame = rect,
            Colors = new CGColor[]
            {
                    _gradinetControl.StartColor.ToCGColor(),
                    _gradinetControl.EndColor.ToCGColor()
            },
            CornerRadius = _gradinetControl.CornerRadius
        };

        Layer.BackgroundColor = UIColor.Clear.CGColor;

       Layer.InsertSublayer(gl,0);
***
}

*

//working but strange fade blending    
public override void Draw(CGRect rect)
    {           
        var gl = new CAGradientLayer
        {
            StartPoint = new CGPoint(0, 0),
            EndPoint = new CGPoint(1, 1),
            Frame = rect,
            Colors = new CGColor[]
            {
                    _gradinetControl.StartColor.ToCGColor(),
                    _gradinetControl.EndColor.ToCGColor()
            },
            CornerRadius = _gradinetControl.CornerRadius
        };

       NativeView.Layer.BackgroundColor = UIColor.Clear.CGColor;
       NativeView.Layer.InsertSublayer(gl,0);           
       base.Draw(rect);
    }

我认为存在一个插件。你可以去那里看看:

XFGloss

在XAML

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xfg="clr-namespace:XFGloss;assembly=XFGloss"
             x:Class="XFGlossSample.Views.AboutPage"
             Title="XFGloss Sample App" Padding="10">

    <xfg:ContentPageGloss.BackgroundGradient>
        <xfg:Gradient Rotation="150">
            <xfg:GradientStep StepColor="White" StepPercentage="0" />
            <xfg:GradientStep StepColor="White" StepPercentage=".5" />
            <xfg:GradientStep StepColor="#ccd9ff" StepPercentage="1" />
        </xfg:Gradient>
    </xfg:ContentPageGloss.BackgroundGradient>
    ...
</ContentPage>

在代码中

namespace XFGlossSample.Views
{
    public class AboutPage : ContentPage
    {
        public AboutPage()
        {
            Title = "XFGloss Sample App";
            Padding = 10;

            // Manually construct a multi-color gradient at an angle of our choosing
            var bkgrndGradient = new Gradient()
            {
                Rotation = 150,
                Steps = new GradientStepCollection()
                {
                    new GradientStep(Color.White, 0),
                    new GradientStep(Color.White, .5),
                    new GradientStep(Color.FromHex("#ccd9ff"), 1)
                }
            };

            ContentPageGloss.SetBackgroundGradient(this, bkgrndGradient);

            Content = { ... }
        }
    }
}

Image with the issue

最后我在 Xamarin 论坛上找到了解决方案 post。 here 似乎 iOS 在图层上呈现不同的颜色。解决方法是根据 xamarin 表单颜色重新制作 cgcolor。

public class ExtendedFrameRenderer : FrameRenderer
{
  public override void Draw(CGRect rect)
{           
    var gl = new CAGradientLayer
    {
        StartPoint = new CGPoint(0, 0),
        EndPoint = new CGPoint(1, 1),
        Frame = rect,
        Colors = new CGColor[]
        {
                //old
                //_gradinetControl.StartColor.ToCGColor(),
                // _gradinetControl.EndColor.ToCGColor()
                //fix
                ToCGColor(__gradinetControl.StartColor),
                ToCGColor(__gradinetControl.EndColor)
        },
        CornerRadius = _gradinetControl.CornerRadius
    };

   NativeView.Layer.BackgroundColor = UIColor.Clear.CGColor;
   NativeView.Layer.InsertSublayer(gl,0);           
   base.Draw(rect);
}
    public static CGColor ToCGColor(Color color)
    {
        return new CGColor(CGColorSpace.CreateSrgb(), new nfloat[] { (float)color.R, (float)color.G, (float)color.B, (float)color.A });
    }
}