在 xamarin 表单应用程序中导航返回时未调用后退按钮的自定义 NavigationRenderer
Custom NavigationRenderer for back button not called while navigating back in xamarin forms application
这是我用来将自定义图标指定为后退按钮的自定义渲染器的代码。
namespace MyProjectName.Droid.Renderers
{
public class MyNavigationRenderer: PageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
var context = (Activity)Xamarin.Forms.Forms.Context;
var toolbar = context.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Droid.Resource.Id.toolbar);
toolbar.NavigationIcon = AndroidX.Core.Content.ContextCompat.GetDrawable(context, Resource.Drawable.bbutton_nav);
}
}
}
此代码成功用我的自定义 bbutton_nav 替换了本机后退箭头图标。当我向前导航时 (Navigate.PushAsync()),自定义图标出现在所有即将出现的屏幕上。但是当我单击后退图标返回一页时 (Navigate.PopAsync()),旧的原生后退箭头重新出现,而不是渲染器设置的新自定义图标。当我尝试调试时,我发现渲染器 class 在向后导航时没有被调用(Navigation.PopAsync())。
感谢您提供有关如何缓解此问题的任何帮助。谢谢
为 NavigationPage
而不是 Page
创建自定义渲染器,并覆盖 OnLayout
方法。
Android会在UpdateToolbar方法中改回默认图标,每次改变当前页面时都会触发OnLayout
方法。
Android 解决方案
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyNavigationRenderer))]
namespace FormsApp.Droid
{
public class MyNavigationRenderer : NavigationPageRenderer
{
Context _context;
AndroidX.AppCompat.Widget.Toolbar _toolbar;
public MyNavigationRenderer(Context context) : base(context)
{
_context = context;
}
public override void OnViewAdded(Android.Views.View child)
{
base.OnViewAdded(child);
if (child.GetType() == typeof(AndroidX.AppCompat.Widget.Toolbar))
{
_toolbar = (AndroidX.AppCompat.Widget.Toolbar)child;
_toolbar.SetNavigationIcon(Resource.Drawable.bbutton_nav);
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (_toolbar != null)
{
if (_toolbar.NavigationIcon != null)
{
_toolbar.NavigationIcon = AndroidX.Core.Content.ContextCompat.GetDrawable(_context, Resource.Drawable.bbutton_nav);
}
}
}
}
}
参考https://forums.xamarin.com/discussion/183344/how-to-change-navigation-back-button-icon。
iOS 解决方案
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyRenderer))]
namespace FormsApp.iOS
{
class MyRenderer : NavigationRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (this.NavigationBar.TopItem.BackBarButtonItem == null)
{
this.NavigationBar.BackIndicatorImage = UIImage.FromFile("dots.png");
this.NavigationBar.BackIndicatorTransitionMaskImage = UIImage.FromFile("dots.png");
this.NavigationBar.TopItem.BackBarButtonItem = new UIBarButtonItem("", UIBarButtonItemStyle.Plain, null);
}
}
}
}
这是我用来将自定义图标指定为后退按钮的自定义渲染器的代码。
namespace MyProjectName.Droid.Renderers
{
public class MyNavigationRenderer: PageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
var context = (Activity)Xamarin.Forms.Forms.Context;
var toolbar = context.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Droid.Resource.Id.toolbar);
toolbar.NavigationIcon = AndroidX.Core.Content.ContextCompat.GetDrawable(context, Resource.Drawable.bbutton_nav);
}
}
}
此代码成功用我的自定义 bbutton_nav 替换了本机后退箭头图标。当我向前导航时 (Navigate.PushAsync()),自定义图标出现在所有即将出现的屏幕上。但是当我单击后退图标返回一页时 (Navigate.PopAsync()),旧的原生后退箭头重新出现,而不是渲染器设置的新自定义图标。当我尝试调试时,我发现渲染器 class 在向后导航时没有被调用(Navigation.PopAsync())。 感谢您提供有关如何缓解此问题的任何帮助。谢谢
为 NavigationPage
而不是 Page
创建自定义渲染器,并覆盖 OnLayout
方法。
Android会在UpdateToolbar方法中改回默认图标,每次改变当前页面时都会触发OnLayout
方法。
Android 解决方案
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyNavigationRenderer))]
namespace FormsApp.Droid
{
public class MyNavigationRenderer : NavigationPageRenderer
{
Context _context;
AndroidX.AppCompat.Widget.Toolbar _toolbar;
public MyNavigationRenderer(Context context) : base(context)
{
_context = context;
}
public override void OnViewAdded(Android.Views.View child)
{
base.OnViewAdded(child);
if (child.GetType() == typeof(AndroidX.AppCompat.Widget.Toolbar))
{
_toolbar = (AndroidX.AppCompat.Widget.Toolbar)child;
_toolbar.SetNavigationIcon(Resource.Drawable.bbutton_nav);
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (_toolbar != null)
{
if (_toolbar.NavigationIcon != null)
{
_toolbar.NavigationIcon = AndroidX.Core.Content.ContextCompat.GetDrawable(_context, Resource.Drawable.bbutton_nav);
}
}
}
}
}
参考https://forums.xamarin.com/discussion/183344/how-to-change-navigation-back-button-icon。
iOS 解决方案
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyRenderer))]
namespace FormsApp.iOS
{
class MyRenderer : NavigationRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (this.NavigationBar.TopItem.BackBarButtonItem == null)
{
this.NavigationBar.BackIndicatorImage = UIImage.FromFile("dots.png");
this.NavigationBar.BackIndicatorTransitionMaskImage = UIImage.FromFile("dots.png");
this.NavigationBar.TopItem.BackBarButtonItem = new UIBarButtonItem("", UIBarButtonItemStyle.Plain, null);
}
}
}
}