protected override void AddChildView(VisualElement childView) { _pageContainer = null; Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage); if (page == null) { // Not a NavigationPage or TabbedPage? Just do the normal thing base.AddChildView(childView); } else { // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a // FragmentContainer in order to get isolated fragment management Fragment fragment = FragmentContainer.CreateInstance(page); var fc = fragment as FragmentContainer; fc?.SetOnCreateCallback(pc => { _pageContainer = pc; SetDefaultBackgroundColor(pc.Child); }); FragmentTransaction transaction = FragmentManager.BeginTransaction(); transaction.DisallowAddToBackStack(); transaction.Add(Id, fragment); transaction.SetTransition((int)FragmentTransit.FragmentOpen); transaction.Commit(); } }
public override Fragment GetItem(int position) { var fragment = FragmentContainer.CreateInstance(_page.Children[position]); _fragments.Add(fragment); return(fragment); }
protected override void AddChildView(VisualElement childView) { _pageContainer = null; Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage); if (page == null) { // The thing we're adding is not a NavigationPage or TabbedPage, so we can just use the old AddChildView if (_currentFragment != null) { // But first, if the previous occupant of this container was a fragment, we need to remove it properly FragmentTransaction transaction = FragmentManager.BeginTransaction(); transaction.DisallowAddToBackStack(); transaction.Remove(_currentFragment); transaction.SetTransition((int)FragmentTransit.None); transaction.Commit(); _currentFragment = null; } base.AddChildView(childView); } else { // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a // FragmentContainer in order to get isolated fragment management Fragment fragment = FragmentContainer.CreateInstance(page); var fc = fragment as FragmentContainer; fc?.SetOnCreateCallback(pc => { _pageContainer = pc; SetDefaultBackgroundColor(pc.Child); }); FragmentTransaction transaction = FragmentManager.BeginTransaction(); transaction.DisallowAddToBackStack(); if (_currentFragment != null) { transaction.Remove(_currentFragment); } transaction.Add(Id, fragment); transaction.SetTransition((int)FragmentTransit.None); transaction.Commit(); _currentFragment = fragment; new Handler(Looper.MainLooper).PostAtFrontOfQueue(() => FragmentManager.ExecutePendingTransactions()); } }
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); }
Fragment GetFragment(Page page, bool removed, bool popToRoot) { // pop if (removed) { return(_fragmentStack[_fragmentStack.Count - 2]); } // pop to root if (popToRoot) { return(_fragmentStack[0]); } // push return(FragmentContainer.CreateInstance(page)); }
void InsertPageBefore(Page page, Page before) { if (!_isAttachedToWindow) { PushCurrentPages(); } UpdateToolbar(); int index = PageController.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); }
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); }); } Context.HideKeyboard(this); // 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); }
protected override void AddChildView(VisualElement childView) { _pageContainer = null; Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage); if (page == null) { // The thing we're adding is not a NavigationPage or TabbedPage, so we can just use the old AddChildView if (_currentFragment != null) { // But first, if the previous occupant of this container was a fragment, we need to remove it properly FragmentTransaction transaction = FragmentManager.BeginTransaction(); transaction.Remove(_currentFragment); transaction.SetTransition((int)FragmentTransit.None); // This is a removal of a fragment that's not going on the back stack; there's no reason to care // whether its state gets successfully saved, since we'll never restore it. Ergo, CommitAllowingStateLoss transaction.CommitAllowingStateLoss(); _currentFragment = null; } base.AddChildView(childView); } else { // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a // FragmentContainer in order to get isolated fragment management Fragment fragment = FragmentContainer.CreateInstance(page); var fc = fragment as FragmentContainer; fc?.SetOnCreateCallback(pc => { _pageContainer = pc; SetDefaultBackgroundColor(pc.Child); }); FragmentTransaction transaction = FragmentManager.BeginTransaction(); if (_currentFragment != null) { transaction.Remove(_currentFragment); } transaction.Add(Id, fragment); transaction.SetTransition((int)FragmentTransit.None); // We don't currently support fragment restoration // So we don't need to worry about loss of this fragment's state transaction.CommitAllowingStateLoss(); _currentFragment = fragment; new Handler(Looper.MainLooper).PostAtFrontOfQueue(() => { if (_pageContainer == null) { // The view we're hosting in the fragment was never created (possibly we're already // navigating to another page?) so there's nothing to commit return; } FragmentManager.ExecutePendingTransactions(); }); } }
protected override void AddChildView(VisualElement childView) { _pageContainer = null; Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage); if (page == null) { // The thing we're adding is not a NavigationPage or TabbedPage, so we can just use the old AddChildView if (_currentFragment != null) { if (!_parent.IsAttachedToRoot()) { return; } // But first, if the previous occupant of this container was a fragment, we need to remove it properly FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); transaction.RemoveEx(_currentFragment); transaction.SetTransitionEx((int)FragmentTransit.None); if (IsAttachedToWindow) { ExecuteTransaction(transaction); } else { _transaction = transaction; } _currentFragment = null; } base.AddChildView(childView); } else { if (!_parent.IsAttachedToRoot()) { return; } // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a // FragmentContainer in order to get isolated fragment management Fragment fragment = FragmentContainer.CreateInstance(page); var fc = fragment as FragmentContainer; fc?.SetOnCreateCallback(pc => { _pageContainer = pc; UpdateFlowDirection(); SetDefaultBackgroundColor(pc.Child); }); FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); if (_currentFragment != null) { transaction.RemoveEx(_currentFragment); } transaction.AddEx(Id, fragment); transaction.SetTransitionEx((int)FragmentTransit.None); if (IsAttachedToWindow) { ExecuteTransaction(transaction); } else { _transaction = transaction; } _currentFragment = fragment; } }
public override Fragment GetItem(int position) { return(FragmentContainer.CreateInstance(_page.Children[position])); }
Task <bool> SwitchContentAsync(Page view, bool animated, bool removed = false, bool popToRoot = false) { var tcs = new TaskCompletionSource <bool>(); Fragment fragment = FragmentContainer.CreateInstance(view); FragmentManager fm = FragmentManager; #if DEBUG // Enables logging of moveToState operations to logcat FragmentManager.EnableDebugLogging(true); #endif List <Fragment> fragments = _fragmentStack; Current = view; ((Platform)Element.Platform).NavAnimationInProgress = true; 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); } } // We don't currently support fragment restoration, so we don't need to worry about // whether the commit loses state transaction.CommitAllowingStateLoss(); // 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 && ((INavigationPageController)Element).StackDepth == 2) { AnimateArrowIn(); } } else if (_drawerToggle != null && ((INavigationPageController)Element).StackDepth == 2) { AnimateArrowOut(); } Device.StartTimer(TimeSpan.FromMilliseconds(TransitionDuration), () => { 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); }); } Context.HideKeyboard(this); ((Platform)Element.Platform).NavAnimationInProgress = false; // TransitionDuration is how long the built-in animations are, and they are "reversible" in the sense that starting another one slightly before it's done is fine return(tcs.Task); }
protected override void AddChildView(VisualElement childView) { _pageContainer = null; Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage); if (page == null) { // The thing we're adding is not a NavigationPage or TabbedPage, so we can just use the old AddChildView if (_currentFragment != null) { if (!_parent.IsAttachedToRoot()) { return; } // But first, if the previous occupant of this container was a fragment, we need to remove it properly FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); transaction.RemoveEx(_currentFragment); transaction.SetTransitionEx((int)FragmentTransit.None); // This is a removal of a fragment that's not going on the back stack; there's no reason to care // whether its state gets successfully saved, since we'll never restore it. Ergo, CommitAllowingStateLoss transaction.CommitAllowingStateLossEx(); _currentFragment = null; } base.AddChildView(childView); } else { if (!_parent.IsAttachedToRoot()) { return; } // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a // FragmentContainer in order to get isolated fragment management Fragment fragment = FragmentContainer.CreateInstance(page); var fc = fragment as FragmentContainer; fc?.SetOnCreateCallback(pc => { _pageContainer = pc; UpdateFlowDirection(); SetDefaultBackgroundColor(pc.Child); }); FragmentTransaction transaction = FragmentManager.BeginTransactionEx(); if (_currentFragment != null) { transaction.RemoveEx(_currentFragment); } transaction.AddEx(Id, fragment); transaction.SetTransitionEx((int)FragmentTransit.None); // We don't currently support fragment restoration // So we don't need to worry about loss of this fragment's state transaction.CommitAllowingStateLossEx(); _currentFragment = fragment; } }