maui icon indicating copy to clipboard operation
maui copied to clipboard

Switch control renders with rectangular frame when toggled

Open gairmuse opened this issue 8 months ago • 2 comments

Description

Using MacCatalyst with the Mac idiom set and the SwitchHandler PreferredStyle = UIKit.UISwitchStyle.Sliding, the switch control is initially drawn correctly but after toggling, is re-drawn with a rectangular frame. The frame is visible in both light and dark modes.

Before Toggle BeforeToggle BeforeToggleLight

After Toggle AfterToggle AfterToggleLight

Steps to Reproduce

Clone and build reproduction project or...

  1. Create new .NET 7 MAUI App using Visual Studio for Mac.
  2. Edit the project file replacing net7.0 with net8.0.
  3. Create global.json with content as shown and place in solution folder.
{
    "sdk": {
      "version": "8.0.100"
    }
} 
  1. Add <PackageReference Include="Microsoft.Maui.Controls" Version="8.0.3" /> to the project file.
  2. Change SupportedOSPlatformVersion for maccatalyst to "15.0".
  3. Edit Info.plist and set UIDeviceFamily values to 1 and 6.
  4. Close and reopen the project.
  5. In the MainPage constructor, add the following.
#if MACCATALYST
        Microsoft.Maui.Handlers.SwitchHandler.Mapper.AppendToMapping("SlideSwitch", (handler, view) =>
        {
            if (handler != null && handler.PlatformView != null)
            {
                handler.PlatformView.PreferredStyle = UIKit.UISwitchStyle.Sliding;
            }
        });
#endif
  1. In MainPage.xaml add a Switch control somewhere on the page.
  2. Run the program and try toggling the switch.

Link to public reproduction project repository

https://github.com/gairmuse/MauiSwitchBug

Version with bug

8.0.3

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

7.0.101

Affected platforms

macOS

Affected platform versions

MacOS 14.1.2

Did you find any workaround?

Partial workaround only. Changing the style for the Switch control as shown fixes the problem for the On position but not the Off position.

<Style TargetType="Switch">
    <Setter Property="OnColor" Value="{OnPlatform MacCatalyst=Transparent}" />
</Style>

Relevant log output

No response

gairmuse avatar Dec 09 '23 02:12 gairmuse

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

ghost avatar Dec 12 '23 19:12 ghost

Verified this on Visual Studio Enterprise 17.9.0 Preview 2(8.0.3). Repro on MacCatalyst, not repro on Windows 11, Android 14.0-API34 and iOS 17.0 with below Project: BugTest.zip

XamlTest avatar Jan 11 '24 09:01 XamlTest

Anyone find a workaround for this? It's a massive UI eyesore on mac catalyst apps. I've tried using VisualStateManager to specifically set a background in the "Off" state, but it appears that the grey box is being drawn on top of the control, or at least in a layer between the control and the background.

piersdeseilligny avatar Mar 05 '24 17:03 piersdeseilligny

I use the following as workaround but it's a bit ugly.

<Style TargetType="Switch">
    <Setter Property="OnColor" Value="{OnPlatform MacCatalyst=Transparent}" />
</Style>

These might need to change to match your UI

<Color x:Key="MacSwitchBackgroundDark">#040404</Color>
<Color x:Key="MacSwitchBackgroundLight">#ffffff</Color>

ApplyMacSwitchHack is called inside every Switch's Toggled event handler. ResetMacSwitchBackgroundColors is called inside every RequestedThemeChanged event handler.

    public static void ApplyMacSwitchHack(Microsoft.Maui.Controls.Switch theSwitch)
    {
#if MACCATALYST
        var name = Application.Current.RequestedTheme == AppTheme.Dark ? "MacSwitchBackgroundDark" : "MacSwitchBackgroundLight";
        var color = Utils.Resource<Color>(name);
        if (color != null)
        {
            theSwitch.BackgroundColor = theSwitch.IsToggled ? Colors.Transparent : color;
        }
#endif
    }

    public static void ResetMacSwitchBackgroundColors(Layout layout)
    {
#if MACCATALYST
        foreach (var child in layout.Children)
        {
            if (child is Microsoft.Maui.Controls.Switch s)
            {
                s.BackgroundColor = Colors.Transparent;
            }
            else if (child is Layout sibling)
            {
                ResetMacSwitchBackgroundColors(sibling);
            }
        }
#endif
    }

gairmuse avatar Mar 05 '24 18:03 gairmuse

So on .net8 maccatalyst, with the device idiom set to mac, even that workaround doesn't seem to be working.

This is Switch.BackgroundColor set to black in the on position: image

And this is it in the off position, once again with the Switch.BackgroundColor programatically set to black: image

It's still got that transparent grey rectangle, somewhere in front of the background. I assume this is a bug in MAUI rather than Mac Catalyst, given it was introduced with the transition to .net 8 and wasn't an issue in .net 7.

piersdeseilligny avatar Mar 06 '24 22:03 piersdeseilligny

Switch.BackgroundColor needs to be Transparent in the On position, which it will be if you use the code above. For the Off position you might need to adjust MacSwitchBackgroundDark to match your UI.

gairmuse avatar Mar 07 '24 07:03 gairmuse

Sorry maybe I wasn't clear enough - I left BackgroundColor to Black in the On position in the screenshot above, so that it's visible that when it's set to the Off position, there's still a grey rectangle around it (whereas it should be pitch black, just like it is in the screenshot where it's switched on).

piersdeseilligny avatar Mar 07 '24 09:03 piersdeseilligny