Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Xamarin.Forms button clicked colour

I am working on a Xamarin.Forms UWP application and I wanted to change my button's background colour when pressed. I have been searching the web and the most straightforward way I could find is this:

 private void Button_OnClicked(object s, EventArgs e)
    {
        var b = (Button) s;
        var originalColour = b.BackgroundColor;
        b.BackgroundColor = Color.DarkOrange;
        Device.StartTimer(TimeSpan.FromSeconds(0.25), () =>
        {
            b.BackgroundColor = originalColour;
            return false;
        });
    }

However, personally, I am not liking this approach very much. How can this be done better?

like image 280
Georgi Koemdzhiev Avatar asked Feb 18 '18 13:02

Georgi Koemdzhiev


3 Answers

An EventTrigger solution in XAML:

Implement the following in MyAssembly, e.g. the portable assembly containing App.xaml:

using Xamarin.Forms;

namespace MyNamespace
{
  public class ButtonTriggerAction : TriggerAction<VisualElement>
  {
    public Color BackgroundColor { get; set; }

    protected override void Invoke(VisualElement visual)
    {
        var button = visual as Button;
        if (button == null) return;
        if (BackgroundColor != null) button.BackgroundColor = BackgroundColor;
    }
  }
}

XAML:

xmlns:local="clr-namespace:MyNamespace;assembly=MyAssembly"
...
<Button Text="EventTrigger">
  <Button.Triggers>
    <EventTrigger Event="Pressed">
      <local:ButtonTriggerAction BackgroundColor="Red" />
    </EventTrigger>
    <EventTrigger Event="Released">
      <local:ButtonTriggerAction BackgroundColor="Default" />
    </EventTrigger>
  </Button.Triggers>
</Button>
like image 197
Benl Avatar answered Oct 27 '22 14:10

Benl


a more natural and cleaner way to do it would be using VisualStateManager

<Button Text="Click Me!">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="Green" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Pressed">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="Red" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Button>

you can read more about in here.

like image 43
Joseph Avatar answered Oct 27 '22 15:10

Joseph


This is the simplest solution but of course not very clean.

THe problem here is that each platform implements the "pressed" state differently and Xamarin.Forms doesn't have any built-in way how to handle this.

In case of UWP, you have two options. First, you can create a new default button style that will be used throughout your app. You can find the default style here, and just copy it, modify the Pressed VisualState and add is as a default resource:

<Style TargetType="Button">
   <!-- ... your style -->
</Style>

However, if the pressed button color should be applied only in some places, you should rather create a new view that derives from button and uses a custom renderer on UWP that applies a custom style in the OnElementChanged event handler:

protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
    base.OnElementChanged(e);

    if (this.Element != null)
    {
        this.Control.Style = ( Style )Application.Current.Resources["CustomButtonStyle"];
    }
}

Other platforms will have similar solutions as well, but you will definitely have to implement them in such platform-specific way, probably using the custom renderers.

For more information on custom renderers see the documentation. You may also find some inspiration in Xamarin.Forms Labs repository.

like image 31
Martin Zikmund Avatar answered Oct 27 '22 16:10

Martin Zikmund