单击按钮上的 Xamarin.Forms 动画(Flash 背景)

Posted

技术标签:

【中文标题】单击按钮上的 Xamarin.Forms 动画(Flash 背景)【英文标题】:Xamarin.Forms Animation on click Button (Flash background) 【发布时间】:2018-10-26 07:22:15 【问题描述】:

我想在我的表单上实现一个拨号盘。 现在,在我的 XAML 中,我正在测试一个按钮: 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>

在我的代码后面我有一个方法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");

它可以工作,但没有我想要的那么平稳。 你能建议我添加动画而不是这个背景颜色吗?

【问题讨论】:

forums.xamarin.com/discussion/58818/… @Johannes 谢谢,我已经看过这篇文章了。问题 - 我应该在哪个事件上将此方法“StartAnimation”与您提供给我的此页面上接受的答案绑定?另外,在我的 CodeBehind 中,我无法“看到”一个名为 x:Name ="whiteLabel" 的标签?谢谢 从您的buttonSelectContact_Clicked 致电StartAnimation。您必须添加两个具有两种不同背景颜色(一个 #0080ff,另一个 #22ac38)的按钮(到网格中,以覆盖它们),也许一个没有点击事件(取决于您想要的功能......),并给出一个 x:Name="buttonSelectContactStandardColor" 和另一个 x:Name="buttonSelectContactAnimationColor",然后在正常显示的那个上调用FadeTo... @Johannes 我明白你说的。如果您想用示例代码回答我的问题,我可以接受您的回答吗? 感谢您指出这一点 :) @Stefan0309 【参考方案1】:

我想更好的选择是创建一个可重用的功能来做到这一点。你可以利用xamarin.forms的动画资源。

例如,您可以创建一个扩展方法,为您提供一种在任何地方重复使用的简便方法,例如 FadeToTranslateTo...

这很容易,除了在这种特殊情况下平滑更改颜色的逻辑。代码如下:

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;
    

导入这个类(通过using namespace 引用),您将能够像下面这样使用它。

声明一个XAML 按钮:

<Button Text="Nice button ;)"
        BackgroundColor="Gray"
        x:Name="btnTeste"
        Clicked="btnTest_Click"/>

在代码隐藏中处理点击:

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);

编辑:

这是结果(gif显示点击和双击,所以你可以看到很多平滑的变化):

【讨论】:

太棒了!我喜欢这种方法 很好的解决方案,这应该是公认的答案! 干得漂亮,我的朋友!而且更简单,没有自定义渲染器!【参考方案2】:

根据https://forums.xamarin.com/discussion/58818/how-to-animate-change-of-background-color 你的代码看起来像这样

XAML

<StackLayout Spacing="20" Padding="15">
    <Grid>
        <Button
        x:Name="buttonSelectContactSecond"
        Text="CLICK" BackgroundColor="#22ac38" />
        <Button
            x:Name="buttonSelectContact"
            Clicked="buttonSelectContact_Clicked"
            Text="CLICK" BackgroundColor="#0080ff" />
    </Grid>
</StackLayout>

在后面的代码中

private async void buttonSelectContact_Clicked(object sender, EventArgs e) 

    StartAnimation();


private async void StartAnimation()

    await Task.Delay(200);
    await buttonSelectContact.FadeTo(0, 250);
    await Task.Delay(200);
    await buttonSelectContact.FadeTo(1, 250);

【讨论】:

【参考方案3】:

您还可以创建带有动画的通用自定义控件:

在这个示例中,我使用了 Image 控件,但您可以使用 Button、Label 等:)

public class NativeImage : Image

    public static readonly BindableProperty CommandProperty =
        BindableProperty.Create(
            nameof(Command),
            typeof(ICommand),
            typeof(NativeImage),
            default(ICommand));

    public ICommand Command
    
        get => (ICommand) GetValue(CommandProperty);
        set => SetValue(CommandProperty, value);
    

    public static readonly BindableProperty CommandParameterProperty =
        BindableProperty.Create(
            nameof(Command),
            typeof(object),
            typeof(NativeImage));

    public object CommandParameter
    
        get => GetValue(CommandParameterProperty);
        set => SetValue(CommandParameterProperty, value);
    

    private ICommand TransitionCommand
    
        get
        
            return new Command(async () =>
            
                AnchorX = 0.48;
                AnchorY = 0.48;
                await this.ScaleTo(0.8, 50, Easing.Linear);
                await Task.Delay(100);
                await this.ScaleTo(1, 50, Easing.Linear);
                Command?.Execute(CommandParameter);
            );
        
    

    public NativeImage()
    
        Initialize();
    

    public void Initialize()
    
        GestureRecognizers.Add(new TapGestureRecognizer
        
            Command = TransitionCommand
        );
    

【讨论】:

一般来说这是个好主意,但是对于这个特定的例子,你需要两个按钮/标签/任何一个在另一个之上,只有一个应该有淡出的动画来实现闪烁的效果背景。你要明白,FadeTo 只是一个 opaque 值的渐变动画,所以你只是慢慢隐藏按钮,然后让它再次出现。我不知道自定义渲染器是否可行,但这可能是解决此类问题的最佳方法...

以上是关于单击按钮上的 Xamarin.Forms 动画(Flash 背景)的主要内容,如果未能解决你的问题,请参考以下文章

更改 Xamarin.Forms 按钮单击的颜色

Xamarin.Forms MQTT 在按钮单击时发布

Xamarin Forms:如何为网格内单击的按钮添加背景颜色(单词搜索游戏)

在 Xamarin.Forms 中打开通知

在 Xamarin Forms iOS 13+ 应用程序中设置导航栏按钮上的字体

Xamarin.Forms - 摇篮 FAB