Skip to content

Conversation

@kubaflo
Copy link
Contributor

@kubaflo kubaflo commented Feb 3, 2024

Description of Change

The initial respect for the ThumbColor and OnColor properties was
overridden by values set within visual states each time the switcher changed
its state. I recommend verifying whether these values have been overwritten,
and if so, exclusively utilizing the new properties.

Issues Fixed

Fixes #19883

Fixes #19380

Before
Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-02-03.at.02.06.58.mp4
After
Screen.Recording.2024-02-04.at.00.25.46.mov

@kubaflo kubaflo requested a review from a team as a code owner February 3, 2024 23:45
@kubaflo kubaflo requested review from PureWeen and rmarinho February 3, 2024 23:45
@ghost ghost added the community ✨ Community Contribution label Feb 3, 2024
@ghost
Copy link

ghost commented Feb 3, 2024

Hey there @kubaflo! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@kubaflo kubaflo force-pushed the onColor-thumbColor-switcher-fix branch from 850ee01 to 627ee31 Compare February 3, 2024 23:52
@jsuarezruiz
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Feb 5, 2024
@BlueRaja
Copy link

BlueRaja commented Mar 5, 2024

Any reason this has been sitting unmerged for a month? Seems like a pretty basic and critical bug to be sitting unfixed for months now

@rmarinho
Copy link
Member

rmarinho commented Mar 5, 2024

/azp run MAUI-UITests-public

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MAUIoxo
Copy link

MAUIoxo commented Mar 19, 2024

@jsuarezruiz @rmarinho
Just wanted to ask why this has not been merged to main for such a long time now? Is there anything missing? Still waiting for this to be fixed. And this fix was provided long time ago. Any reason for that?

@rmarinho
Copy link
Member

@MAUIoxo we are not sure this is correct fix to work with VSM. we were discussing internally.

@MAUIoxo
Copy link

MAUIoxo commented Mar 20, 2024

Thanks for the update on this! So, at least we know why it is parked 😊

@elparasite
Copy link

@MAUIoxo we are not sure this is correct fix to work with VSM. we were discussing internally.

Hi, was the discussion effective ?
This is an unbearable suspense.

@MAUIoxo
Copy link

MAUIoxo commented Apr 13, 2024

@MAUIoxo we are not sure this is correct fix to work with VSM. we were discussing internally.

Hi, was the discussion effective ? This is an unbearable suspense.

Yes it was - I found out that this issue is going to take forever to be fixed and probably no one is going to deal with a solution anytime soon, so I guess I'll just have to come up with my own solution 😅

Here is an example of a CustomSwitch with a CustomSwitchHandler that allows me to set the OnColor and ThumbColor as in a normal Switch in XAML and map the states of IsToggled, OnColor and ThumbColor to the corresponding properties of the newly created iOS UISwitch. This is just a possible solution for iOS. I've tested it with scrolling also as re-drawing View elements also has to be updated correspondingly. At least it works for me and tested with <MauiVersion>8.0.40-nightly.10485</MauiVersion>.


CustomSwitch:

namespace OptimizerApp.Pages.Views.Controls.CustomSwitch
{
    public class CustomSwitch : Switch
    {
        
    }
}

Integration in XAML Code:

...
<constrols:CustomSwitch ... IsToggled="{Binding IsSelected, Mode=TwoWay}" ThumbColor="{StaticResource Gray100}" OnColor="{StaticResource DarkOrange1}" />
...

CustomSwitchHandler:

#if IOS

using OptimizerApp.Pages.Views.Controls.CustomSwitch;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using UIKit;

namespace OptimizerApp.Platforms.iOS.ControlHandlers
{
    public partial class CustomSwitchHandler : ViewHandler<CustomSwitch, UISwitch>
    {
        /// <summary>
        /// Configures property mappings for the CustomSwitch and binds UI properties to platform-specific handlers.
        /// This mapper directs changes in MAUI's CustomSwitch properties to appropriate methods that
        /// update the native iOS UISwitch, ensuring UI consistency and responsiveness:
        /// - 'IsToggled' updates the switch's active state.
        /// - 'OnColor' adjusts the color when the switch is on.
        /// - 'ThumbColor' changes the color of the switch thumb.
        /// These mappings ensure that the visual state of the UISwitch is synchronized with the CustomSwitch.
        /// </summary>
        public static PropertyMapper<CustomSwitch, CustomSwitchHandler> CustomSwitchMapper = new PropertyMapper<CustomSwitch, CustomSwitchHandler>
        {
            [nameof(CustomSwitch.IsToggled)] = MapIsToggled,
            [nameof(CustomSwitch.OnColor)] = MapOnColor,
            [nameof(CustomSwitch.ThumbColor)] = MapThumbColor
        };

        
        public CustomSwitchHandler() : base(CustomSwitchMapper)
        {
        }

