Andy Donegan
Andy Donegan

Reputation: 915

.Net Maui Switch visual state manager will not change OnColor for Off state

Just implementing a switch into a display which has a black background on Android.

Added a Switch managed to set OnColor and ThumbColor for On State and Thumbcolor for Off State, but no matter were I tinker I can not set the Oncolor for the off state using visual state manager (hope that makes sense).

As you can see in the image below, the on State is green, the off state shows nothing it melds into the black background. I want to set that as grey.

enter image description here

My Switch

<Switch IsToggled="True" Style="{StaticResource ToggleSwitch}">

In My Styles.xaml I have added my custom style.

    <Style x:Key ="ToggleSwitch" TargetType="Switch">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="On">
                        <VisualState.Setters>
                            <Setter Property="OnColor"
                            Value="Green" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Off">
                        <VisualState.Setters>
                            <Setter Property="OnColor"
                            Value="Gray" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>

I have seen other answers suggesting changing Background and Backgroundcolor, this is not the answer as the background has to be black. No matter what I try I can not change the off state color at all.

Any suggestions/pointers as always appreciated.

Reference: .NET MAUI: Change off color of switch <-- This answer is no good at all.

https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/switch#switch-visual-states

https://learn.microsoft.com/en-us/dotnet/maui/user-interface/visual-states

contemplating using a custom solution at this rate :- https://github.com/IeuanWalker/Maui.Switch

But would much rather use native or as near as possible to native.

Thanks in Advance.

Upvotes: 1

Views: 1916

Answers (2)

Morse
Morse

Reputation: 9115

We can achieve this by using SwitchHandler

Add variables to store On and Thumb colors from Maui Switch

private Color? _onColor;
private Color? _thumbColor;

Replace Mapping

Mapper.ReplaceMapping<Switch, ISwitchHandler>("TrackColor", SwitchColorMapper);

Implementation of mapper

private void SwitchColorMapper(ISwitchHandler handler, Switch view)
{
    MapTrackColor(handler, view);

    var platformView = handler.PlatformView;
    _onColor = view.OnColor;
    _thumbColor = view.ThumbColor;

    platformView.CheckedChange -= OnCheckedChange;
    platformView.CheckedChange += OnCheckedChange;

    if (platformView is null || view.IsEnabled is false)
    {
        return;
    }

    SetColors(ref platformView);
}

private void SetColors(ref SwitchCompat switchCompat)
{
    if (_onColor == null || _thumbColor == null || switchCompat.Enabled is false)
    {
        return;
    }
    if (BlendModeCompat.SrcAtop != null)
    {
        if (switchCompat.Checked)
        {
            var thumbColorFilter = BlendModeColorFilterCompat.CreateBlendModeColorFilterCompat(_onColor.ToAndroid(), BlendModeCompat.SrcAtop);
            if (thumbColorFilter is not null && switchCompat.ThumbDrawable is not null)
            {
                switchCompat.ThumbDrawable.SetColorFilter(thumbColorFilter);
            }
            var trackColorFilter = BlendModeColorFilterCompat.CreateBlendModeColorFilterCompat(_thumbColor.ToAndroid(), BlendModeCompat.SrcAtop);
            if (trackColorFilter is not null && switchCompat.TrackDrawable is not null)
            {
                switchCompat.TrackDrawable.SetColorFilter(trackColorFilter);
            }
        }
        else
        {
            var offColor = _onColor.MultiplyAlpha(0.75f);//Use any
            var disabledColor = Colors.Grey;

            var thumbColorFilter = BlendModeColorFilterCompat.CreateBlendModeColorFilterCompat(appSecondaryColor.ToAndroid(), BlendModeCompat.SrcAtop);
            if (thumbColorFilter is not null && switchCompat.ThumbDrawable is not null)
            {
                switchCompat.ThumbDrawable.SetColorFilter(thumbColorFilter);
            }
            var trackColorFilter = BlendModeColorFilterCompat.CreateBlendModeColorFilterCompat(disabledColor.ToAndroid(), BlendModeCompat.SrcAtop);
            if (trackColorFilter != null)
            {
                switchCompat.TrackDrawable?.SetColorFilter(trackColorFilter);
            }
        }
    }
}

private void OnCheckedChange(object? sender, CompoundButton.CheckedChangeEventArgs e)
{
    if (sender is SwitchCompat switchCompat && _onColor != null && _thumbColor != null)
    {
        SetColors(ref switchCompat);
    }
}

Upvotes: 0

Alexandar May - MSFT
Alexandar May - MSFT

Reputation: 10063

No matter what I try I cannot change the Off state color at all.

This is because natively Switch only has OnColor Property which can only get or set the color of the switch when it is in the On position. So it would be perfect when there would be a BindableProperty OffColor to set for Switch.

However, you can raise a feature request:https://github.com/dotnet/maui/issues/new/choose for adding a BindableProperty OffColor to set for Switch.

As an alternative workaround, you can use the custom solution as you mentioned:https://github.com/IeuanWalker/Maui.Switch. I checked the sample code, you can change the Off state color via CustomSwitch_SwitchPanUpdate method:

static void CustomSwitch_SwitchPanUpdate(CustomSwitch customSwitch, SwitchPanUpdatedEventArgs e) 
{
       //Switch Color Animation
        Color fromSwitchColor = e.IsToggled ? Color.FromArgb("#6200ee") : Color.FromArgb("#fafafa");
        Color toSwitchColor = e.IsToggled ? Color.FromArgb("#fafafa") : Color.FromArgb("#6200ee");

        Color fromColor = e.IsToggled ? Color.FromArgb("#00ff00") : Color.FromArgb("#808080");
        Color toColor = e.IsToggled ? Color.FromArgb("#808080") : Color.FromArgb("#00ff00");

        double t = e.Percentage * 0.01;

        customSwitch.KnobBackgroundColor = ColorAnimationUtil.ColorAnimation(fromSwitchColor, toSwitchColor, t);
        customSwitch.BackgroundColor = ColorAnimationUtil.ColorAnimation(fromColor, toColor, t);
}

Output which has a black background:

enter image description here

Upvotes: 3

Related Questions