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

时间:2018-01-31 08:23:11

标签: c# xamarin xamarin.forms

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

Stepper control

有没有人知道如何通过在XAML中设置新颜色来为步进器的iOS和Android版本更改蓝色到红色?请注意,最后的需求被添加到赏金的文本中。感谢

5 个答案:

答案 0 :(得分:7)

可以使用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>
        <StackLayout 
            HorizontalOptions="Center"
            VerticalOptions="Center">

            <local:RedStepper/>
            <Stepper
                local:StepperColorEffect.Color="Red"/>

        </StackLayout>
    </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)
        {
            switch (bindable)
            {
                case Stepper stepper:
                    RemoveEffect(stepper);
                    stepper.Effects.Add(new StepperColorRoutingEffect());
                    break;
            }
        }

        static void RemoveEffect(Stepper entry)
        {
            var effectToRemoveList = entry.Effects.Where(e => e is StepperColorRoutingEffect).ToList();

            foreach (var entryReturnTypeEffect in effectToRemoveList)
                entry.Effects.Remove(entryReturnTypeEffect);
        }
    }

    class StepperColorRoutingEffect : RoutingEffect
    {
        public StepperColorRoutingEffect() : base("CustomStepper.StepperColorEffect")
        {
        }
    }
}

iOS PlatformEffect

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

        protected override void OnDetached()
        {
            if (Element is Stepper element && Control is UIStepper control)
                control.TintColor = UIColor.Blue;
        }
    }
}

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

截图

的Android

enter image description here

的iOS

enter image description here

答案 1 :(得分: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);
    }
}

对Android设备的影响:

enter image description here

答案 2 :(得分:0)

您需要创建自定义渲染器。查看源代码,iOS上的步进器的原生控件为UIStepper,而Android上的原始控件实际上是带有两个按钮的水平LinearLayout。因此,对于Android,自定义渲染器应更新按钮的背景颜色,而在iOS上,它们似乎是图标,因此请尝试更改TintColor的{​​{1}}。

答案 3 :(得分:0)

这是我的解决方案,也参考@ 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         {             得到{返回Element作为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         {             得到{返回Element作为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();
    }
}

}

答案 4 :(得分:-1)

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

通用文件:

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

        }
    }
}

Andoid

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