如何在Xamarin Forms工具栏和UINavigationBar中添加渐变

14

我正在创建一个适用于Android和iOS操作系统的Xamarin Forms跨平台应用程序。 我需要为这两个操作系统的AppBars(在Android中称为ToolBar,在iOS中称为UINavigationBar)添加渐变。 有没有办法实现这一点? 请帮我解决问题...无论是任何内容。

输入图像描述


1
最后的办法是使用图像,但我强烈不建议这样做。 - LeRoy
@LeRoy,你有没有想过如何将图像应用到Appbar中? - Dehan Wjiesekara
2个回答

24

你应该使用自定义渲染器,就像这样:

在你的PCL或共享项目中:

public class NavigationPageGradientHeader : NavigationPage
{
    public NavigationPageGradientHeader(Page root) : base(root)
    {
    }
    
    public static readonly BindableProperty RightColorProperty =
      BindableProperty.Create(propertyName: nameof(RightColor),
          returnType: typeof(Color),
          declaringType: typeof(NavigationPageGradientHeader),
          defaultValue: Color.Accent);

    public static readonly BindableProperty LeftColorProperty =
       BindableProperty.Create(propertyName: nameof(LeftColor),
           returnType: typeof(Color),
           declaringType: typeof(NavigationPageGradientHeader),
           defaultValue: Color.Accent);

    public Color RightColor
    {
        get { return (Color)GetValue(RightColorProperty); }
        set { SetValue(RightColorProperty, value); }
    }

    public Color LeftColor
    {
        get { return (Color)GetValue(LeftColorProperty); }
        set { SetValue(LeftColorProperty, value); }
    }
}

[更新]

我花了时间创建了一个示例,你可以在Github中查看。

然后在你的Android项目中:

[assembly: ExportRenderer(typeof(NavigationPageGradientHeader), typeof(NavigationPageGradientHeaderRenderer))]
namespace YournameSpace.Droid
{
    public class NavigationPageGradientHeaderRenderer : NavigationRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
        {
            base.OnElementChanged(e);

            //run once when element is created
            if (e.OldElement != null || Element == null)
            {
            return;
            }

            var control = (NavigationPageGradientHeader)this.Element;
            var context = (MainActivity)this.Context;

            context.ActionBar.SetBackgroundDrawable(new GradientDrawable(GradientDrawable.Orientation.RightLeft, new int[] { control.RightColor.ToAndroid(), control.LeftColor.ToAndroid() }));
        }
    }
}

如果你在MainActivity中使用了FormsAppCompatActivity,只需像这样添加一个gradient中的可绘制对象:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >

  <gradient
      android:angle="180"
      android:centerColor="#26C986"
      android:endColor="#109F8D"
      android:startColor="#36ED81"
      android:type="linear" />

</shape>

然后在您的 Toolbar.axml 文件中调用此可绘制资源:

<android.support.v7.widget.Toolbar
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/toolbar"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/gradient"
   android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
   android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

在您的iOS项目中:

[assembly: ExportRenderer(typeof(NavigationPageGradientHeader), typeof(NavigationPageGradientHeaderRenderer))]
namespace YourNameSpace.iOS
{
    public class NavigationPageGradientHeaderRenderer: NavigationRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            var control = (NavigationPageGradientHeader)this.Element;

            var gradientLayer = new CAGradientLayer();
            gradientLayer.Bounds = NavigationBar.Bounds;
            gradientLayer.Colors = new CGColor[] { control.RightColor.ToCGColor(), control.LeftColor.ToCGColor() };
            gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
            gradientLayer.EndPoint = new CGPoint(1.0, 0.5);

            UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
            gradientLayer.RenderInContext(UIGraphics.GetCurrentContext());
            UIImage image = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();

            NavigationBar.SetBackgroundImage(image, UIBarMetrics.Default);
        }
    }
}

最后在你的 App.xaml.cs 文件中像这样调用该控件:

MainPage = new NavigationPageGradientHeader(new MainPage()) {
     LeftColor = Color.FromHex("#109F8D"),
     RightColor = Color.FromHex("#36ED81")
};

输入图像描述


这个用户的回答让我非常失望。 - Dehan Wjiesekara
8
失望了吗?我正在睡觉,不可能24小时随时待命。因此,我已经提供了一个解决您问题的示例。请查看我的更新。 - Wilson Vargas
能否更改NavigationBar的高度? - Dehan Wjiesekara
2
是的,但您应该为此提出一个新问题 :) - Wilson Vargas
非常聪明,谢谢! - Bryce Friha
显示剩余7条评论

1

我知道这是一个老问题,但现在有一种简单的方法可以使用LinearGradientBrush来解决它。 只需将以下内容添加到您的App.xaml文件中:

   <Application.Resources>
            <Style TargetType="NavigationPage">
                <Setter Property="BarBackground">
                    <LinearGradientBrush StartPoint="0,0"
                                         EndPoint="1,1">
                      <GradientStop Color="#26C986"
                                    Offset="0.25" />
                      <GradientStop Color="#109F8D"
                                    Offset="0.75" />             
                      <GradientStop Color="#36ED81"
                                    Offset="1.0" />
                   </LinearGradientBrush>   
                </Setter>
            </Style>
   </Application.Resources>

我希望这能对某些人有所帮助!祝你有愉快的一天!

1
嗨,@Bryce感谢您的贡献。 - Dehan Wjiesekara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接