Xamarin为iOS构建渐变帧渲染器

时间:2018-01-01 15:36:07

标签: c# xamarin xamarin.forms xamarin.ios custom-renderer

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

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

首先我尝试覆盖SetupLayer方法,因为它在默认的帧渲染器see here中,并在那里添加子层

我开始工作的方法是重写Draw方法并在框架视图中添加一个子图层,并将框架图层背景设置为UIColor.Clear。

我得到的问题是控件我放在框架内部,渐变也会以某种方式褪色,就像有一些层混合的东西一样。像.5不透明度。

任何建议如何使Layer(Gradient)完全不透明?

我做错了吗?

提前致谢。

更新:我从示例中删除了不必要的代码,因为没有造成混淆,我面临的问题是了解图层混合在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);
    }

2 个答案:

答案 0 :(得分:0)

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

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 = { ... }
        }
    }
}

答案 1 :(得分:0)

Image with the issue

最后,我在Xamarin论坛帖子上找到了解决方案。 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 });
    }
}