예제 #1
0
        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);
            });
        }
예제 #2
0
        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);
        }
        Task <bool> SwitchContentAsync(Page page, bool animated, bool removed = false, bool popToRoot = 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 = page;

            ((Platform)Element.Platform).NavAnimationInProgress = true;
            FragmentTransaction transaction = FragmentManager.BeginTransaction();

            if (animated)
            {
                SetupPageTransition(transaction, !removed);
            }

            if (_fragmentStack.Count == 0)
            {
                transaction.Add(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.Remove(currentToRemove);
                        popPage = popToRoot;
                    }

                    Fragment toShow = _fragmentStack.Last();
                    // Execute pending transactions so that we can be sure the fragment list is accurate.
                    FragmentManager.ExecutePendingTransactions();
                    if (FragmentManager.Fragments.Contains(toShow))
                    {
                        transaction.Show(toShow);
                    }
                    else
                    {
                        transaction.Add(Id, toShow);
                    }
                }
                else
                {
                    // push
                    Fragment currentToHide = _fragmentStack.Last();
                    transaction.Hide(currentToHide);
                    transaction.Add(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.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);
        }