如何更改ActionBar的操作视图';与Xamarin的菜单项
本文关键字:Xamarin 菜单项 视图 何更改 ActionBar 操作 | 更新日期: 2023-09-27 17:59:43
我在ActionBar
中有一个带有图标的菜单项,当用户单击它、运行任务,然后将其更改回图标时,我想将其更改为ProgressBar
。下面是我的代码,但单击菜单项时不会发生任何事情。
活动:ImportReferenceView.cs
public class ImportReferenceView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.ImportReferenceView);
ActionBar.SetDisplayShowCustomEnabled(true);
}
public override bool OnCreateOptionsMenu(Android.Views.IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.import_actions, menu);
return true;
}
public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
{
switch (item.ItemId)
{
case Resource.Id.action_import:
item.SetActionView(Resource.Layout.progressbar);
item.ExpandActionView();
var vm = ((ImportReferenceViewModel)ViewModel);
Task task = Task.Run(() => vm.ImportCommand.Execute(vm.SelectedTableReferences));
Task.WaitAll(new Task[] { task });
item.CollapseActionView();
item.SetActionView(null);
break;
default:
break;
}
return true;
}
}
菜单操作:import_actions.xml
<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_import"
android:showAsAction="always"
android:icon="@drawable/action_down"
android:title="Refresh"/>
</menu>
progressbar视图:progressbar.axml
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
我正试图用Xamarin实现类似于本文的操作栏/操作视图部分中描述的功能
任何帮助或建议都将不胜感激
以下是我的操作方法:
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.home_menu, menu);
_refreshWrapper = new RefreshActionButtonWrapper(menu);
var set = this.CreateBindingSet<HomeView, HomeViewModel>();
set.Bind(_refreshWrapper).For("IsBusy").To(vm => vm.MyService.IsBusy);
set.Apply();
return true;
}
我使用MvvvmCross数据绑定将IsBusy属性绑定到包装类。你不必那样做。您可以直接设置IsBusy属性(请参阅下面的示例)。
public class RefreshActionButtonWrapper
{
private readonly IMenu _optionsMenu;
public RefreshActionButtonWrapper(IMenu optionsMenu)
{
_optionsMenu = optionsMenu;
}
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
var dispatcher = MvxMainThreadDispatcher.Instance;
dispatcher.RequestMainThreadAction(() => SetRefreshActionButtonState(_isBusy));
}
}
public void SetRefreshActionButtonState(bool refreshing)
{
if (_optionsMenu == null) return;
var refreshItem = _optionsMenu.FindItem(Resource.Id.refresh_action);
if (refreshing)
{
refreshItem.SetActionView(Resource.Layout.actionbar_indeterminate_progress);
}
else
{
refreshItem.SetActionView(null);
}
}
}
诀窍是更改主线程上的操作视图。MvvmCross提供了一种在主线程上调用请求的方法:
var dispatcher = MvxMainThreadDispatcher.Instance;
dispatcher.RequestMainThreadAction(() => SetRefreshActionButtonState(_isBusy));
然后你可以做这样的事情。使用wait等待导入功能完成。我喜欢将IsBusy状态包装在try/finaly中,以确保IsBusy始终设置为false,即使在异常情况下也是如此。
public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
{
switch (item.ItemId)
{
case Resource.Id.action_import:
try
{
_refreshWrapper.IsBusy = true;
var vm = ((ImportReferenceViewModel)ViewModel);
await Task.Run(() => vm.ImportCommand.Execute(vm.SelectedTableReferences));
}
finally
{
_refreshWrapper.IsBusy = false;
}
break;
default:
break;
}
return true;
}
BTW:如果您从MvxActivity<ImportReferenceViewModel>您将拥有一个强类型的ViewModel属性,并且不必强制转换它。