        /// <summary>
        /// Creates the native UISwitch view
        /// </summary>
        /// <returns>The newly created UISwitch instance</returns>
        protected override UISwitch CreatePlatformView()
        {
            return new UISwitch();
        }

        /// <summary>
        /// Connects this handler to the UISwitch, setting up event handlers and initial state
        /// </summary>
        /// <param name="platformView">The UISwitch to connect</param>
        protected override void ConnectHandler(UISwitch platformView)
        {
            base.ConnectHandler(platformView);

            platformView.ValueChanged += OnSwitchValueChanged;
            platformView.On = VirtualView.IsToggled;    // Synchronize the UISwitch's state with the IsToggled property of the MAUI CustomSwitch

            SetSwitchColors(platformView, VirtualView);
        }

        /// <summary>
        /// Disconnects this handler from the UISwitch and clean up the event handlers
        /// </summary>
        /// <param name="platformView">The UISwitch to disconnect</param>
        protected override void DisconnectHandler(UISwitch platformView)
        {
            platformView.ValueChanged -= OnSwitchValueChanged;
            base.DisconnectHandler(platformView);

            // Reset UI properties
            ResetSwitchColors(platformView);
        }

        /// <summary>
        /// Sets the ThumbColor and OnTintColor of the UISwitch based on the properties of the CustomSwitch
        /// </summary>
        /// <param name="uiSwitch">The native UISwitch</param>
        /// <param name="customSwitch">The MAUI CustomSwitch</param>
        private static void SetSwitchColors(UISwitch uiSwitch, CustomSwitch customSwitch)
        {
            // Setting the null-values will set it to default values
            uiSwitch.ThumbTintColor = customSwitch.ThumbColor != default(Color) ? customSwitch.ThumbColor.ToPlatform() : null;
            uiSwitch.OnTintColor = customSwitch.OnColor != default(Color) ? customSwitch.OnColor.ToPlatform() : null;
        }

        /// <summary>
        /// Resets the ThumbColor and OnTintColor properties of the UISwitch to defaults
        /// </summary>
        /// <param name="uiSwitch">The UISwitch to reset</param>
        private void ResetSwitchColors(UISwitch uiSwitch)
        {
            uiSwitch.ThumbTintColor = null;
            uiSwitch.OnTintColor = null;
        }

        /// <summary>
        /// Map changes in the OnColor property to the UISwitch
        /// </summary>
        public static void MapOnColor(CustomSwitchHandler handler, CustomSwitch customSwitch)
        {
            if (handler.PlatformView != null)
            {
                handler.PlatformView.OnTintColor = customSwitch.OnColor.ToPlatform();
            }
        }

        /// <summary>
        /// Map changes in the ThumbColor property to the UISwitch
        /// </summary>
        public static void MapThumbColor(CustomSwitchHandler handler, CustomSwitch customSwitch)
        {
            if (handler.PlatformView != null)
            {
                handler.PlatformView.ThumbTintColor = customSwitch.ThumbColor.ToPlatform();
            }
        }

        /// <summary>
        /// Map changes in the IsToggled property to the UISwitch
        /// </summary>
        public static void MapIsToggled(CustomSwitchHandler handler, CustomSwitch customSwitch)
        {
            if (handler.PlatformView != null)
            {
                handler.PlatformView.On = customSwitch.IsToggled;                
                handler.UpdateSwitchColors(handler.PlatformView, customSwitch);     // Update colors when switch is toggled/untoggled
            }
        }

        private void OnSwitchValueChanged(object sender, EventArgs e)
        {
            var uiSwitch = (UISwitch)sender;
            VirtualView.IsToggled = uiSwitch.On;

            UpdateSwitchColors(uiSwitch, VirtualView);
        }

        /// <summary>
        /// Update the OnTintColor and ThumbColor with the colors defined in the customSwitch
        /// </summary>
        private void UpdateSwitchColors(UISwitch uiSwitch, CustomSwitch customSwitch)
        {
            if (uiSwitch.On)
            {
                if (customSwitch.OnColor != default(Color))
                {
                    uiSwitch.OnTintColor = customSwitch.OnColor.ToPlatform();
                }
            }

            if (customSwitch.ThumbColor != default(Color))
            {
                uiSwitch.ThumbTintColor = customSwitch.ThumbColor.ToPlatform();
            }
        }
    }
}

