summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs789
1 files changed, 789 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
new file mode 100644
index 00000000..fd4cb72b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
@@ -0,0 +1,789 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.Animation;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Android.OS;
+using Android.Runtime;
+using Android.Support.V4.Widget;
+using Android.Support.V7.Graphics.Drawable;
+using Android.Util;
+using Android.Views;
+using ActionBarDrawerToggle = Android.Support.V7.App.ActionBarDrawerToggle;
+using AView = Android.Views.View;
+using AToolbar = Android.Support.V7.Widget.Toolbar;
+using Fragment = Android.Support.V4.App.Fragment;
+using FragmentManager = Android.Support.V4.App.FragmentManager;
+using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class NavigationPageRenderer : VisualElementRenderer<NavigationPage>, IManageFragments
+ {
+ #region Statics
+
+ // All statics need to be made non-static/bound to platform
+
+ static ViewPropertyAnimator s_currentAnimation;
+
+ #endregion
+
+ readonly List<Fragment> _fragmentStack = new List<Fragment>();
+
+ Drawable _backgroundDrawable;
+ Page _current;
+
+ bool _disposed;
+ ActionBarDrawerToggle _drawerToggle;
+ FragmentManager _fragmentManager;
+ int _lastActionBarHeight = -1;
+ AToolbar _toolbar;
+ ToolbarTracker _toolbarTracker;
+ bool _toolbarVisible;
+
+ public NavigationPageRenderer()
+ {
+ AutoPackage = false;
+ Id = FormsAppCompatActivity.GetUniqueId();
+ Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
+ }
+
+ internal int ContainerPadding { get; set; }
+
+ Page Current
+ {
+ get { return _current; }
+ set
+ {
+ if (_current == value)
+ return;
+
+ if (_current != null)
+ _current.PropertyChanged -= CurrentOnPropertyChanged;
+
+ _current = value;
+
+ if (_current != null)
+ {
+ _current.PropertyChanged += CurrentOnPropertyChanged;
+ ToolbarVisible = NavigationPage.GetHasNavigationBar(_current);
+ }
+ }
+ }
+
+ FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
+
+ bool ToolbarVisible
+ {
+ get { return _toolbarVisible; }
+ set
+ {
+ if (_toolbarVisible == value)
+ return;
+ _toolbarVisible = value;
+ RequestLayout();
+ }
+ }
+
+ public void SetFragmentManager(FragmentManager childFragmentManager)
+ {
+ if (_fragmentManager == null)
+ _fragmentManager = childFragmentManager;
+ }
+
+ public Task<bool> PopToRootAsync(Page page, bool animated = true)
+ {
+ return OnPopToRootAsync(page, animated);
+ }
+
+ public Task<bool> PopViewAsync(Page page, bool animated = true)
+ {
+ return OnPopViewAsync(page, animated);
+ }
+
+ public Task<bool> PushViewAsync(Page page, bool animated = true)
+ {
+ return OnPushAsync(page, animated);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ var activity = (FormsAppCompatActivity)Context;
+
+ // API only exists on newer android YAY
+ if ((int)Build.VERSION.SdkInt >= 17)
+ {
+ if (!activity.IsDestroyed)
+ {
+ FragmentManager fm = FragmentManager;
+ FragmentTransaction trans = fm.BeginTransaction();
+ foreach (Fragment fragment in _fragmentStack)
+ trans.Remove(fragment);
+ trans.CommitAllowingStateLoss();
+ fm.ExecutePendingTransactions();
+ }
+ }
+
+ if (Element != null)
+ {
+ for (var i = 0; i < Element.InternalChildren.Count; i++)
+ {
+ var child = Element.InternalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Android.Platform.GetRenderer(child);
+ renderer?.Dispose();
+ }
+ Element.PushRequested -= OnPushed;
+ Element.PopRequested -= OnPopped;
+ Element.PopToRootRequested -= OnPoppedToRoot;
+ Element.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ Element.RemovePageRequested -= OnRemovePageRequested;
+ Element.SendDisappearing();
+ }
+
+ if (_toolbarTracker != null)
+ {
+ _toolbarTracker.CollectionChanged -= ToolbarTrackerOnCollectionChanged;
+ _toolbarTracker.Target = null;
+ _toolbarTracker = null;
+ }
+
+ if (_toolbar != null)
+ {
+ _toolbar.NavigationClick -= BarOnNavigationClick;
+ _toolbar.Dispose();
+ _toolbar = null;
+ }
+
+ Current = null;
+
+ Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ _fragmentStack.Last().UserVisibleHint = true;
+ RegisterToolbar();
+ UpdateToolbar();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.PushRequested -= OnPushed;
+ e.OldElement.PopRequested -= OnPopped;
+ e.OldElement.PopToRootRequested -= OnPoppedToRoot;
+ e.OldElement.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ e.OldElement.RemovePageRequested -= OnRemovePageRequested;
+
+ RemoveAllViews();
+ if (_toolbar != null)
+ AddView(_toolbar);
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_toolbarTracker == null)
+ {
+ SetupToolbar();
+ _toolbarTracker = new ToolbarTracker();
+ _toolbarTracker.CollectionChanged += ToolbarTrackerOnCollectionChanged;
+ }
+
+ var parents = new List<Page>();
+ Page root = Element;
+ while (!Application.IsApplicationOrNull(root.RealParent))
+ {
+ root = (Page)root.RealParent;
+ parents.Add(root);
+ }
+
+ _toolbarTracker.Target = e.NewElement;
+ _toolbarTracker.AdditionalTargets = parents;
+ UpdateMenu();
+
+ e.NewElement.PushRequested += OnPushed;
+ e.NewElement.PopRequested += OnPopped;
+ e.NewElement.PopToRootRequested += OnPoppedToRoot;
+ e.NewElement.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
+ e.NewElement.RemovePageRequested += OnRemovePageRequested;
+
+ // If there is already stuff on the stack we need to push it
+ e.NewElement.StackCopy.Reverse().ForEach(p => PushViewAsync(p, false));
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
+ UpdateToolbar();
+ else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
+ UpdateToolbar();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ AToolbar bar = _toolbar;
+ // make sure bar stays on top of everything
+ bar.BringToFront();
+
+ base.OnLayout(changed, l, t, r, b);
+
+ int barHeight = ActionBarHeight();
+
+ if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0)
+ {
+ ResetToolbar();
+ bar = _toolbar;
+ }
+ _lastActionBarHeight = barHeight;
+
+ bar.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(barHeight, MeasureSpecMode.Exactly));
+
+ int internalHeight = b - t - barHeight;
+ int containerHeight = ToolbarVisible ? internalHeight : b - t;
+ containerHeight -= ContainerPadding;
+
+ Element.ContainerArea = new Rectangle(0, 0, Context.FromPixels(r - l), Context.FromPixels(containerHeight));
+ // Potential for optimization here, the exact conditions by which you don't need to do this are complex
+ // and the cost of doing when it's not needed is moderate to low since the layout will short circuit pretty fast
+ Element.ForceLayout();
+
+ for (var i = 0; i < ChildCount; i++)
+ {
+ AView child = GetChildAt(i);
+ bool isBar = JNIEnv.IsSameObject(child.Handle, bar.Handle);
+
+ if (ToolbarVisible)
+ {
+ if (isBar)
+ bar.Layout(0, 0, r - l, barHeight);
+ else
+ child.Layout(0, barHeight + ContainerPadding, r, b);
+ }
+ else
+ {
+ if (isBar)
+ bar.Layout(0, -1000, r, barHeight - 1000);
+ else
+ child.Layout(0, ContainerPadding, r, b);
+ }
+ }
+ }
+
+ protected virtual void SetupPageTransition(FragmentTransaction transaction, bool isPush)
+ {
+ if (isPush)
+ transaction.SetTransition((int)FragmentTransit.FragmentOpen);
+ else
+ transaction.SetTransition((int)FragmentTransit.FragmentClose);
+ }
+
+ internal int GetNavBarHeight()
+ {
+ if (!ToolbarVisible)
+ return 0;
+
+ return ActionBarHeight();
+ }
+
+ int ActionBarHeight()
+ {
+ int attr = Resource.Attribute.actionBarSize;
+
+ int actionBarHeight;
+ using(var tv = new TypedValue())
+ {
+ actionBarHeight = 0;
+ if (Context.Theme.ResolveAttribute(attr, tv, true))
+ actionBarHeight = TypedValue.ComplexToDimensionPixelSize(tv.Data, Resources.DisplayMetrics);
+ }
+
+ if (actionBarHeight <= 0)
+ return Device.Info.CurrentOrientation.IsPortrait() ? (int)Context.ToPixels(56) : (int)Context.ToPixels(48);
+
+ return actionBarHeight;
+ }
+
+ void AnimateArrowIn()
+ {
+ var icon = _toolbar.NavigationIcon as DrawerArrowDrawable;
+ if (icon == null)
+ return;
+
+ ValueAnimator valueAnim = ValueAnimator.OfFloat(0, 1);
+ valueAnim.SetDuration(200);
+ valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
+ valueAnim.Start();
+ }
+
+ void AnimateArrowOut()
+ {
+ var icon = _toolbar.NavigationIcon as DrawerArrowDrawable;
+ if (icon == null)
+ return;
+
+ ValueAnimator valueAnim = ValueAnimator.OfFloat(1, 0);
+ valueAnim.SetDuration(200);
+ valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
+ valueAnim.Start();
+ }
+
+ void BarOnNavigationClick(object sender, AToolbar.NavigationClickEventArgs navigationClickEventArgs)
+ {
+ Element?.PopAsync();
+ }
+
+ void CurrentOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ ToolbarVisible = NavigationPage.GetHasNavigationBar(Current);
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ UpdateToolbar();
+ }
+
+ async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (nameof(Device.Info.CurrentOrientation) == e.PropertyName)
+ ResetToolbar();
+ }
+
+ void FilterPageFragment(Page page)
+ {
+ _fragmentStack.RemoveAll(f => ((FragmentContainer)f).Page == page);
+ }
+
+ void HandleToolbarItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName || e.PropertyName == MenuItem.TextProperty.PropertyName || e.PropertyName == MenuItem.IconProperty.PropertyName)
+ UpdateMenu();
+ }
+
+ void InsertPageBefore(Page page, Page before)
+ {
+ UpdateToolbar();
+
+ int index = Element.InternalChildren.IndexOf(before);
+ if (index == -1)
+ throw new InvalidOperationException("This should never happen, please file a bug");
+
+ Fragment fragment = FragmentContainer.CreateInstance(page);
+ _fragmentStack.Insert(index, fragment);
+ }
+
+ void OnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ InsertPageBefore(e.Page, e.BeforePage);
+ }
+
+ void OnPopped(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopViewAsync(e.Page, e.Animated);
+ }
+
+ void OnPoppedToRoot(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopToRootAsync(e.Page, e.Animated);
+ }
+
+ Task<bool> OnPopToRootAsync(Page page, bool animated)
+ {
+ return SwitchContentAsync(page, animated, true, true);
+ }
+
+ Task<bool> OnPopViewAsync(Page page, bool animated)
+ {
+ Page pageToShow = Element.StackCopy.Skip(1).FirstOrDefault();
+ if (pageToShow == null)
+ return Task.FromResult(false);
+
+ return SwitchContentAsync(pageToShow, animated, true);
+ }
+
+ Task<bool> OnPushAsync(Page view, bool animated)
+ {
+ return SwitchContentAsync(view, animated);
+ }
+
+ void OnPushed(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PushViewAsync(e.Page, e.Animated);
+ }
+
+ void OnRemovePageRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ RemovePage(e.Page);
+ }
+
+ void RegisterToolbar()
+ {
+ Context context = Context;
+ AToolbar bar = _toolbar;
+ Element page = Element.RealParent;
+
+ MasterDetailPage masterDetailPage = null;
+ while (page != null)
+ {
+ if (page is MasterDetailPage)
+ {
+ masterDetailPage = page as MasterDetailPage;
+ break;
+ }
+ page = page.RealParent;
+ }
+
+ if (masterDetailPage == null)
+ {
+ masterDetailPage = Element.InternalChildren[0] as MasterDetailPage;
+ if (masterDetailPage == null)
+ return;
+ }
+
+ if (masterDetailPage.ShouldShowSplitMode)
+ return;
+
+ var renderer = Android.Platform.GetRenderer(masterDetailPage) as MasterDetailPageRenderer;
+ if (renderer == null)
+ return;
+
+ var drawerLayout = (DrawerLayout)renderer;
+ _drawerToggle = new ActionBarDrawerToggle((Activity)context, drawerLayout, bar, global::Android.Resource.String.Ok, global::Android.Resource.String.Ok)
+ {
+ ToolbarNavigationClickListener = new ClickListener(Element)
+ };
+
+ drawerLayout.SetDrawerListener(new DrawerMultiplexedListener { Listeners = { _drawerToggle, renderer } });
+ _drawerToggle.DrawerIndicatorEnabled = true;
+ }
+
+ void RemovePage(Page page)
+ {
+ IVisualElementRenderer rendererToRemove = Android.Platform.GetRenderer(page);
+ var containerToRemove = (PageContainer)rendererToRemove?.ViewGroup.Parent;
+
+ // Also remove this page from the fragmentStack
+ FilterPageFragment(page);
+
+ containerToRemove.RemoveFromParent();
+ if (rendererToRemove != null)
+ {
+ rendererToRemove.ViewGroup.RemoveFromParent();
+ rendererToRemove.Dispose();
+ }
+ containerToRemove?.Dispose();
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(10), () =>
+ {
+ UpdateToolbar();
+ return false;
+ });
+ }
+
+ void ResetToolbar()
+ {
+ _toolbar.RemoveFromParent();
+ _toolbar.NavigationClick -= BarOnNavigationClick;
+ _toolbar = null;
+
+ SetupToolbar();
+ RegisterToolbar();
+ UpdateToolbar();
+ UpdateMenu();
+ }
+
+ void SetupToolbar()
+ {
+ Context context = Context;
+ var activity = (FormsAppCompatActivity)context;
+
+ AToolbar bar;
+ if (FormsAppCompatActivity.ToolbarResource != 0)
+ bar = activity.LayoutInflater.Inflate(FormsAppCompatActivity.ToolbarResource, null).JavaCast<AToolbar>();
+ else
+ bar = new AToolbar(context);
+
+ bar.NavigationClick += BarOnNavigationClick;
+
+ AddView(bar);
+ _toolbar = bar;
+ }
+
+ Task<bool> SwitchContentAsync(Page view, bool animated, bool removed = false, bool popToRoot = false)
+ {
+ var activity = (FormsAppCompatActivity)Context;
+ var tcs = new TaskCompletionSource<bool>();
+ Fragment fragment = FragmentContainer.CreateInstance(view);
+ FragmentManager fm = FragmentManager;
+ List<Fragment> fragments = _fragmentStack;
+
+ Current = view;
+
+ FragmentTransaction transaction = fm.BeginTransaction();
+
+ if (animated)
+ SetupPageTransition(transaction, !removed);
+
+ transaction.DisallowAddToBackStack();
+
+ if (fragments.Count == 0)
+ {
+ transaction.Add(Id, fragment);
+ fragments.Add(fragment);
+ }
+ else
+ {
+ if (removed)
+ {
+ // pop only one page, or pop everything to the root
+ var popPage = true;
+ while (fragments.Count > 1 && popPage)
+ {
+ Fragment currentToRemove = fragments.Last();
+ fragments.RemoveAt(fragments.Count - 1);
+ transaction.Remove(currentToRemove);
+ popPage = popToRoot;
+ }
+
+ Fragment toShow = fragments.Last();
+ // Execute pending transactions so that we can be sure the fragment list is accurate.
+ fm.ExecutePendingTransactions();
+ if (fm.Fragments.Contains(toShow))
+ transaction.Show(toShow);
+ else
+ transaction.Add(Id, toShow);
+ }
+ else
+ {
+ // push
+ Fragment currentToHide = fragments.Last();
+ transaction.Hide(currentToHide);
+ transaction.Add(Id, fragment);
+ fragments.Add(fragment);
+ }
+ }
+ transaction.Commit();
+
+ // The fragment transitions don't really SUPPORT telling you when they end
+ // There are some hacks you can do, but they actually are worse than just doing this:
+
+ if (animated)
+ {
+ if (!removed)
+ {
+ UpdateToolbar();
+ if (_drawerToggle != null && Element.StackDepth == 2)
+ AnimateArrowIn();
+ }
+ else if (_drawerToggle != null && Element.StackDepth == 2)
+ AnimateArrowOut();
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(200), () =>
+ {
+ tcs.TrySetResult(true);
+ fragment.UserVisibleHint = true;
+ if (removed)
+ UpdateToolbar();
+ return false;
+ });
+ }
+ else
+ {
+ Device.StartTimer(TimeSpan.FromMilliseconds(1), () =>
+ {
+ tcs.TrySetResult(true);
+ fragment.UserVisibleHint = true;
+ UpdateToolbar();
+ return false;
+ });
+ }
+
+ // 200ms is how long the animations are, and they are "reversible" in the sense that starting another one slightly before it's done is fine
+
+ return tcs.Task;
+ }
+
+ void ToolbarTrackerOnCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ UpdateMenu();
+ }
+
+ void UpdateMenu()
+ {
+ AToolbar bar = _toolbar;
+ Context context = Context;
+ IMenu menu = bar.Menu;
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ item.PropertyChanged -= HandleToolbarItemPropertyChanged;
+ menu.Clear();
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ {
+ item.PropertyChanged += HandleToolbarItemPropertyChanged;
+ if (item.Order == ToolbarItemOrder.Secondary)
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ else
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ FileImageSource icon = item.Icon;
+ if (!string.IsNullOrEmpty(icon))
+ {
+ Drawable iconBitmap = context.Resources.GetDrawable(icon);
+ if (iconBitmap != null)
+ menuItem.SetIcon(iconBitmap);
+ }
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetShowAsAction(ShowAsAction.Always);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ }
+ }
+
+ void UpdateToolbar()
+ {
+ if (_disposed)
+ return;
+
+ Context context = Context;
+ var activity = (FormsAppCompatActivity)context;
+ AToolbar bar = _toolbar;
+ ActionBarDrawerToggle toggle = _drawerToggle;
+
+ if (bar == null)
+ return;
+
+ bool isNavigated = Element.StackDepth > 1;
+ bar.NavigationIcon = null;
+
+ if (isNavigated)
+ {
+ if (toggle != null)
+ {
+ toggle.DrawerIndicatorEnabled = false;
+ toggle.SyncState();
+ }
+
+ if (NavigationPage.GetHasBackButton(Element.CurrentPage))
+ {
+ var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
+ icon.Progress = 1;
+ bar.NavigationIcon = icon;
+ }
+ }
+ else
+ {
+ if (toggle != null)
+ {
+ toggle.DrawerIndicatorEnabled = true;
+ toggle.SyncState();
+ }
+ }
+
+ Color tintColor = Element.BarBackgroundColor;
+
+ if (Forms.IsLollipopOrNewer)
+ {
+ if (tintColor.IsDefault)
+ bar.BackgroundTintMode = null;
+ else
+ {
+ bar.BackgroundTintMode = PorterDuff.Mode.Src;
+ bar.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToAndroid());
+ }
+ }
+ else
+ {
+ if (tintColor.IsDefault && _backgroundDrawable != null)
+ bar.SetBackground(_backgroundDrawable);
+ else if (!tintColor.IsDefault)
+ {
+ if (_backgroundDrawable == null)
+ _backgroundDrawable = bar.Background;
+ bar.SetBackgroundColor(tintColor.ToAndroid());
+ }
+ }
+
+ Color textColor = Element.BarTextColor;
+ if (!textColor.IsDefault)
+ bar.SetTitleTextColor(textColor.ToAndroid().ToArgb());
+
+ bar.Title = Element.CurrentPage.Title ?? "";
+ }
+
+ class ClickListener : Object, IOnClickListener
+ {
+ readonly NavigationPage _element;
+
+ public ClickListener(NavigationPage element)
+ {
+ _element = element;
+ }
+
+ public void OnClick(AView v)
+ {
+ _element?.PopAsync();
+ }
+ }
+
+ class DrawerMultiplexedListener : Object, DrawerLayout.IDrawerListener
+ {
+ public List<DrawerLayout.IDrawerListener> Listeners { get; } = new List<DrawerLayout.IDrawerListener>(2);
+
+ public void OnDrawerClosed(AView drawerView)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerClosed(drawerView);
+ }
+
+ public void OnDrawerOpened(AView drawerView)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerOpened(drawerView);
+ }
+
+ public void OnDrawerSlide(AView drawerView, float slideOffset)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerSlide(drawerView, slideOffset);
+ }
+
+ public void OnDrawerStateChanged(int newState)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerStateChanged(newState);
+ }
+ }
+ }
+} \ No newline at end of file