【问题标题】:Change Xamarin forms button color更改 Xamarin 表单按钮颜色
【发布时间】:2017-09-02 09:39:16
【问题描述】:

我是 xamarin 的新手,我想在单击后更改按钮的颜色,一旦该过程完成,它应该返回默认颜色,请参阅下面的代码如何在运行时重新呈现按钮。命令是先执行的,所以我在 click 中处理了它。这个功能应该适用于 android 和 iOS。

public class RippleButton : Button
{
    private readonly Color _defaultBackgroundColor = Color.FromRgb(255, 87, 34);
    private readonly Color _clickedBackgroundColor = Color.FromRgb(76, 175, 80);

    public ICommand ClickCommand
    {
        get { return (ICommand)GetValue(ClickCommandProperty); }
        set
        {
            SetValue(ClickCommandProperty, value);
        }
    }


    public static readonly BindableProperty ClickCommandProperty = BindableProperty.Create(
                                                   propertyName: nameof(ClickCommand),
                                                   returnType: typeof(ICommand),
                                                   declaringType: typeof(RippleButton),
                                                   defaultValue: null,
                                                   defaultBindingMode: BindingMode.TwoWay,
                                                   propertyChanged: OnClickCommandChanged);

    private static void OnClickCommandChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
    }

    public RippleButton()
    {
        const int animationTime = 10;


        TextColor = Color.FromRgb(255, 255, 255);
        BackgroundColor = _defaultBackgroundColor;

        Clicked += async (sender, e) =>
        {
            var btn = (RippleButton)sender;

            BackgroundColor = Color.FromRgb(76, 175, 80);

            ClickCommand?.Execute(btn.CommandParameter);

            await btn.ScaleTo(1.2, animationTime);
            await btn.ScaleTo(1, animationTime);

            BackgroundColor = _defaultBackgroundColor;
        };
    }

    private void ChangeColorOfButton()
    {
        BackgroundColor = _clickedBackgroundColor;
        Device.StartTimer(TimeSpan.FromSeconds(0.25), () =>
        {
            BackgroundColor = _defaultBackgroundColor;
            return false;
        });
    }
}

【问题讨论】:

  • 你的意思是在你按下按钮的时候改变按钮的颜色,在你松开按钮的时候改变它的颜色?
  • 是的。一旦该过程完成,它应该返回到默认颜色。

标签: c# xamarin mvvm xamarin.forms


【解决方案1】:

为了等待命令执行 - 一种方法是定义一个异步命令。 Stephen Cleary 分享了一些awesome patterns on how to implement asynchronous commands

您可以将异步命令定义为:

public interface IAsyncCommand : ICommand
{
    Task ExecuteAsync(object parameter);
}

public abstract class AsyncCommandBase : IAsyncCommand
{
    public abstract bool CanExecute(object parameter);
    public abstract Task ExecuteAsync(object parameter);

    public async void Execute(object parameter)
    {
        await ExecuteAsync(parameter);
    }

    public event EventHandler CanExecuteChanged;

    protected void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

public class AsyncCommand<TResult> : AsyncCommandBase, INotifyPropertyChanged
{
    private readonly Func<Task<TResult>> _command;
    private NotifyTaskCompletion<TResult> _execution;

    public AsyncCommand(Func<Task<TResult>> command)
    {
        _command = command;
    }

    public override bool CanExecute(object parameter)
    {
        return Execution == null || Execution.IsCompleted;
    }

    public override async Task ExecuteAsync(object parameter)
    {
        Execution = new NotifyTaskCompletion<TResult>(_command());
        RaiseCanExecuteChanged();
        await Execution.TaskCompletion;
        RaiseCanExecuteChanged();
    }

    public NotifyTaskCompletion<TResult> Execution
    {
        get { return _execution; }
        private set
        {
            _execution = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

您现在可以将控件重构为:

public class RippleButton : Button
{
    public static readonly BindableProperty ClickedBackgroundColorProperty =
        BindableProperty.Create(
            "ClickedBackgroundColor", typeof(Color), typeof(RippleButton),
            defaultValue: Color.FromRgb(76, 175, 80));

    public Color ClickedBackgroundColor
    {
        get { return (Color)GetValue(ClickedBackgroundColorProperty); }
        set { SetValue(ClickedBackgroundColorProperty, value); }
    }

    public static readonly BindableProperty AsyncCommandProperty =
        BindableProperty.Create(
            "AsyncCommand", typeof(IAsyncCommand), typeof(RippleButton),
            defaultValue: default(IAsyncCommand));

    public IAsyncCommand AsyncCommand
    {
        get { return (IAsyncCommand)GetValue(AsyncCommandProperty); }
        set { SetValue(AsyncCommandProperty, value); }
    }

    public RippleButton()
    {
        const int animationTime = 150;

        TextColor = Color.FromRgb(255, 255, 255);
        BackgroundColor = Color.FromRgb(255, 87, 34);

        Clicked += async (sender, e) =>
        {
            //execute command only if button is enabled.
            if (!IsEnabled)
                return;

            //continue only if command is executable, and not allow multiple click(s)
            if (AsyncCommand == null || !AsyncCommand.CanExecute(CommandParameter))
                return;

            var defaultColor = BackgroundColor;
            BackgroundColor = ClickedBackgroundColor;
            IsEnabled = false;

            await AsyncCommand.ExecuteAsync(CommandParameter);

            await this.ScaleTo(1.2, animationTime);
            await this.ScaleTo(1, animationTime);

            IsEnabled = true;
            BackgroundColor = defaultColor;
        };
    }
}

示例用法:

XAML

<local:RippleButton Text="Download" 
                    AsyncCommand="{Binding SimulateDownloadCommand}" />

查看模型

public class YourViewModel : BaseViewModel
{
    public YourViewModel()
    {
        SimulateDownloadCommand = new AsyncCommand<bool>(() => SimulateDownloadAsync());
    }

    private IAsyncCommand _downloadCommand;
    public IAsyncCommand SimulateDownloadCommand
    {
        get { return _downloadCommand; }
        private set
        {
            if (_downloadCommand != value)
            {
                _downloadCommand = value;
                OnPropertyChanged("SimulateDownloadCommand");
            }
        }
    }

    async Task<bool> SimulateDownloadAsync()
    {
        await Task.Run(() => SimulateDownload());
        return true;
    }

    void SimulateDownload()
    {
        // Simulate a 1.5 second pause
        var endTime = DateTime.Now.AddSeconds(1.5);
        while (true)
        {
            if (DateTime.Now >= endTime)
            {
                break;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2021-07-07
    • 2021-11-20
    • 2011-04-19
    • 2018-02-08
    相关资源
    最近更新 更多