#endif

MauiProgram.cs:

...
#if IOS
using OptimizerApp.Platforms.iOS.ControlHandlers;
#endif
...

var builder = MauiApp.CreateBuilder();
builder
    .UseMauiApp<App>()
    ...
    .ConfigureMauiHandlers(handlers =>
    {
        // The handler will only be called if the target platform is iOS
#if IOS
        handlers.AddHandler<CustomSwitch, CustomSwitchHandler>();
#endif
    });
...

CustomSwitchHandler



BUT:
It even does not have to be this full blown implementation. As I found out, it was sufficient to just use this simple CustomSwitch above which simply derives from Switch and use this in XAML with corresponding Color settings. See before and after on iOS and Android :


Simple Switch iOS:

SwitchiOS


CustomSwitch iOS:

CustomSwitchiOS



Simple Switch Android:

SwitchAndroid


CustomSwitch Android:

CustomSwitchHandlerAndroid


@Eilon Eilon removed the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 10, 2024
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 13, 2024
@jsuarezruiz
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@AncientLust
Copy link

For me the simplest solution was to go into Resources/Styles/Styles.xaml, search for "Switch" and set colors you need both for dark and white theme.

@divyesh008
Copy link

divyesh008 commented Aug 14, 2024

I have tried this, but its not working. ThumbColor not getting changed even if set using DataTrigger.

Screen.Recording.2024-08-14.at.11.01.17.PM.mov

@jsuarezruiz
Copy link
Contributor

I have tried this, but its not working. ThumbColor not getting changed even if set using DataTrigger.

Screen.Recording.2024-08-14.at.11.01.17.PM.mov

@kubaflo

@kubaflo kubaflo force-pushed the onColor-thumbColor-switcher-fix branch from 464b341 to e2ebe3a Compare October 31, 2024 14:16
@kubaflo
Copy link
Contributor Author

kubaflo commented Oct 31, 2024

@jsuarezruiz could you please /azp

@divyesh008 can you please try again with changes I've just added

@jsuarezruiz
Copy link
Contributor

/rebase

@github-actions github-actions bot force-pushed the onColor-thumbColor-switcher-fix branch from e2ebe3a to 9fb6ad9 Compare November 15, 2024 09:23
@jsuarezruiz
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@kubaflo kubaflo force-pushed the onColor-thumbColor-switcher-fix branch from 9fb6ad9 to 597f6bc Compare March 8, 2025 01:15
@kubaflo
Copy link
Contributor Author

kubaflo commented Mar 8, 2025

Any reason this has been sitting unmerged for a month? Seems like a pretty basic and critical bug to be sitting unfixed for months now

It's the anniversary of your comment 😂

@MAUIoxo
Copy link

MAUIoxo commented Mar 8, 2025

Any reason this has been sitting unmerged for a month? Seems like a pretty basic and critical bug to be sitting unfixed for months now

It's the anniversary of your comment 😂

The 7th year is always the critical one 😅😂

@kubaflo kubaflo self-assigned this Mar 8, 2025
Copy link
Member

@mattleibow mattleibow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picking option red because I wonder if this is fixed or requires a different fix to work with the style specificities.

Also, could the "not working" be the case because the is no Normal style to fall back to?

public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Switch), null,
propertyChanged: (bindable, oldValue, newValue) =>
{
((IView)bindable)?.Handler?.UpdateValue(nameof(ISwitch.ThumbColor));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't this property automatically fire this update?

Comment on lines 23 to +24
((IView)bindable)?.Handler?.UpdateValue(nameof(ISwitch.TrackColor));

((IView)bindable)?.Handler?.UpdateValue(nameof(ISwitch.ThumbColor));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe with the new work @StephaneDelcroix did with style specificities, this is no longer needed and the style should swap?

@mattleibow
Copy link
Member

/rebase

@github-actions github-actions bot force-pushed the onColor-thumbColor-switcher-fix branch from 597f6bc to 242b708 Compare May 13, 2025 16:37
@kubaflo
Copy link
Contributor Author

kubaflo commented May 13, 2025

@mattleibow you're right. The changes are no longer needed, so I'm closing this PR

@kubaflo kubaflo closed this May 13, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Jun 13, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Switch] Switch Toggle: OnColor Not set correctly and ThumbColor Not Reset When Toggled Off Switch control ignores OnColor and ThumbColor

10 participants