XAML 如何在Xamarin表单中添加渐变到页面标题下方的边框线?

ryoqjall  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(114)

我如何在Xamarin表单中添加渐变到页面页眉下方的边框线?
我想实现的一个例子是here

zysjyyx4

zysjyyx41#

我如何在Xamarin表单中添加渐变到页面页眉下方的边框线?
我创建自定义渲染来创建渐变边框。
首先,您需要定义渲染:

public class GradientViewRender : View
{
    public static readonly BindableProperty GradientColorsProperty = BindableProperty.Create<GradientViewRender, Color[]>(p => p.GradientColors, new Color[]{Color.White} );

    public Color[] GradientColors
    {
        get { return (Color[])base.GetValue(GradientColorsProperty); }
        set { base.SetValue(GradientColorsProperty, value); }
    }

    
    public static readonly BindableProperty ViewHeightProperty = BindableProperty.Create<GradientViewRender, double>(p => p.ViewHeight, 0);

    public double ViewHeight
    {
        get { return (double)base.GetValue(ViewHeightProperty); }
        set { base.SetValue(ViewHeightProperty, value); }
    }

    
    public static readonly BindableProperty LeftToRightProperty = BindableProperty.Create<GradientViewRender, bool>(p => p.LeftToRight, true);

    public bool LeftToRight
    {
        get { return (bool)base.GetValue(LeftToRightProperty); }
        set { base.SetValue(LeftToRightProperty, value); }
    }
}

此渲染采用"颜色“数组,这样您就可以根据需要为渐变提供任意多的颜色。
然后您可以在android中实现此渲染。

public class GradientViewRenderer : Xamarin.Forms.Platform.Android.ViewRenderer<GradientTest.GradientViewRender, View>
{
    LinearLayout layout;
    Xamarin.Forms.Color[] gradientColors;
   
    double viewHeight;
    

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

        if (Control == null)
        {
            layout = new LinearLayout(Application.Context);
            layout.SetBackgroundColor(Color.White);
        
            gradientColors = (Xamarin.Forms.Color[])e.NewElement.GradientColors;
            
            viewHeight = (double)e.NewElement.ViewHeight;
            

            CreateLayout();
        }

        if (e.OldElement != null)
        {
            // Unsubscribe from event handlers and cleanup any resources
        }

        if (e.NewElement != null)
        {
            // Configure the control and subscribe to event handlers
            gradientColors = (Xamarin.Forms.Color[])e.NewElement.GradientColors;
            
            viewHeight = (double)e.NewElement.ViewHeight;
            

            CreateLayout();
        }
    }

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

        if (e.PropertyName == GradientViewRender.ViewHeightProperty.PropertyName)
        {
            this.viewHeight = (double)this.Element.ViewHeight;
            CreateLayout();
        }
        
        else if (e.PropertyName == GradientViewRender.GradientColorsProperty.PropertyName)
        {
            this.gradientColors = (Xamarin.Forms.Color[])this.Element.GradientColors;
            CreateLayout();
        }
        
        
    }

    private void CreateLayout()
    {
        layout.SetMinimumWidth((int)viewWidth);
        layout.SetMinimumHeight((int)viewHeight);

        CreateGradient();

        SetNativeControl(layout);
    }

    public void CreateGradient()
    {
        //Need to convert the colors to Android Color objects
        int[] androidColors = new int[gradientColors.Count()];

        for (int i = 0; i < gradientColors.Count(); i++)
        {
            Xamarin.Forms.Color temp = gradientColors[i];
            androidColors[i] = temp.ToAndroid();
        }

        GradientDrawable gradient = new GradientDrawable(GradientDrawable.Orientation.LeftRight, androidColors);

        if (roundCorners)
            gradient.SetCornerRadii(new float[] { cornerRadius, cornerRadius, cornerRadius, cornerRadius, cornerRadius, cornerRadius, cornerRadius, cornerRadius });

        layout.SetBackground(gradient);
    }
}

关于更详细的信息,你可以看看:
https://baglabs.com/2017/07/14/creating-gradients-xamarin-forms/
您可以从以下位置获取样本:
https://github.com/baileysh9/xamarin_forms_gradient
最后,您可以得到这样的渐变边框:

您可以通过GradientColors更改不同的颜色。

z4bn682m

z4bn682m2#

创建一个Xamarin.Forms视图,使用自定义渲染器在iOS和Android的视图中绘制渐变。然后将该视图放置在您想要的任何位置,大概就在标题栏或标题栏的下方。
首先阅读有关制作自定义渲染器的文档:https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/
我尝试从Xamarin.Forms框视图开始。

