非阻塞 UI 线程动画
Non-blocking UI Thread animation
我正在尝试执行不阻塞主线程的异步动画。
我正在尝试做的场景:
用户点击按钮,一段时间后 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)));
});
}
我也尝试了不同的方法来 运行 动画异步,但是 none 有效(等待 Task.Run、Activity.RunOnUiThread..)。
我怎样才能 运行 我的动画异步?
我为我糟糕的英语道歉。
有问题,我为了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;
}));
}));
});
});
}
我正在尝试执行不阻塞主线程的异步动画。 我正在尝试做的场景:
用户点击按钮,一段时间后 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)));
});
}
我也尝试了不同的方法来 运行 动画异步,但是 none 有效(等待 Task.Run、Activity.RunOnUiThread..)。
我怎样才能 运行 我的动画异步?
我为我糟糕的英语道歉。
有问题,我为了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;
}));
}));
});
});
}