Xamarin.Fomrs 用户界面——控件——主题——自定义主题

来源:互联网 发布:linux find size 编辑:程序博客网 时间:2024/05/22 17:47

创建自定义主题

PDF用于离线使用
  • 下载PDF

让我们知道你对此的感受

除了从Nuget软件包(如Light and Dark主题)添加主题之外 ,您还可以创建自己的资源字典主题,您可以在应用程序中引用它。

主题页面 上BoxView显示的三个样式根据两个可下载主题中定义的三个类型进行样式化。

要了解这些工作原理,以下标记将创建一个相当于您可以直接添加到App.xaml的样式。

请注意,Class对于属性Style(而不是在 x:Key 早期版本Xamarin.Forms可用的属性)。

<ResourceDictionary>  <!-- DEFINE ANY CONSTANTS -->  <Color x:Key="SeparatorLineColor">#CCCCCC</Color>  <Color x:Key="iOSDefaultTintColor">#007aff</Color>    <Color x:Key="AndroidDefaultAccentColorColor">#1FAECE</Color>    <OnPlatform                x:TypeArguments="Color"                x:Key="AccentColor"                Android="{ StaticResource AndroidDefaultAccentColorColor }"                iOS="{ StaticResource iOSDefaultTintColor }"            />  <!--  BOXVIEW CLASSES -->  <Style TargetType="BoxView" Class="HorizontalRule">    <Setter Property="BackgroundColor" Value="{ StaticResource SeparatorLineColor }" />    <Setter Property="HeightRequest" Value="1" />  </Style>  <Style TargetType="BoxView" Class="Circle">    <Setter Property="BackgroundColor" Value="{ StaticResource AccentColor }" />    <Setter Property="WidthRequest" Value="34"/>    <Setter Property="HeightRequest" Value="34"/>    <Setter Property="HorizontalOptions" Value="Start" />    <Setter Property="local:ThemeEffects.Circle" Value="True" />  </Style>  <Style TargetType="BoxView" Class="Rounded">    <Setter Property="BackgroundColor" Value="{ StaticResource AccentColor }" />    <Setter Property="HorizontalOptions" Value="Start" />    <Setter Property="BackgroundColor" Value="{ StaticResource AccentColor }" />    <Setter Property="local:ThemeEffects.CornerRadius" Value="4" />  </Style></ResourceDictionary>

你会注意到,Rounded该类引用一个自定义的效果CornerRadius。下面给出了这个效果的代码 - 要正确引用,xmlns必须将自定义 值添加到App.xaml的根元素中:

xmlns:local="clr-namespace:ThemesDemo;assembly=ThemesDemo"

PCL或共享项目中的C#代码

用于创建圆角的代码BoxView使用效果。使用a应用拐角半径,BindableProperty并通过应用效果来实现。该效果需要iOS和Android项目中的平台特定代码(如下所示)。

namemspace ThemesDemo{  public static class ThemeEffects  {  public static readonly BindableProperty CornerRadiusProperty =    BindableProperty.CreateAttached("CornerRadius", typeof(double), typeof(ThemeEffects), 0.0, propertyChanged: OnChanged<CornerRadiusEffect, double>);    private static void OnChanged<TEffect, TProp>(BindableObject bindable, object oldValue, object newValue)              where TEffect : Effect, new()    {        var view = bindable as View;        if (view == null)        {            return;        }        if (EqualityComparer<TProp>.Equals(newValue, default(TProp)))        {            var toRemove = view.Effects.FirstOrDefault(e => e is TEffect);            if (toRemove != null)            {                view.Effects.Remove(toRemove);            }        }        else        {            view.Effects.Add(new TEffect());        }    }    public static void SetCornerRadius(BindableObject view, double radius)    {        view.SetValue(CornerRadiusProperty, radius);    }    public static double GetCornerRadius(BindableObject view)    {        return (double)view.GetValue(CornerRadiusProperty);    }    private class CornerRadiusEffect : RoutingEffect    {        public CornerRadiusEffect()            : base("Xamarin.CornerRadiusEffect")        {        }    }  }}

iOS项目中的C#代码

using System;using Xamarin.Forms;using Xamarin.Forms.Platform.iOS;using CoreGraphics;using Foundation;using XFThemes;namespace ThemesDemo.iOS{    public class CornerRadiusEffect : PlatformEffect    {        private nfloat _originalRadius;        protected override void OnAttached()        {            if (Container != null)            {                _originalRadius = Container.Layer.CornerRadius;                Container.ClipsToBounds = true;                UpdateCorner();            }        }        protected override void OnDetached()        {            if (Container != null)            {                Container.Layer.CornerRadius = _originalRadius;                Container.ClipsToBounds = false;            }        }        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)        {            base.OnElementPropertyChanged(args);            if (args.PropertyName == ThemeEffects.CornerRadiusProperty.PropertyName)            {                UpdateCorner();            }        }        private void UpdateCorner()        {            Container.Layer.CornerRadius = (nfloat)ThemeEffects.GetCornerRadius(Element);        }    }}

Android项目中的C#代码

using System;using Xamarin.Forms.Platform;using Xamarin.Forms.Platform.Android;using Android.Views;using Android.Graphics;namespace ThemesDemo.Droid{    public class CornerRadiusEffect : BaseEffect    {        private ViewOutlineProvider _originalProvider;        protected override bool CanBeApplied()        {            return Container != null && (int)Android.OS.Build.VERSION.SdkInt >= 21;        }        protected override void OnAttachedInternal()        {            _originalProvider = Container.OutlineProvider;            Container.OutlineProvider = new CornerRadiusOutlineProvider(Element);            Container.ClipToOutline = true;        }        protected override void OnDetachedInternal()        {            Container.OutlineProvider = _originalProvider;            Container.ClipToOutline = false;        }        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)        {            base.OnElementPropertyChanged(args);            if (!Attached)            {                return;            }            if (args.PropertyName == ThemeEffects.CornerRadiusProperty.PropertyName)            {                Container.Invalidate();            }        }        private class CornerRadiusOutlineProvider : ViewOutlineProvider        {            private Xamarin.Forms.Element _element;            public CornerRadiusOutlineProvider(Xamarin.Forms.Element element)            {                _element = element;            }            public override void GetOutline(Android.Views.View view, Outline outline)            {                var pixles =                    (float)ThemeEffects.GetCornerRadius(_element) *                    view.Resources.DisplayMetrics.Density;                outline.SetRoundRect(new Rect(0, 0, view.Width, view.Height), (int)pixles);            }        }    }}

概要

可以通过为需要自定义外观的每个控件定义样式来创建自定义主题。应该通过Class资源字典中的不同属性来区分控件的多种样式,然后通过StyleClass在控件上设置属性来应用。

风格还可以利用效果来进一步定制控件的外观。

隐式样式 (不带任何一个x:KeyStyle属性)继续应用于与之匹配的所有控件TargetType