I want to implement a dialpad on my form. Now, in my XAML I am testing a button: XAML
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyXFDemo001.Views.NewItemPage" Title="New Item"> <ContentPage.ToolbarItems> <ToolbarItem Text="Save" Clicked="Save_Clicked" /> </ContentPage.ToolbarItems> <ContentPage.Content> <StackLayout Spacing="20" Padding="15"> <Button x:Name="buttonSelectContact" Clicked="buttonSelectContact_Clicked" Text="CLICK" BackgroundColor="#0080ff" /> </StackLayout> </ContentPage.Content>
And in my code behind I have a method buttonSelectContact_Clicked:
private async void buttonSelectContact_Clicked(object sender, EventArgs e) { Button btn = (Button)sender; btn.BackgroundColor = Color.FromHex("#22ac38"); await Task.Delay(500); btn.BackgroundColor = Color.FromHex("#0080ff"); }
It works, but not quietly as smooth as I want. Can you suggest me to add animation instead of this BackgroundColor?
I guess the better choice is to create a reusable feature to do that. You may take advantage of the animation resources from xamarin.forms.
For example, you can create an extension method that provides you a nice and easy way to reuse anywhere, like FadeTo
or TranslateTo
...
It is pretty easy, except for the logic that smoothly changes the color in this particular case. Here is the code:
public static class AnimationExtensions { public static Task<bool> ChangeBackgroundColorTo(this Button self, Color newColor, uint length = 250, Easing easing = null) { Task<bool> ret = new Task<bool>(() => false); if (!self.AnimationIsRunning(nameof(ChangeBackgroundColorTo))) { Color fromColor = self.BackgroundColor; try { Func<double, Color> transform = (t) => Color.FromRgba(fromColor.R + t * (newColor.R - fromColor.R), fromColor.G + t * (newColor.G - fromColor.G), fromColor.B + t * (newColor.B - fromColor.B), fromColor.A + t * (newColor.A - fromColor.A)); ret = TransmuteColorAnimation(self, nameof(ChangeBackgroundColorTo), transform, length, easing); } catch (Exception ex) { // to supress animation overlapping errors self.BackgroundColor = fromColor; } } return ret; } private static Task<bool> TransmuteColorAnimation(Button button, string name, Func<double, Color> transform, uint length, Easing easing) { easing = easing ?? Easing.Linear; var taskCompletionSource = new TaskCompletionSource<bool>(); button.Animate(name, transform, (color) => { button.BackgroundColor = color; }, 16, length, easing, (v, c) => taskCompletionSource.SetResult(c)); return taskCompletionSource.Task; } }
Importing this class (by the using namespace
reference) you will be able to use it like bellow.
Declaring an XAML
button:
<Button Text="Nice button ;)" BackgroundColor="Gray" x:Name="btnTeste" Clicked="btnTest_Click"/>
Handling click in the code-behind:
private async void btnTest_Click(object sender, EventArgs args) { #region You will not need this block, it is just to choose a random color for change to var colors = new[] { Color.Red, Color.Pink, Color.Silver, Color.Yellow, Color.Black, Color.Green }; var rnd = new Random(); var actualColor = btnTeste.BackgroundColor; var randomColor = colors.Where(c => c != actualColor).ToArray()[rnd.Next(0, colors.Length - 2)]; #endregion // Here is the effective use of the smooth background color change animation await btnTeste.ChangeBackgroundColorTo(randomColor, 150, Easing.CubicOut); await btnTeste.ChangeBackgroundColorTo(actualColor, 100, Easing.SinOut); }
EDIT:
Here is the result (the gif shows clicks and double-clicks, so you can see a lot of smoothy changes):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With