【问题标题】:Xamarin Forms Gradient Renderer not working on iOSXamarin Forms Gradient Renderer 无法在 iOS 上运行
【发布时间】:2018-06-15 09:26:57
【问题描述】:

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

我正在使用来自XLabs 的渐变代码。我不确定是什么坏了。正确方向的提示会有所帮助。

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

    }
}

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.ios gradient


    【解决方案1】:

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

    protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
    
            if (e.OldElement == null) // perform initial setup
            {
                ModernOrderCalendar page = e.NewElement as ModernOrderCalendar;
                var gradientLayer = new CAGradientLayer();
                gradientLayer.Name = "gradient";
                CGRect rect = View.Bounds;          
                gradientLayer.Frame = rect;
                gradientLayer.Colors = new CGColor[] { page.StartColor.ToCGColor(), page.EndColor.ToCGColor() };
                View.Layer.InsertSublayer(gradientLayer, 0);
            }
        }
    
        public override void ViewWillLayoutSubviews()
        {
            base.ViewWillLayoutSubviews();
            if (Xamarin.Forms.Device.Idiom == TargetIdiom.Tablet)
            {
                var gradientLayer = View.Layer.Sublayers.FirstOrDefault(l => l.Name == "gradient");
                gradientLayer.Frame = View.Bounds;
                View.Layer.Sublayers[0] = gradientLayer;
                CGRect frame = View.Bounds;
                View.Bounds = frame;
            }
        }
    

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

    因此,我在布局子视图时调整了渐变层的宽度和高度,因为此时视图的宽度和高度肯定是已知的。

    【讨论】:

      【解决方案2】:

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

      public override void LayoutSubviews()
      {
          base.LayoutSubviews();
      
          CATransaction.Begin();
          CATransaction.DisableActions = true;
      
          GradientLayer.Frame = NativeView.Bounds;
      
          CATransaction.Commit();
      }
      

      【讨论】:

        猜你喜欢
        • 2018-03-01
        • 2019-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-23
        相关资源
        最近更新 更多