首先在Xamarin.Forms核心共享项目中创建一个新类,该项目继承自BoxView并为开始、中间和结束颜色设置3个可绑定属性:

using System;
using Xamarin.Forms;

namespace YourNameSpace
{
    public class GradientView : BoxView
    {
        public static readonly BindableProperty StartColorProperty =
            BindableProperty.Create(
                nameof(StartColor),
                typeof(Color),
                typeof(GradientView),
                Color.Transparent);

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

        public static readonly BindableProperty MiddleColorProperty =
            BindableProperty.Create(
                nameof(MiddleColor),
                typeof(Color),
                typeof(GradientView),
                Color.Transparent);

        public Color MiddleColor
        {
            get
            {
                return (Color)GetValue(MiddleColorProperty);
            }
            set
            {
                SetValue(MiddleColorProperty, value);
            }
        }

        public static readonly BindableProperty EndColorProperty =
            BindableProperty.Create(
                nameof(EndColor),
                typeof(Color),
                typeof(GradientView),
                Color.Transparent);

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

在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:d="http://xamarin.com/schemas/2014/forms/design"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:local="clr-namespace:TestUITest"
                mc:Ignorable="d"
                x:Class="TestUITest.MainPage"
                Title="Gradient View"
                BackgroundColor="Black">
    <StackLayout>
        <!-- Place new controls here -->
        <local:GradientView
            StartColor="DarkBlue"
            MiddleColor="LightBlue"
            EndColor="DarkBlue"
            HeightRequest="5" />
        <Label Text="Welcome to Xamarin.Forms!"
               HorizontalOptions="Center"
               VerticalOptions="Center"
               TextColor="White"/>
    </StackLayout>
</ContentPage>

同时将导航栏设置为黑色(以匹配屏幕截图),因此在Xamarin.Forms应用程序类中:

public App()
{
        InitializeComponent();

        var navPage = new NavigationPage(new MainPage());

        navPage.BarBackgroundColor = Color.Black;
        navPage.BarTextColor = Color.LightBlue;

        MainPage = navPage;
}

现在针对特定于平台的渲染器:
安卓系统:

using System;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using YourNameSpace;
using YourNameSpace.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(GradientView),typeof(GradientViewRenderer))]
namespace YourNameSpace.Droid
{
    public class GradientViewRenderer : BoxRenderer
    {
        public GradientViewRenderer(Context context) : base(context)
        {
        }

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

            if (e.NewElement != null)
            {
                GradientView formsGradientView = Element as GradientView;

                int[] colors = {
                   Convert.ToInt32(formsGradientView.StartColor.ToHex().Replace("#", "0x"), 16),
                   Convert.ToInt32(formsGradientView.MiddleColor.ToHex().Replace("#", "0x"), 16),
                   Convert.ToInt32(formsGradientView.EndColor.ToHex().Replace("#", "0x"), 16)
                };

                var gradeDrawable = new GradientDrawable(GradientDrawable.Orientation.LeftRight, colors);
                ViewGroup.SetBackgroundDrawable(gradeDrawable);
            }
        }
    }
}

iOS操作系统:

using System;
using CoreAnimation;
using CoreGraphics;
using YourNameSpace;
using YourNameSpace.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(GradientView), typeof(GradientViewRenderer))]
namespace YourNameSpace.iOS
{
    public class GradientViewRenderer : BoxRenderer
    {

        public override void Draw(CGRect rect)
        {
            //base.Draw(rect);
            GradientView formsGradientView = Element as GradientView;

            var currentContext = UIGraphics.GetCurrentContext();
            currentContext.SaveState();

            var colorSpace = CGColorSpace.CreateDeviceRGB();

            var startColor = formsGradientView.StartColor;
            var startColorComponents = startColor.ToCGColor().Components;

            var middleColor = formsGradientView.MiddleColor;
            var middleColorComponents = middleColor.ToCGColor().Components;

            var endColor = formsGradientView.EndColor;
            var endColorComponents = endColor.ToCGColor().Components;

            nfloat[] colorComponents = {
                startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3],
                middleColorComponents[0], middleColorComponents[1], middleColorComponents[2], middleColorComponents[3],
                endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3]
            };

            nfloat[] locations = { 0f, 0.5f, 1f };

            var gradient = new CGGradient(colorSpace, colorComponents, locations);

            var startPoint = new CGPoint(0, NativeView.Bounds.Height);
            var endPoint = new CGPoint(NativeView.Bounds.Width, NativeView.Bounds.Height);

            currentContext.DrawLinearGradient(gradient, startPoint, endPoint, CGGradientDrawingOptions.None);
            currentContext.RestoreState();

        }
    }
}

相关问题