2017-09-02 10 views
1

私はxamarinを初めて使いました。プロセスが完了したらデフォルトの色に戻す必要があるので、クリック時にボタンの色を変更したいです。下のコードを参照してください。実行時間。コマンドが最初に実行されたので、私はclick.Thisの機能でこれを処理していたアンドロイドとiOSで動作するはずです。Xamarinフォームのボタンの色を変更する

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; 
     }); 
    } 
} 
+0

あなたがボタンを押している間、ボタンの色を変更し、あなたがそれを離すと戻ってそれを変更することを意味していますか? –

+0

はい。プロセスが完了したら、デフォルトの色に戻ります。 –

答えて

3

コマンド実行を待つために、非同期コマンドを定義する方法の1つがあります。 Stephen Cleary氏はawesome patterns on how to implement asynchronous commandsを共有しています。

あなたはとして非同期コマンドを定義することができます。

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

使用例:あなたは今のように、あなたのコントロールをリファクタリングすることができます

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

を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; 
      } 
     } 
    } 
} 

enter image description hereenter image description here

関連する問題