【问题标题】:How can I change the colors of a stepper for iOS and Android?如何更改 iOS 和 Android 步进器的颜色?
【发布时间】:2018-01-31 08:23:10
【问题描述】:

我的代码使用如下所示的步进器:

如何通过在 XAML 中设置新颜色,将 iOS 和 Android 版本步进器的颜色从蓝色更改为红色?

【问题讨论】:

    标签: c# xamarin xamarin.forms


    【解决方案1】:

    这是我的解决方案,也参考了@Alan2 的回答。

    Xamarin.Forms

        public class StepperExtend : Stepper
    {
        public static readonly BindableProperty ColorProperty =
            BindableProperty.Create(
                nameof(Color),
                typeof(Color),
                typeof(StepperExtend),
                Color.Default);
    
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }
    }
    

    Xamarin.Android

    [assembly:ExportRenderer(typeof(StepperExtend), typeof(StepperExtendRenderer))]
    

    命名空间 HydroUkPoc.Frontend.Forms.Droid.Renderer { 公共类 StepperExtendRenderer : StepperRenderer { StepperExtend FormElement { 获取 { 作为 StepperExtend 返回元素; } }

        protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                UpdateColor();
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == StepperExtend.ColorProperty.PropertyName)
            {
                UpdateColor();
            }
            else
            {
                base.OnElementPropertyChanged(sender, e);
            }
        }
    
        private void UpdateColor()
        {
            Control.GetChildAt(0).Background.SetColorFilter(FormElement.Color.ToAndroid(), PorterDuff.Mode.Multiply);
            Control.GetChildAt(1).Background.SetColorFilter(FormElement.Color.ToAndroid(), PorterDuff.Mode.Multiply);
        }
    }
    

    }

    Xamarin.iOS

    [assembly:ExportRenderer(typeof(StepperExtend), typeof(StepperExtendRenderer))]
    

    命名空间 HydroUkPoc.Frontend.Forms.iOS.Renderer { 公共类 StepperExtendRenderer : StepperRenderer { StepperExtend FormElement { 获取 { 作为 StepperExtend 返回元素; } }

        protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                UpdateColor();
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == StepperExtend.ColorProperty.PropertyName)
            {
                UpdateColor();
            }
            else
            {
                base.OnElementPropertyChanged(sender, e);
            }
        }
    
        private void UpdateColor()
        {
            Control.TintColor = FormElement.Color.ToUIColor();
        }
    }
    

    }

    【讨论】:

      【解决方案2】:

      这可以使用Effects 来完成。

      代码

      我在这里创建了一个示例应用程序:https://github.com/brminnick/CustomStepper

      在 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" 
          x:Class="CustomStepper.StepperPage"
          xmlns:local="clr-namespace:CustomStepper">
          
          <ContentPage.Content>
              <Stepper
                  HorizontalOptions="Center"
                  VerticalOptions="Center"
                  local:StepperColorEffect.Color="Red"/>
          </ContentPage.Content>
      </ContentPage>
      

      步进色彩效果

      using System.Linq;
      
      using Xamarin.Forms;
      
      namespace CustomStepper
      {
          public static class StepperColorEffect
          {
              public static readonly BindableProperty ColorProperty =
                  BindableProperty.CreateAttached(nameof(Color),
                      typeof(Color),
                      typeof(Stepper),
                      Color.Gray,
                      propertyChanged: OnStepperColorChanged);
      
              public static Color GetColor(BindableObject view) => (Color)view.GetValue(ColorProperty);
      
              public static void SetColor(BindableObject view, Color value) => view.SetValue(ColorProperty, value);
      
              static void OnStepperColorChanged(BindableObject bindable, object oldValue, object newValue) => UpdateEffect(bindable);
      
              static void UpdateEffect(BindableObject bindable)
              {
                  var stepper = (Stepper)bindable:
                  RemoveEffect(stepper);
                  stepper.Effects.Add(new StepperColorRoutingEffect());
              }
      
              static void RemoveEffect(Stepper entry)
              {
                  var effectToRemoveList = entry.Effects.OfType<StepperColorRoutingEffect>();
      
                  foreach (var entryReturnTypeEffect in effectToRemoveList)
                      entry.Effects.Remove(entryReturnTypeEffect);
              }
          }
      
          class StepperColorRoutingEffect : RoutingEffect
          {
              public StepperColorRoutingEffect() : base("CustomStepper.StepperColorEffect")
              {
              }
          }
      }
      

      iOS 平台效果

      using UIKit;
      
      using Xamarin.Forms;
      using Xamarin.Forms.Platform.iOS;
      
      using CustomStepper.iOS;
      
      [assembly: ResolutionGroupName("CustomStepper")]
      [assembly: ExportEffect(typeof(StepperColorEffect), nameof(StepperColorEffect))]
      namespace CustomStepper.iOS
      {
          public class StepperColorEffect : PlatformEffect
          {
              protected override void OnAttached()
              {
                  if (Element is Stepper element && Control is UIStepper control)
                  {
                      control.TintColor = CustomStepper.StepperColorEffect.GetColor(element).ToUIColor();
                      control.SetIncrementImage(Control.GetIncrementImage(UIControlState.Normal), UIControlState.Normal);
                      control.SetDecrementImage(Control.GetDecrementImage(UIControlState.Normal), UIControlState.Normal);
                  }
              }
      
              protected override void OnDetached()
              {
                  if (Element is Stepper element && Control is UIStepper control)
                  {
                      control.TintColor = UIColor.Blue;
                      control.SetIncrementImage(Control.GetIncrementImage(UIControlState.Normal), UIControlState.Normal);
                      control.SetDecrementImage(Control.GetDecrementImage(UIControlState.Normal), UIControlState.Normal);
                  }
              }
          }
      }
      

      Android 平台效果

      using Android.Widget;
      using Android.Graphics;
      
      using Xamarin.Forms;
      using Xamarin.Forms.Platform.Android;
      
      using CustomStepper.Droid;
      
      [assembly: ResolutionGroupName("CustomStepper")]
      [assembly: ExportEffect(typeof(StepperColorEffect), nameof(StepperColorEffect))]
      namespace CustomStepper.Droid
      {
          public class StepperColorEffect : PlatformEffect
          {
              protected override void OnAttached()
              {
                  if (Element is Stepper element && Control is LinearLayout control)
                  {
                      control.GetChildAt(0).Background.SetColorFilter(CustomStepper.StepperColorEffect.GetColor(element).ToAndroid(), PorterDuff.Mode.Multiply);
                      control.GetChildAt(1).Background.SetColorFilter(CustomStepper.StepperColorEffect.GetColor(element).ToAndroid(), PorterDuff.Mode.Multiply);
                  }
              }
      
              protected override void OnDetached()
              {
                  if (Element is Stepper element && Control is LinearLayout control)
                  {
                      control.GetChildAt(0).Background.SetColorFilter(Xamarin.Forms.Color.Gray.ToAndroid(), PorterDuff.Mode.Multiply);
                      control.GetChildAt(1).Background.SetColorFilter(Xamarin.Forms.Color.Gray.ToAndroid(), PorterDuff.Mode.Multiply);
                  }
              }
          }
      }
      

      截图

      安卓

      iOS

      【讨论】:

      • 感谢您的帮助。问题中概述的还有一件事。你能做到吗,这样我就可以将 Color="Red" 或 Color="Black" 之类的东西添加到 XAML 中以用于自定义步进器。我不想将颜色硬编码到渲染器中。
      • 嘿@Alan2!我已经更新了使用效果的答案。以后请不要编辑和更改您的问题,因为这对于试图回答您问题的开发人员来说是浪费时间。我花了一个多小时解决你原来的问题。然后您编辑了原始问题,我又花了 45 分钟解决了您的第二个问题。下次,请在 StackOverflow 上提出第二个问题。
      • 抱歉,我想您可能没有注意到赏金文本中提到了更改 XAML 的必要性。它是这样说的:“我可以在 XAML 中添加诸如 Color="Red" 或 Color="Black" 之类的内容”。我所希望的是像
      【解决方案3】:

      如何更改 iOS 和 Android 步进器的颜色?

      在您的Xamarin.Android 项目中,您可以创建一个自定义矢量可绘制对象并将其用作背景,以实现与您在上面发布的图片相同的外观。

      button_selector.xmlbutton_border.xml 文件放在您的Android Resources\drawable 文件夹中:

      button_selector.xml

      <?xml version="1.0" encoding="utf-8"?>
      <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@color/colorAccent" android:state_pressed="true"/>
        <item android:drawable="@color/colorPrimaryDark" android:state_focused="true"/>
        <item android:drawable="@drawable/button_border"/>
      </selector>
      

      button_border.xml:

      <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
             android:shape="rectangle" >
      
        <solid android:color="#00FFFFFF" />
        <corners android:radius="5dp" />
        <stroke
          android:width="2dp"
          android:color="#FFFFFF" />
      
      </shape>
      

      在你的ExtStepperRenderer:

      protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
      {
          base.OnElementChanged(e);
          MyStepper s = Element as MyStepper;
      
          if (Control != null)
          {
              var button = Control.GetChildAt(0) as Android.Widget.Button;
              button.SetTextColor(s.MyColor.ToAndroid());
              button.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.button_selector, null));
              button.Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
      
              var button2 = Control.GetChildAt(1) as Android.Widget.Button;
              button2.SetTextColor(s.MyColor.ToAndroid());
              button2.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.button_selector, null));
              button2.Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
          }
      }
      

      在安卓设备上的效果:

      【讨论】:

        【解决方案4】:

        我想出了一个简单的解决方案。

        普通文件:

        using Xamarin.Forms;
        
        namespace Japanese
        {
            public class ExtStepper : Stepper
            {
        
                public static readonly BindableProperty ColorProperty =
           BindableProperty.Create(nameof(Color),
               typeof(Color), typeof(ExtStepper),
               Color.Default);
        
                public Color StepperColor
                {
                    get { return (Color)GetValue(ColorProperty); }
                    set { SetValue(ColorProperty, value); }
                }
        
            }
        }
        

        iOS

        using Xamarin.Forms;
        using Japanese;
        using Japanese.iOS;
        using Xamarin.Forms.Platform.iOS;
        
        [assembly: ExportRenderer(typeof(ExtStepper), typeof(ExtStepperRenderer))]
        namespace Japanese.iOS
        {
            public class ExtStepperRenderer : StepperRenderer
            {
                protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
                {
                    base.OnElementChanged(e);
                    ExtStepper s = Element as ExtStepper;
        
                    if (Control != null)
                        Control.TintColor = s.StepperColor.ToUIColor();
        
                }
            }
        }
        

        机器人

        using Xamarin.Forms;
        using Xamarin.Forms.Platform.Android;
        using Japanese;
        using Japanese.Droid;
        using Android.Content;
        using Android.Graphics;
        
        [assembly: ExportRenderer(typeof(ExtStepper), typeof(ExtStepperRenderer))]
        namespace Japanese.Droid
        {
            public class ExtStepperRenderer : StepperRenderer
            {
                public ExtStepperRenderer(Context context) : base(context)
                {
                }
        
                protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
                {
                    base.OnElementChanged(e);
                    ExtStepper s = Element as ExtStepper;
        
                    if (Control != null)
                    {
                        Control.GetChildAt(0).Background.SetColorFilter(s.StepperColor.ToAndroid(), PorterDuff.Mode.Multiply);
                        Control.GetChildAt(1).Background.SetColorFilter(s.StepperColor.ToAndroid(), PorterDuff.Mode.Multiply);
                    }
        
        
                }
            }
        }
        

        XAML

        <local:ExtStepper StepperColor="Red" x:Name="rptStepper
        

        【讨论】:

        • 嘿@Alan2!如果您只分配一次颜色,这将起作用。如果您尝试再次更新 Color 或将其绑定到 ViewModel,Stepper Color 将不会更新。
        【解决方案5】:

        您需要创建一个自定义渲染器。查看源代码,iOS 上的 Stepper 的本机控件是 UIStepper,而在 Android 上它实际上是带有两个按钮的水平 LinearLayout。所以对于Android,自定义渲染器应该更新按钮的背景颜色,而在iOS上,它们看起来是图标,所以尝试改变UIStepperTintColor

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-12
          • 1970-01-01
          • 2021-06-26
          • 1970-01-01
          • 1970-01-01
          • 2019-04-19
          • 2019-07-01
          • 1970-01-01
          相关资源
          最近更新 更多