我有一个遵循MVVM模式的多页(Android& iOS)Xamarin.Forms应用程序。有时,业务逻辑可以调用重要的活动,例如触发与某些Web服务的数据同步。我想向用户显示后台正在发生的事情。工具栏中的ActivityIndicator将是我理想的解决方案。该活动与前景中的页面无关,因此我不想将指标放在页面上,我希望它在外面的某个地方,工具栏似乎是正确的位置。
我的第一次尝试是通过XAML:
<ContentPage.ToolbarItems>
<ToolbarItem>
<ActivityIndicator IsRunning="{Binding IsRunning}" />
</ToolbarItem>
</ContentPage.ToolbarItems>
虽然这个(和类似的方法)编译,它会抛出一个异常,看起来像ActivityIndicator可能不是ToolbarItems的子代或任何工具栏项。
翻转手册页我偶然发现了页面类的IsBusy属性。
https://developer.xamarin.com/api/property/Xamarin.Forms.Page.IsBusy/
试试,我使用了这段代码:
public App ()
{
InitializeComponent();
MainPage = new App1.MainPage();
MainPage.IsBusy = true;
}
结果是 - 什么都没有。没有错误,但工具栏中没有显示任何内容。我在论坛中发现了一些迹象表明这个功能可能在最新的Android版本中被丢弃了,但没有明确的说明,而且文档也没有这么说。
我如何实现我的目标?
答案 0 :(得分:1)
以下是可以在PCL和Android项目中使用的代码,遗憾的是我目前尚未编写iOS自定义渲染器。不管怎样,您需要在PCL中使用自定义NavigationPage
,并在Android项目中使用自定义NavigationPageRenderer
:
CustomNavigationPage.cs (在您的PCL项目中):
public class CustomNavigationPage : NavigationPage
{
public event EventHandler<EventArgs> OnShowActivityIndicator;
public event EventHandler<EventArgs> OnHideActivityIndicator;
}
CustomNavigationPageRenderer.cs (在Android项目中):
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(CustomNavigationPageRenderer))]
namespace MyProject.Droid.CustomRenderers
{
CustomNavigationPage page;
Android.Support.V7.Widget.Toolbar _toolbar;
Android.Widget.ProgressBar _progressBar;
bool _isProgressBarCurrentlyOnToolBar = false;
public class CustomNavigationPageRenderer : NavigationPageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomNavigationPage> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
page = (CustomNavigationPage)e.NewElement;
page.OnShowActivityIndicator += HandleShowActivityIndicator;
page.OnHideActivityIndicator += HandleHideActivityIndicator;
}
}
private void HandleShowActivityIndicator(object sender, EventArgs e)
{
var progressBar = GetProgressBar();
if (progressBar == null)
return;
var toolbar = GetToolbar();
if (toolbar == null)
return;
Device.BeginInvokeOnMainThread(() =>
{
if (_isProgressBarCurrentlyOnToolBar == false)
{
toolbar.AddView(progressBar);
_isProgressBarCurrentlyOnToolBar = true;
}
});
}
private void HandleHideActivityIndicator(object sender, EventArgs e)
{
var progressBar = GetProgressBar();
if (progressBar == null)
return;
var toolbar = GetToolbar();
if (toolbar == null)
return;
Device.BeginInvokeOnMainThread(() =>
{
if (_isProgressBarCurrentlyOnToolBar)
{
toolbar.RemoveView(progressBar);
_isProgressBarCurrentlyOnToolBar = false;
}
});
}
private Android.Support.V7.Widget.Toolbar GetToolbar()
{
if (_toolbar == null)
{
for (var i = 0; i < this.ChildCount; i++)
{
var child = GetChildAt(i);
if (child.GetType() == typeof(Android.Support.V7.Widget.Toolbar))
{
_toolbar = (Android.Support.V7.Widget.Toolbar)child;
}
}
}
return _toolbar;
}
private Android.Widget.ProgressBar GetProgressBar()
{
if (_progressBar == null)
{
_progressBar = new Android.Widget.ProgressBar(Xamarin.Forms.Forms.Context)
{
Indeterminate = true,
LayoutParameters = new LayoutParams(Utils.PxToDip(20), Utils.PxToDip(20))
};
_progressBar.SetPadding(10, 0, 0, 0);
}
return _progressBar;
}
}
}
使用它很简单,在你的代码后面只需调用事件处理程序。即:
public class MyPage : CustomNavigationPage
{
public MyPage()
{
// show it:
OnShowActivityIndicator?.Invoke(this, null);
// hide it:
OnHideActivityIndicator?.Invoke(this, null);
}
}