void RemovePage(Page page) { if (!_isAttachedToWindow) { PushCurrentPages(); } Fragment fragment = GetPageFragment(page); if (fragment == null) { return; } #if DEBUG // Enables logging of moveToState operations to logcat FragmentManager.EnableDebugLogging(true); #endif // Go ahead and take care of the fragment bookkeeping for the page being removed FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); transaction.RemoveEx(fragment); transaction.CommitAllowingStateLossEx(); // And remove the fragment from our own stack _fragmentStack.Remove(fragment); Device.StartTimer(TimeSpan.FromMilliseconds(10), () => { UpdateToolbar(); return(false); }); }
void AddTransitionTimer(TaskCompletionSource <bool> tcs, Fragment fragment, FragmentManager fragmentManager, IReadOnlyCollection <Fragment> fragmentsToRemove, int duration, bool shouldUpdateToolbar) { Device.StartTimer(TimeSpan.FromMilliseconds(duration), () => { tcs.TrySetResult(true); Current?.SendAppearing(); if (shouldUpdateToolbar) { UpdateToolbar(); } if (fragmentsToRemove.Count > 0) { FragmentTransaction fragmentTransaction = fragmentManager.BeginTransactionEx(); foreach (Fragment frag in fragmentsToRemove) { fragmentTransaction.RemoveEx(frag); } fragmentTransaction.CommitAllowingStateLossEx(); } return(false); }); }
Task <bool> SwitchContentAsync(Page page, bool animated, bool removed = false, bool popToRoot = false) { if (!Element.IsAttachedToRoot()) { return(Task.FromResult(false)); } var tcs = new TaskCompletionSource <bool>(); Fragment fragment = GetFragment(page, removed, popToRoot); #if DEBUG // Enables logging of moveToState operations to logcat FragmentManager.EnableDebugLogging(true); #endif Current?.SendDisappearing(); Current = page; if (Platform != null) { Platform.NavAnimationInProgress = true; } FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); if (animated) { SetupPageTransition(transaction, !removed); } var fragmentsToRemove = new List <Fragment>(); if (_fragmentStack.Count == 0) { transaction.AddEx(Id, fragment); _fragmentStack.Add(fragment); } else { if (removed) { // pop only one page, or pop everything to the root var popPage = true; while (_fragmentStack.Count > 1 && popPage) { Fragment currentToRemove = _fragmentStack.Last(); _fragmentStack.RemoveAt(_fragmentStack.Count - 1); transaction.HideEx(currentToRemove); fragmentsToRemove.Add(currentToRemove); popPage = popToRoot; } Fragment toShow = _fragmentStack.Last(); // Execute pending transactions so that we can be sure the fragment list is accurate. FragmentManager.ExecutePendingTransactionsEx(); if (FragmentManager.Fragments.Contains(toShow)) { transaction.ShowEx(toShow); } else { transaction.AddEx(Id, toShow); } } else { // push Fragment currentToHide = _fragmentStack.Last(); transaction.HideEx(currentToHide); transaction.AddEx(Id, fragment); _fragmentStack.Add(fragment); } } // We don't currently support fragment restoration, so we don't need to worry about // whether the commit loses state transaction.CommitAllowingStateLossEx(); // 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 && NavigationPageController.StackDepth == 2) { AnimateArrowIn(); } } else if (_drawerToggle != null && NavigationPageController.StackDepth == 2) { AnimateArrowOut(); } AddTransitionTimer(tcs, fragment, FragmentManager, fragmentsToRemove, TransitionDuration, removed); } else { AddTransitionTimer(tcs, fragment, FragmentManager, fragmentsToRemove, 1, true); } Context.HideKeyboard(this); if (Platform != null) { Platform.NavAnimationInProgress = false; } return(tcs.Task); }
protected override void Dispose(bool disposing) { if (disposing && !_disposed) { _disposed = true; if (_titleViewRenderer != null) { Android.Platform.ClearRenderer(_titleViewRenderer.View); _titleViewRenderer.Dispose(); _titleViewRenderer = null; } _toolbar.RemoveView(_titleView); _titleView?.Dispose(); _titleView = null; _toolbar.RemoveView(_titleIconView); _titleIconView?.Dispose(); _titleIconView = null; _imageSource = null; if (_toolbarTracker != null) { _toolbarTracker.CollectionChanged -= ToolbarTrackerOnCollectionChanged; _toolbarTracker.Target = null; _toolbarTracker = null; } if (_toolbar != null) { _toolbar.SetNavigationOnClickListener(null); _toolbar.Dispose(); _toolbar = null; } if (_drawerLayout != null && _drawerListener != null) { _drawerLayout.RemoveDrawerListener(_drawerListener); } if (_drawerListener != null) { _drawerListener.Dispose(); _drawerListener = null; } if (_drawerToggle != null) { _drawerToggle.Dispose(); _drawerToggle = null; } if (_backgroundDrawable != null) { _backgroundDrawable.Dispose(); _backgroundDrawable = null; } Current = null; // We dispose the child renderers after cleaning up everything related to DrawerLayout in case // one of the children is a MasterDetailPage (which may dispose of the DrawerLayout). if (Element != null) { foreach (Element element in PageController.InternalChildren) { var child = element as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Android.Platform.GetRenderer(child); renderer?.Dispose(); } var navController = NavigationPageController; navController.PushRequested -= OnPushed; navController.PopRequested -= OnPopped; navController.PopToRootRequested -= OnPoppedToRoot; navController.InsertPageBeforeRequested -= OnInsertPageBeforeRequested; navController.RemovePageRequested -= OnRemovePageRequested; } Device.Info.PropertyChanged -= DeviceInfoPropertyChanged; // API only exists on newer android YAY if ((int)Build.VERSION.SdkInt >= 17) { FragmentManager fm = FragmentManager; if (!fm.IsDestroyed) { FragmentTransaction trans = fm.BeginTransactionEx(); foreach (Fragment fragment in _fragmentStack) { trans.RemoveEx(fragment); } trans.CommitAllowingStateLossEx(); fm.ExecutePendingTransactionsEx(); } } } base.Dispose(disposing); }