非阻塞UI线程动画

时间:2016-12-24 12:31:27

标签: multithreading xamarin.android android-animation mvvmcross

我正在尝试执行异步动画,这不会阻塞主线程。 我想要做的场景:

  • 用户单击一个按钮,并在一段时间后查看ViewModel属性 改变其状态。

  • 在MvxFragment视图中我订阅了OnPropertyChanged事件,如果所需的属性已更改,我会执行动画(显示通知给 用户几秒钟。)

我很困惑,当动画正在进行时应用程序没有响应:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    var ignore = base.OnCreateView(inflater, container, savedInstanceState);

    var view = this.BindingInflate(Resource.Layout.MyView, null);
    ViewModel.WeakSubscribe(PropertyChanged);

    return view;
}

private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "IsSaved")
    {
        if (ViewModel.IsSaved)
        {
            ShowSavedPopup();
        }
    }
}

private void ShowSavedPopup()
{       
    var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
    dispatcher.RequestMainThreadAction(() =>
    {

        var popupView = View.FindViewById(Resource.Id.popup);
        popupView.Alpha = 0.0f;

        popupView.Animate()
            .SetDuration(4000)
            .Alpha(1f)));
    });
}

我也尝试了不同的方法来运行动画异步,但没有一个工作(等待Task.Run,​​Activity.RunOnUiThread ..)。

如何运行动画异步?

1 个答案:

答案 0 :(得分:0)

我为我可怜的英语道歉。

问题我删除了brewity动画场景的结束行,但问题隐藏在那里。 在我的情况下,问题是使用Thread.Sleep。

冻结了主UI线程。

我应该使用异步任务。并使用Task.Delay显示所需时间段的弹出窗口。

工作解决方案将是:

private async void ShowSavedPopup()
{       
    // check if animation is in progress
    if (_isBusy) return;

    _isBusy = true;

    await Task.Factory.StartNew(() =>
    {
        _popupView.Post(() =>
        {
            _popupView.Visibility = ViewStates.Visible;
            _popupView.Alpha = 0.0f;

            _popupView.Animate()
                .SetDuration(400)
                .Alpha(1f)
                .WithEndAction(new Runnable(async () =>
                {
                    await Task.Delay(2000);

                    _popupView.Animate()
                        .SetDuration(400)
                        .Alpha(0.0f)
                        .WithEndAction(new Runnable(() => { 
                            _popupView.Visibility = ViewStates.Gone;  
                            isBusy = false;
                        }));
                }));
        });
    });
}