且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

开关不遵守样式 OnColor 设置

更新时间:2023-10-01 23:53:46

感谢一些谷歌搜索,并编写自定义渲染器:在关闭"状态下更改 UISwitch 的颜色;状态https://forums.xamarin.com/discussion/62450/how-can-i-customize-the-color-in-switchhttps://blog.wislon.io/posts/2017/05/15/xamforms-change-switch-color

Thanks to some googling, and writing a custom renderer: Change color of UISwitch in "off" state https://forums.xamarin.com/discussion/62450/how-can-i-customize-the-color-in-switch and https://blog.wislon.io/posts/2017/05/15/xamforms-change-switch-colour

解决方案如下:创建新的 CustomSwitch 控件,它将添加一个名为 OffColor 的新 Color 属性,如下所示:

The solution is as follows: Create new CustomSwitch control which will add a new Color property called OffColor as so:

public class CustomSwitch : Switch
    {
        public static readonly BindableProperty OffColorProperty = 
            BindableProperty.Create(nameof(CustomSwitch), typeof(Color), typeof(CustomSwitch));

        public CustomSwitch()
        {
            OffColor = Color.Transparent;
        }

        public Color OffColor {
            get => (Color) GetValue(OffColorProperty);
            set => SetValue(OffColorProperty, value);
        }
    }

通过创建 Android 和 iOS 渲染器来关注此应用:

Follow this app by creating both an Android and iOS renderer:

安卓:

public class CustomSwitchRenderer : SwitchRenderer
    {
        public CustomSwitchRenderer(Context context): base(context) { }

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

            if(Control == null)
            {
                return;
            }

            var element = (CustomSwitch) Element;

            if(!element.IsToggled)
            {
                Control.TrackTintList = ColorStateList.ValueOf(element.OffColor.ToAndroid());
            } 
        }
    }

iOS:

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

            if(Control == null)
            {
                return;
            }

            var element = (CustomSwitch) Element;
            
            var maskView = new UIView(Control.Frame)
            {
                BackgroundColor = element.IsToggled ? element.OnColor.ToUIColor() : element.OffColor.ToUIColor(),
                ClipsToBounds = true
            };

            maskView.Layer.CornerRadius = Control.Frame.Height / 2;

            Control.MaskView = maskView; 

            if(!element.IsToggled)
            {
                Control.TintColor = element.OffColor.ToUIColor();
                Control.BackgroundColor = element.OffColor.ToUIColor();
                
            } else
            {
                Control.TintColor = element.OnColor.ToUIColor();
                Control.OnTintColor = element.OnColor.ToUIColor();
                Control.BackgroundColor = element.OnColor.ToUIColor();
            }

        }

iOS 涉及更多,因为您几乎必须创建与 TrackTintList 等效的 Android,因为对于 iOS,TintColor 所做的只是将颜色应用于开关的边框.面具在那里相应地填写.

iOS is a bit more involved since you pretty much have to create the Android equivalent of the TrackTintList because for iOS all that TintColor does is just apply the color to the border of the switch. The mask is there to fill it in accordingly.

最后,保持使用 Style 资源字典的精神,更新样式如下:

Finally, maintaining the spirit of using a Style resource dictionary, update the style as follows:

<Style x:Key="SwitchThemeMomentum" TargetType="customcontrols:CustomSwitch">
        <Setter Property="IsToggled" Value="{Binding MomentumToggled, Mode=TwoWay}"/>
        <Style.Triggers>
            <DataTrigger TargetType="customcontrols:CustomSwitch" Binding="{Binding MomentumToggled, Mode=TwoWay}" Value="True">
                <Setter Property="ThumbColor" Value="{StaticResource Green}"/>
                <Setter Property="OffColor" Value="Transparent" />
                <Setter Property="OnColor" Value="{StaticResource SwitchOn}" />
                <Setter Property="IsToggled" Value="True" />
            </DataTrigger>
            <DataTrigger TargetType="customcontrols:CustomSwitch" Binding="{Binding MomentumToggled, Mode=TwoWay}" Value="False">
                <Setter Property="ThumbColor" Value="{StaticResource LightGray}" />
                <Setter Property="OffColor" Value="{StaticResource Gray80}" />
                <Setter Property="IsToggled" Value="False" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

重要提示:请注意我们如何将 TargetType 更新为我们的 CustomSwitch 而不是默认的 Switch;这是因为默认的 Switch 控件显然缺少 OffColor 属性.

Important: Note how we update the TargetType to be our CustomSwitch instead of a default Switch; this is because the default Switch control obviously lacks a OffColor property.