xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] UWP Button BackgroundColor turns gray when hovering #9123

Open MhAllan opened 4 years ago

MhAllan commented 4 years ago

Description

UWP Button BackgroundColor turns gray when hovering on it while targeting builds: 17763 and 18362, problem doesn't appear in creators update (16299)

Steps to Reproduce

  1. Create a XF button with background color
  2. target UWP 17763 or 18362
  3. hover on the button

Expected Behavior

Button preserves its background color (similar to what we get when targeting version 16299)

Actual Behavior

Button turns to gray (or whatever default theme)

Basic Information

Workaround

In UWP App.Xaml Resources:

<Style x:Key="ButtonStyle" TargetType="Button">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="RootGrid"
                                  Background="{TemplateBinding Background}">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal">
                                            <Storyboard>
                                                <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="PointerOver">
                                            <Storyboard>
                                                <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Pressed">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                                                               Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Disabled">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                                                               Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <ContentPresenter x:Name="ContentPresenter"
                                                  BorderBrush="{TemplateBinding BorderBrush}"
                                                  BorderThickness="{TemplateBinding BorderThickness}"
                                                  Content="{TemplateBinding Content}"
                                                  ContentTransitions="{TemplateBinding ContentTransitions}"
                                                  ContentTemplate="{TemplateBinding ContentTemplate}"
                                                  Padding="{TemplateBinding Padding}"
                                                  HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                                  AutomationProperties.AccessibilityView="Raw" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

Then create UWP button renderer

 public class CustomButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                var style = Application.Current.Resources["ButtonStyle"] as Style;
                Control.Style = style;
            }
        }
}
juanmalm commented 4 years ago

Is this issue planned to be fixed?

mnxamdev commented 4 years ago

We are having this issue too. We're trying to get get a Windows release out using shared code from our Android and iOS apps. Please help Xamarin! I'd be happy with a workaround.

MhAllan commented 4 years ago

@mnxamdev I updated the issue with my workaround, hope it works for you. don't forget to export your renderer

mnxamdev commented 4 years ago

Beat me to it @MhAllan ! This was a real pain to figure out. I too had to create a custom control template too except all I did was add an empty PointerOver visual state. I'm unclear though if I need to add additional {TemplateBinding X} to respective properties to make sure all properties are bound on the consumed/declared button:

<ControlTemplate x:Key="DefaultButtonControlTemplate" TargetType="Button">
        <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="PointerOver"/>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <ContentPresenter 
                x:Name="ContentPresenter" 
                AutomationProperties.AccessibilityView="Raw" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}"
                ContentTemplate="{TemplateBinding ContentTemplate}" 
                ContentTransitions="{TemplateBinding ContentTransitions}" 
                Content="{TemplateBinding Content}" 
                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                Padding="{TemplateBinding Padding}" 
                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
                TextWrapping="WrapWholeWords"/>
        </Grid>
    </ControlTemplate>
    public class UWPButton : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control button = Control;
                var template = Windows.UI.Xaml.Application.Current.Resources["DefaultButtonControlTemplate"] as ControlTemplate;
                button.Template = template;
            }
        }
    }
holecekp commented 4 years ago

@MhAllan Thank you very much for your workaround. It works also for ImageButton.

jfversluis commented 2 years ago

I see some workarounds and I think we did some fixes in this area, closing this one for now, let me know if this is still an issue to anyone! Thanks!

dag23 commented 2 years ago

@jfversluis It was fixed in 5.0.0.2083 but it's a problem again in 5.0.0.2244.

snakebytetech commented 2 years ago

An update (12/21/2021)....I'm not exactly which thing I did was what fixed it, but my issue where the "active" color is removed and doesn't come back is now working again. I was testing the various previous versions of Xamarin.Forms, but I'm back to the current of 5.0.0.2291. I think what may have fixed it was I cleaned the solution, I opened the directory of my shared project and UWP projects and deleted the obj/bin folders, then rebuilt the solution and restarted VisualStudio 2022. Try that to see if it helps. Note, my buttons still change on hover to show an outline of a button which isn't really what I want either, but at least my active color comes back. I also reverted put my target and min version for UWP back to 1903/18362. Unfortunately, everything else I mention below is still a problem.

This is still a problem for me as well as other layout issues when I upgraded Xamarin.Forms from 5.0.0.2012 to 5.0.0.2291. I'm targeting UWP for now, Minimum version = 17763 and target = 18362. I also updated a handful of other Nugets.

This latest update messed up the layout for multiple objects.

Before the upgrade to the latest Xamarin.Forms, this screenshot below looked nice and well layed out. You can see how labels are scrunched with a bunch of space between switches and labels. Note, I have a custom renderer for the switch to hide the on/off text because the words on/off are redundant. I tried removing my renderer and that didn't help. The words to the right of the switches are supposed to be what is right next to the switch. Instead, there is a big gap between the switch and the label now. That wasn't there before.

2021-12-20_16-03-33

Since this thread is about the button, I'm not only experiencing the same as above, but I use buttons as a navigation so I can use Windows shortcut keys and when you click one, it'll make the text color of that button "active". Now, when you hover that button, the "active" color goes away. The only way to get it back is to click it again.

It's as though you forgot about light themes and UWP apps and only tested your releases with dark themes on Android and iOS.

Please help. I don't want to have to go back into every one of my pages to re-design them and change my background so the hover "feature" doesn't ghost out my controls. At this point, if there's not a fix/suggestion soon, I'm probably going to downgrade my Xamarin.Forms and cross my fingers you fix it with the next release because I don't have the time to mess with something like this right now.

snakebytetech commented 2 years ago

Another update. It seems the spacing problem was caused by my Switch Renderer is no longer supported. I like the new version better and perhaps it's how I should have originally written it. Hopefully it helps someone else experiencing similar problems.

image

image

dag23 commented 2 years ago

I have investigated and the template of the FormsButton does not contain a Grid. https://github.com/xamarin/Xamarin.Forms/commit/b85c28e530eff581c6fa48742e07cd84cca7dd3e#diff-489c1b3b032afaa3b926f0420f2d644b2faabe1d5008d278e10b6fb5feccbd28 The ButtonRenderer is searching for one to use the InterceptVisualStateManager. https://github.com/xamarin/Xamarin.Forms/blob/5.0.0/Xamarin.Forms.Platform.UAP/ButtonRenderer.cs So it doesn't hook the InterceptVisualStateManager and we can't override the Visual States for the Button in Xamarin.Forms styles.

jfversluis commented 2 years ago

Hey everyone, thanks for all the input here. I see a lot of things that might or might not be related, but just to be sure; this is still (or again) an issue in the latest stable version 5.0.0.2291? But it was fixed in an earlier version?

Seems like this PR #13148 might have something to do with it?

@dag23 besides doing the research do you also have a proposal on how to fix it?

bobwhitten commented 2 years ago

I have this issue, and I've not had success yet with a workaround. I'm running 5.0.0.2478 (latest, as of this writing), and target version is build 19041 (Win 10, version 2004). For me, this is difficult because I have a dark background, and some white buttons with black text. So, it almost disappears. Disabled is even more.

The iOS behavior for this is just fine (changes opacity, I think, of text).

I don't want to spend too long on this -- this latecomer app will probably move over to MAUI pretty soon.