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;
            }
        }
示例#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);
        }
示例#3
0
        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;
                    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;
            }
        }