Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewrdev/95fe6b6d1ff2334488b40fc788833987 to your computer and use it in GitHub Desktop.
Save matthewrdev/95fe6b6d1ff2334488b40fc788833987 to your computer and use it in GitHub Desktop.
Intercepts the "soft" back button events from the Android toolbar and forwards them to the Page.OnBackButtonPressed for handling.
using System.Reflection;
using System.Threading.Tasks;
using Android.Content;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyApp.Droid.Renderers.InterceptBackButtonNavigationPageRenderer))]
namespace MyApp.Droid.Renderers
{
public class InterceptBackButtonNavigationPageRenderer : NavigationPageRenderer
{
private readonly FieldInfo _toolbarFieldInfo;
AToolbar Toolbar => _toolbarFieldInfo.GetValue(this) as AToolbar;
private readonly FieldInfo _flyoutPageFieldInfo;
FlyoutPage FlyoutPage => _flyoutPageFieldInfo.GetValue(this) as FlyoutPage;
public InterceptBackButtonNavigationPageRenderer(Context context) : base(context)
{
_toolbarFieldInfo = typeof(NavigationPageRenderer).GetField("_toolbar", BindingFlags.Instance | BindingFlags.NonPublic);
_flyoutPageFieldInfo = typeof(NavigationPageRenderer).GetField("_flyoutPage", BindingFlags.Instance | BindingFlags.NonPublic);
}
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
BindSoftNavigationInterception();
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
BindSoftNavigationInterception();
}
private void BindSoftNavigationInterception()
{
Toolbar.NavigationClick -= Toolbar_NavigationClick;
Toolbar.NavigationClick += Toolbar_NavigationClick;
}
private async void Toolbar_NavigationClick(object sender, AToolbar.NavigationClickEventArgs e)
{
if (Element is null)
{
return;
}
if (Element is INavigationPageController controller
&& controller.StackDepth <= 1)
{
if (FlyoutPage != null)
{
FlyoutPage.IsPresented = !FlyoutPage.IsPresented;
}
}
else
{
Element.SendBackButtonPressed();
}
}
protected override async Task<bool> OnPopToRootAsync(Page page, bool animated)
{
var result = await base.OnPopToRootAsync(page, animated);
BindSoftNavigationInterception();
return result;
}
protected override async Task<bool> OnPushAsync(Page view, bool animated)
{
var result = await base.OnPushAsync(view, animated);
BindSoftNavigationInterception();
return result;
}
protected override async Task<bool> OnPopViewAsync(Page page, bool animated)
{
var result = await base.OnPopViewAsync(page, animated);
BindSoftNavigationInterception();
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment