Xamarin Forms Gradient Renderer不能在iOS上运行

时间:2018-06-15 09:26:57

标签: xamarin xamarin.forms xamarin.ios gradient

我正在尝试使用渐变渲染器,我已经在PCL中编写了一个类,并为Android和iOS编写了一个渲染器。 Android渲染器正在运行,但iOS渲染器根本没有显示渐变颜色。

我正在使用XLabs中的此Gradient代码。我不确定是什么破了。正确方向的提示会有所帮助。

PCL代码:

using Xamarin.Forms;

namespace gradient
{
    public enum GradientOrientation
    {
        Vertical,
        Horizontal
    }

    public class GradientContentView : ContentView
    {
        public GradientOrientation Orientation
        {
            get { return (GradientOrientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        public static readonly BindableProperty OrientationProperty =
            BindableProperty.Create<GradientContentView, GradientOrientation>(x => x.Orientation, GradientOrientation.Vertical, BindingMode.OneWay);

        public Color StartColor
        {
            get { return (Color)GetValue(StartColorProperty); }
            set { SetValue(StartColorProperty, value); }
        }

        public static readonly BindableProperty StartColorProperty =
            BindableProperty.Create<GradientContentView, Color>(x => x.StartColor, Color.White, BindingMode.OneWay);

        public Color EndColor
        {
            get { return (Color)GetValue(EndColorProperty); }
            set { SetValue(EndColorProperty, value); }
        }

        public static readonly BindableProperty EndColorProperty =
            BindableProperty.Create<GradientContentView, Color>(x => x.EndColor, Color.Black, BindingMode.OneWay);
    }
}

iOS渲染器代码:

using CoreAnimation;
using CoreGraphics;
using gradient;
using gradient.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(GradientContentView), typeof(GradientContentViewRenderer))]
namespace gradient.iOS
{
    class GradientContentViewRenderer : VisualElementRenderer<ContentView>
    {
        private GradientContentView GradientContentView
        {
            get { return (GradientContentView)Element; }
        }

        protected CAGradientLayer GradientLayer { get; set; }

        protected override void OnElementChanged(ElementChangedEventArgs<ContentView> e)
        {
            base.OnElementChanged(e);

            if (GradientContentView != null &&
                NativeView != null)
            {
                // Create a gradient layer and add it to the 
                // underlying UIView
                GradientLayer = new CAGradientLayer();
                GradientLayer.Frame = NativeView.Bounds;
                GradientLayer.Colors = new CGColor[]
                {
                    GradientContentView.StartColor.ToCGColor(),
                    GradientContentView.EndColor.ToCGColor()
                };

                SetOrientation();

                NativeView.Layer.InsertSublayer(GradientLayer, 0);
            }
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (GradientLayer != null && GradientContentView != null)
            {
                // Turn off Animations
                CATransaction.Begin();
                CATransaction.DisableActions = true;

                if (e.PropertyName == GradientContentView.StartColorProperty.PropertyName)
                    GradientLayer.Colors[0] = GradientContentView.StartColor.ToCGColor();

                if (e.PropertyName == GradientContentView.EndColorProperty.PropertyName)
                    GradientLayer.Colors[1] = GradientContentView.EndColor.ToCGColor();

                if (e.PropertyName == VisualElement.WidthProperty.PropertyName ||
                    e.PropertyName == VisualElement.HeightProperty.PropertyName)
                    GradientLayer.Frame = NativeView.Bounds;

                if (e.PropertyName == GradientContentView.OrientationProperty.PropertyName)
                    SetOrientation();

                CATransaction.Commit();
            }
        }
        void SetOrientation()
        {
            if (GradientContentView.Orientation == GradientOrientation.Horizontal)
            {
                GradientLayer.StartPoint = new CGPoint(0, 0.5);
                GradientLayer.EndPoint = new CGPoint(1, 0.5);
            }
            else
            {
                GradientLayer.StartPoint = new CGPoint(0.5, 0);
                GradientLayer.EndPoint = new CGPoint(0.5, 1);
            }
        }

    }
}

2 个答案:

答案 0 :(得分:1)

这是我渲染渐变背景的代码,我没有使用方向,但也许有帮助。

@JsonInclude(Include.ALWAYS)

我看到的主要区别是您似乎没有覆盖ViewWillLayoutSubviews方法。我有同样的问题,导致在创建窗口期间创建没有高度和宽度的渐变图层(此时View尚未布局)。

因此,在布局子视图时,我会调整渐变层的宽度和高度,因为在那时,视图的宽度和高度是明确的。

答案 1 :(得分:0)

您必须在VisualElementRenderer.LayoutSubviews中更新图层的大小:

public override void LayoutSubviews()
{
    base.LayoutSubviews();

    CATransaction.Begin();
    CATransaction.DisableActions = true;

    GradientLayer.Frame = NativeView.Bounds;

    CATransaction.Commit();
}