2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.ComponentModel;
21 using Tizen.NUI.BaseComponents;
22 using Tizen.NUI.Binding;
24 namespace Tizen.NUI.Components
27 /// PoppedEventArgs is a class to record <see cref="Navigator.Popped"/> event arguments which will be sent to user.
29 /// <since_tizen> 9 </since_tizen>
30 public class PoppedEventArgs : EventArgs
33 /// Page popped by Navigator.
35 /// <since_tizen> 9 </since_tizen>
36 public Page Page { get; internal set; }
40 /// The Navigator is a class which navigates pages with stack methods such as Push and Pop.
43 /// With Transition class, Navigator supports smooth transition of View pair between two Pages
44 /// by using <see cref="PushWithTransition(Page)"/> and <see cref="PopWithTransition()"/> methods.
45 /// If current top Page and next top Page have <see cref="View"/>s those have same TransitionTag,
46 /// Navigator creates smooth transition motion for them.
47 /// Navigator.Transition property can be used to set properties of the Transition such as TimePeriod and AlphaFunction.
48 /// When all transitions are finished, Navigator calls a callback methods those connected on the "TransitionFinished" event.
52 /// Navigator navigator = new Navigator()
54 /// TimePeriod = new TimePeriod(500),
55 /// AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseInOutSine)
58 /// View view = new View()
60 /// TransitionOptions = new TransitionOptions()
62 /// /* Set properties for the transition of this View */
66 /// ContentPage newPage = new ContentPage()
71 /// Navigator.PushWithTransition(newPage);
74 /// <since_tizen> 9 </since_tizen>
75 public class Navigator : Control
78 /// TransitionProperty
80 [EditorBrowsable(EditorBrowsableState.Never)]
81 public static readonly BindableProperty TransitionProperty = BindableProperty.Create(nameof(Transition), typeof(Transition), typeof(Navigator), null, propertyChanged: (bindable, oldValue, newValue) =>
83 var instance = (Navigator)bindable;
86 instance.InternalTransition = newValue as Transition;
89 defaultValueCreator: (bindable) =>
91 var instance = (Navigator)bindable;
92 return instance.InternalTransition;
96 /// EnableBackNavigationProperty
98 [EditorBrowsable(EditorBrowsableState.Never)]
99 public static readonly BindableProperty EnableBackNavigationProperty = BindableProperty.Create(nameof(EnableBackNavigation), typeof(bool), typeof(Navigator), default(bool), propertyChanged: (bindable, oldValue, newValue) =>
101 var instance = (Navigator)bindable;
102 if (newValue != null)
104 instance.InternalEnableBackNavigation = (bool)newValue;
107 defaultValueCreator: (bindable) =>
109 var instance = (Navigator)bindable;
110 return instance.InternalEnableBackNavigation;
113 private const int DefaultTransitionDuration = 300;
115 //This will be replaced with view transition class instance.
116 private Animation curAnimation = null;
118 //This will be replaced with view transition class instance.
119 private Animation newAnimation = null;
121 private TransitionSet transitionSet = null;
123 private Transition transition = new Transition()
125 TimePeriod = new TimePeriod(DefaultTransitionDuration),
126 AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Default),
129 private bool transitionFinished = true;
131 //TODO: Needs to consider how to remove disposed window from dictionary.
132 //Two dictionaries are required to remove disposed navigator from dictionary.
133 private static Dictionary<Window, Navigator> windowNavigator = new Dictionary<Window, Navigator>();
134 private static Dictionary<Navigator, Window> navigatorWindow = new Dictionary<Navigator, Window>();
136 private List<Page> navigationPages = new List<Page>();
138 private bool enableBackNavigation = true;
140 private Window parentWindow;
142 private void OnWindowKeyEvent(object sender, Window.KeyEventArgs e)
144 if (!EnableBackNavigation)
149 if ((e.Key.State == Key.StateType.Up) && ((e.Key.KeyPressedName == "Escape") || (e.Key.KeyPressedName == "BackSpace") || (e.Key.KeyPressedName == "XF86Back")))
153 Tizen.Log.Info("NUI", $"Navigator pops the peek page by {e.Key.KeyPressedName}.\n");
159 private void OnAddedToWindow(object sender, EventArgs e)
161 parentWindow = Window.Get(this);
162 parentWindow.KeyEvent += OnWindowKeyEvent;
165 private void OnRemovedFromWindow(object sender, EventArgs e)
167 parentWindow.KeyEvent -= OnWindowKeyEvent;
171 private void Initialize()
173 Layout = new AbsoluteLayout();
175 AddedToWindow += OnAddedToWindow;
176 RemovedFromWindow += OnRemovedFromWindow;
180 /// Creates a new instance of a Navigator.
182 /// <since_tizen> 9 </since_tizen>
183 public Navigator() : base()
189 /// Creates a new instance of a Navigator with style.
191 /// <param name="style">A style applied to the newly created Navigator.</param>
192 [EditorBrowsable(EditorBrowsableState.Never)]
193 public Navigator(ControlStyle style) : base(style)
199 [EditorBrowsable(EditorBrowsableState.Never)]
200 public override void OnInitialize()
204 AccessibilityRole = Role.PageTabList;
208 /// An event fired when Transition has been finished.
210 /// <since_tizen> 9 </since_tizen>
211 public event EventHandler<EventArgs> TransitionFinished;
214 /// An event fired when Pop of a page has been finished.
217 /// When you free resources in the Popped event handler, please make sure if the popped page is the page you find.
219 /// <since_tizen> 9 </since_tizen>
220 public event EventHandler<PoppedEventArgs> Popped;
223 /// Returns the count of pages in Navigator.
225 /// <since_tizen> 9 </since_tizen>
226 public int PageCount => navigationPages.Count;
229 /// Transition properties for the transition of View pair having same transition tag.
231 /// <since_tizen> 9 </since_tizen>
232 public Transition Transition
236 return GetValue(TransitionProperty) as Transition;
240 SetValue(TransitionProperty, value);
241 NotifyPropertyChanged();
244 private Transition InternalTransition
257 /// Pushes a page to Navigator.
258 /// If the page is already in Navigator, then it is not pushed.
260 /// <param name="page">The page to push to Navigator.</param>
261 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
262 /// <since_tizen> 9 </since_tizen>
263 public void PushWithTransition(Page page)
265 if (!transitionFinished)
267 Tizen.Log.Error("NUI", "Transition is still not finished.\n");
273 throw new ArgumentNullException(nameof(page), "page should not be null.");
276 //Duplicate page is not pushed.
277 if (navigationPages.Contains(page)) return;
279 var topPage = Peek();
287 navigationPages.Add(page);
289 page.Navigator = this;
292 page.InvokeAppearing();
293 topPage.InvokeDisappearing();
294 topPage.SaveKeyFocus();
296 transitionSet = CreateTransitions(topPage, page, true);
297 transitionSet.Finished += (object sender, EventArgs e) =>
299 if (page is DialogPage == false)
301 topPage.SetVisible(false);
304 // Need to update Content of the new page
305 ShowContentOfPage(page);
308 page.InvokeAppeared();
309 page.RestoreKeyFocus();
311 topPage.InvokeDisappeared();
312 NotifyAccessibilityStatesChangeOfPages(topPage, page);
314 transitionFinished = false;
318 /// Pops the top page from Navigator.
320 /// <returns>The popped page.</returns>
321 /// <exception cref="InvalidOperationException">Thrown when there is no page in Navigator.</exception>
322 /// <since_tizen> 9 </since_tizen>
323 public Page PopWithTransition()
325 if (!transitionFinished)
327 Tizen.Log.Error("NUI", "Transition is still not finished.\n");
331 if (navigationPages.Count == 0)
333 throw new InvalidOperationException("There is no page in Navigator.");
336 var topPage = Peek();
338 if (navigationPages.Count == 1)
342 //Invoke Popped event
343 Popped?.Invoke(this, new PoppedEventArgs() { Page = topPage });
347 var newTopPage = navigationPages[navigationPages.Count - 2];
350 newTopPage.InvokeAppearing();
351 topPage.InvokeDisappearing();
352 topPage.SaveKeyFocus();
354 transitionSet = CreateTransitions(topPage, newTopPage, false);
355 transitionSet.Finished += (object sender, EventArgs e) =>
358 topPage.SetVisible(true);
360 // Need to update Content of the new page
361 ShowContentOfPage(newTopPage);
364 newTopPage.InvokeAppeared();
365 newTopPage.RestoreKeyFocus();
367 topPage.InvokeDisappeared();
369 //Invoke Popped event
370 Popped?.Invoke(this, new PoppedEventArgs() { Page = topPage });
372 transitionFinished = false;
378 /// Pushes a page to Navigator.
379 /// If the page is already in Navigator, then it is not pushed.
381 /// <param name="page">The page to push to Navigator.</param>
382 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
383 /// <since_tizen> 9 </since_tizen>
384 public void Push(Page page)
386 if (!transitionFinished)
388 Tizen.Log.Error("NUI", "Transition is still not finished.\n");
394 throw new ArgumentNullException(nameof(page), "page should not be null.");
397 //Duplicate page is not pushed.
398 if (navigationPages.Contains(page)) return;
408 navigationPages.Add(page);
410 page.Navigator = this;
413 page.InvokeAppearing();
414 curTop.InvokeDisappearing();
416 curTop.SaveKeyFocus();
418 //TODO: The following transition codes will be replaced with view transition.
419 InitializeAnimation();
421 if (page is DialogPage == false)
423 curAnimation = new Animation(DefaultTransitionDuration);
424 curAnimation.AnimateTo(curTop, "PositionX", 0.0f, 0, DefaultTransitionDuration);
425 curAnimation.EndAction = Animation.EndActions.StopFinal;
426 curAnimation.Finished += (object sender, EventArgs args) =>
428 curTop.SetVisible(false);
431 curTop.InvokeDisappeared();
435 page.PositionX = SizeWidth;
436 page.SetVisible(true);
437 // Set Content visible because it was hidden by HideContentOfPage.
438 (page as ContentPage)?.Content?.SetVisible(true);
440 newAnimation = new Animation(DefaultTransitionDuration);
441 newAnimation.AnimateTo(page, "PositionX", 0.0f, 0, DefaultTransitionDuration);
442 newAnimation.EndAction = Animation.EndActions.StopFinal;
443 newAnimation.Finished += (object sender, EventArgs e) =>
445 // Need to update Content of the new page
446 ShowContentOfPage(page);
449 page.InvokeAppeared();
450 NotifyAccessibilityStatesChangeOfPages(curTop, page);
452 page.RestoreKeyFocus();
458 ShowContentOfPage(page);
459 page.RestoreKeyFocus();
464 /// Pops the top page from Navigator.
466 /// <returns>The popped page.</returns>
467 /// <exception cref="InvalidOperationException">Thrown when there is no page in Navigator.</exception>
468 /// <since_tizen> 9 </since_tizen>
471 if (!transitionFinished)
473 Tizen.Log.Error("NUI", "Transition is still not finished.\n");
477 if (navigationPages.Count == 0)
479 throw new InvalidOperationException("There is no page in Navigator.");
484 if (navigationPages.Count == 1)
488 //Invoke Popped event
489 Popped?.Invoke(this, new PoppedEventArgs() { Page = curTop });
494 var newTop = navigationPages[navigationPages.Count - 2];
497 newTop.InvokeAppearing();
498 curTop.InvokeDisappearing();
499 curTop.SaveKeyFocus();
501 //TODO: The following transition codes will be replaced with view transition.
502 InitializeAnimation();
504 if (curTop is DialogPage == false)
506 curAnimation = new Animation(DefaultTransitionDuration);
507 curAnimation.AnimateTo(curTop, "PositionX", SizeWidth, 0, DefaultTransitionDuration);
508 curAnimation.EndAction = Animation.EndActions.StopFinal;
509 curAnimation.Finished += (object sender, EventArgs e) =>
511 //Removes the current top page after transition is finished.
514 curTop.PositionX = 0.0f;
517 curTop.InvokeDisappeared();
519 //Invoke Popped event
520 Popped?.Invoke(this, new PoppedEventArgs() { Page = curTop });
524 newTop.SetVisible(true);
525 // Set Content visible because it was hidden by HideContentOfPage.
526 (newTop as ContentPage)?.Content?.SetVisible(true);
528 newAnimation = new Animation(DefaultTransitionDuration);
529 newAnimation.AnimateTo(newTop, "PositionX", 0.0f, 0, DefaultTransitionDuration);
530 newAnimation.EndAction = Animation.EndActions.StopFinal;
531 newAnimation.Finished += (object sender, EventArgs e) =>
533 // Need to update Content of the new page
534 ShowContentOfPage(newTop);
537 newTop.InvokeAppeared();
539 newTop.RestoreKeyFocus();
546 newTop.RestoreKeyFocus();
553 /// Returns the page of the given index in Navigator.
554 /// The indices of pages in Navigator are basically the order of pushing or inserting to Navigator.
555 /// So a page's index in Navigator can be changed whenever push/insert or pop/remove occurs.
557 /// <param name="index">The index of a page in Navigator.</param>
558 /// <returns>The page of the given index in Navigator.</returns>
559 /// <exception cref="ArgumentOutOfRangeException">Thrown when the argument index is less than 0, or greater than the number of pages.</exception>
560 public Page GetPage(int index)
562 if ((index < 0) || (index > navigationPages.Count))
564 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than or equal to the number of pages.");
567 return navigationPages[index];
571 /// Returns the current index of the given page in Navigator.
572 /// The indices of pages in Navigator are basically the order of pushing or inserting to Navigator.
573 /// So a page's index in Navigator can be changed whenever push/insert or pop/remove occurs.
575 /// <param name="page">The page in Navigator.</param>
576 /// <returns>The index of the given page in Navigator. If the given page is not in the Navigator, then -1 is returned.</returns>
577 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
578 /// <since_tizen> 9 </since_tizen>
579 public int IndexOf(Page page)
583 throw new ArgumentNullException(nameof(page), "page should not be null.");
586 for (int i = 0; i < navigationPages.Count; i++)
588 if (navigationPages[i] == page)
598 /// Inserts a page at the specified index of Navigator.
599 /// The indices of pages in Navigator are basically the order of pushing or inserting to Navigator.
600 /// So a page's index in Navigator can be changed whenever push/insert or pop/remove occurs.
601 /// To find the current index of a page in Navigator, please use IndexOf(page).
602 /// If the page is already in Navigator, then it is not inserted.
604 /// <param name="index">The index of a page in Navigator where the page will be inserted.</param>
605 /// <param name="page">The page to insert to Navigator.</param>
606 /// <exception cref="ArgumentOutOfRangeException">Thrown when the argument index is less than 0, or greater than the number of pages.</exception>
607 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
608 /// <since_tizen> 9 </since_tizen>
609 public void Insert(int index, Page page)
611 if ((index < 0) || (index > navigationPages.Count))
613 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than or equal to the number of pages.");
618 throw new ArgumentNullException(nameof(page), "page should not be null.");
621 //Duplicate page is not pushed.
622 if (navigationPages.Contains(page)) return;
624 //TODO: The following transition codes will be replaced with view transition.
625 InitializeAnimation();
627 ShowContentOfPage(page);
629 if (index == PageCount)
631 page.SetVisible(true);
635 page.SetVisible(false);
638 navigationPages.Insert(index, page);
640 page.SiblingOrder = index;
641 page.Navigator = this;
642 if (index == PageCount - 1)
646 NotifyAccessibilityStatesChangeOfPages(navigationPages[PageCount - 2], page);
650 NotifyAccessibilityStatesChangeOfPages(null, page);
656 /// Inserts a page to Navigator before an existing page.
657 /// If the page is already in Navigator, then it is not inserted.
659 /// <param name="before">The existing page, before which a page will be inserted.</param>
660 /// <param name="page">The page to insert to Navigator.</param>
661 /// <exception cref="ArgumentNullException">Thrown when the argument before is null.</exception>
662 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
663 /// <exception cref="ArgumentException">Thrown when the argument before does not exist in Navigator.</exception>
664 /// <since_tizen> 9 </since_tizen>
665 public void InsertBefore(Page before, Page page)
669 throw new ArgumentNullException(nameof(before), "before should not be null.");
674 throw new ArgumentNullException(nameof(page), "page should not be null.");
677 //Find the index of before page.
678 int beforeIndex = navigationPages.FindIndex(x => x == before);
680 //before does not exist in Navigator.
681 if (beforeIndex == -1)
683 throw new ArgumentException("before does not exist in Navigator.", nameof(before));
686 Insert(beforeIndex, page);
690 /// Removes a page from Navigator.
692 /// <param name="page">The page to remove from Navigator.</param>
693 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
694 /// <since_tizen> 9 </since_tizen>
695 public void Remove(Page page)
699 throw new ArgumentNullException(nameof(page), "page should not be null.");
702 //TODO: The following transition codes will be replaced with view transition.
703 InitializeAnimation();
705 HideContentOfPage(page);
711 navigationPages[PageCount - 2].SetVisible(true);
712 NotifyAccessibilityStatesChangeOfPages(page, navigationPages[PageCount - 2]);
714 else if (PageCount == 1)
716 NotifyAccessibilityStatesChangeOfPages(page, null);
719 page.Navigator = null;
720 navigationPages.Remove(page);
725 /// Removes a page at the specified index of Navigator.
726 /// The indices of pages in Navigator are basically the order of pushing or inserting to Navigator.
727 /// So a page's index in Navigator can be changed whenever push/insert or pop/remove occurs.
728 /// To find the current index of a page in Navigator, please use IndexOf(page).
730 /// <param name="index">The index of a page in Navigator where the page will be removed.</param>
731 /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is less than 0, or greater than or equal to the number of pages.</exception>
732 /// <since_tizen> 9 </since_tizen>
733 public void RemoveAt(int index)
735 if ((index < 0) || (index >= navigationPages.Count))
737 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than the number of pages.");
740 Remove(navigationPages[index]);
744 /// Returns the page at the top of Navigator.
746 /// <returns>The page at the top of Navigator.</returns>
747 /// <since_tizen> 9 </since_tizen>
750 if (navigationPages.Count == 0) return null;
752 return navigationPages[navigationPages.Count - 1];
756 /// Gets or sets if Navigator pops the peek page when back button or back key is pressed and released.
758 [EditorBrowsable(EditorBrowsableState.Never)]
759 public bool EnableBackNavigation
763 return (bool)GetValue(EnableBackNavigationProperty);
767 SetValue(EnableBackNavigationProperty, value);
768 NotifyPropertyChanged();
772 private bool InternalEnableBackNavigation
776 enableBackNavigation = value;
780 return enableBackNavigation;
785 /// Disposes Navigator and all children on it.
787 /// <param name="type">Dispose type.</param>
788 [EditorBrowsable(EditorBrowsableState.Never)]
789 protected override void Dispose(DisposeTypes type)
796 if (type == DisposeTypes.Explicit)
798 foreach (Page page in navigationPages)
800 Utility.Dispose(page);
802 navigationPages.Clear();
806 if (navigatorWindow.TryGetValue(this, out window) == true)
808 navigatorWindow.Remove(this);
809 windowNavigator.Remove(window);
812 AddedToWindow -= OnAddedToWindow;
813 RemovedFromWindow -= OnRemovedFromWindow;
820 /// Returns the default navigator of the given window.
822 /// <returns>The default navigator of the given window.</returns>
823 /// <exception cref="ArgumentNullException">Thrown when the argument window is null.</exception>
824 /// <since_tizen> 9 </since_tizen>
825 public static Navigator GetDefaultNavigator(Window window)
829 throw new ArgumentNullException(nameof(window), "window should not be null.");
832 if (windowNavigator.ContainsKey(window) == true)
834 return windowNavigator[window];
837 var defaultNavigator = new Navigator();
838 defaultNavigator.WidthResizePolicy = ResizePolicyType.FillToParent;
839 defaultNavigator.HeightResizePolicy = ResizePolicyType.FillToParent;
840 window.Add(defaultNavigator);
841 windowNavigator.Add(window, defaultNavigator);
842 navigatorWindow.Add(defaultNavigator, window);
844 return defaultNavigator;
848 /// Create Transitions between currentTopPage and newTopPage
850 /// <param name="currentTopPage">The top page of Navigator.</param>
851 /// <param name="newTopPage">The new top page after transition.</param>
852 /// <param name="pushTransition">True if this transition is for push new page</param>
853 private TransitionSet CreateTransitions(Page currentTopPage, Page newTopPage, bool pushTransition)
855 currentTopPage.SetVisible(true);
856 // Set Content visible because it was hidden by HideContentOfPage.
857 (currentTopPage as ContentPage)?.Content?.SetVisible(true);
859 newTopPage.SetVisible(true);
860 // Set Content visible because it was hidden by HideContentOfPage.
861 (newTopPage as ContentPage)?.Content?.SetVisible(true);
863 List<View> taggedViewsInNewTopPage = new List<View>();
864 RetrieveTaggedViews(taggedViewsInNewTopPage, newTopPage, true);
865 List<View> taggedViewsInCurrentTopPage = new List<View>();
866 RetrieveTaggedViews(taggedViewsInCurrentTopPage, currentTopPage, true);
868 List<KeyValuePair<View, View>> sameTaggedViewPair = new List<KeyValuePair<View, View>>();
869 foreach (View currentTopPageView in taggedViewsInCurrentTopPage)
871 bool findPair = false;
872 foreach (View newTopPageView in taggedViewsInNewTopPage)
874 if ((currentTopPageView.TransitionOptions != null) && (newTopPageView.TransitionOptions != null) &&
875 currentTopPageView.TransitionOptions?.TransitionTag == newTopPageView.TransitionOptions?.TransitionTag)
877 sameTaggedViewPair.Add(new KeyValuePair<View, View>(currentTopPageView, newTopPageView));
884 taggedViewsInNewTopPage.Remove(sameTaggedViewPair[sameTaggedViewPair.Count - 1].Value);
887 foreach (KeyValuePair<View, View> pair in sameTaggedViewPair)
889 taggedViewsInCurrentTopPage.Remove(pair.Key);
892 TransitionSet newTransitionSet = new TransitionSet();
893 foreach (KeyValuePair<View, View> pair in sameTaggedViewPair)
895 TransitionItem pairTransition = transition.CreateTransition(pair.Key, pair.Value, pushTransition);
896 if (pair.Value.TransitionOptions?.TransitionWithChild ?? false)
898 pairTransition.TransitionWithChild = true;
900 newTransitionSet.AddTransition(pairTransition);
903 newTransitionSet.Finished += (object sender, EventArgs e) =>
905 if (newTopPage.Layout != null)
907 newTopPage.Layout.RequestLayout();
909 if (currentTopPage.Layout != null)
911 currentTopPage.Layout.RequestLayout();
913 transitionFinished = true;
914 InvokeTransitionFinished();
915 transitionSet.Dispose();
918 if (!pushTransition || newTopPage is DialogPage == false)
920 View transitionView = (currentTopPage is ContentPage) ? (currentTopPage as ContentPage).Content : (currentTopPage as DialogPage).Content;
921 if (currentTopPage.DisappearingTransition != null && transitionView != null)
923 TransitionItemBase disappearingTransition = currentTopPage.DisappearingTransition.CreateTransition(transitionView, false);
924 disappearingTransition.TransitionWithChild = true;
925 newTransitionSet.AddTransition(disappearingTransition);
929 currentTopPage.SetVisible(false);
932 if (pushTransition || currentTopPage is DialogPage == false)
934 View transitionView = (newTopPage is ContentPage) ? (newTopPage as ContentPage).Content : (newTopPage as DialogPage).Content;
935 if (newTopPage.AppearingTransition != null && transitionView != null)
937 TransitionItemBase appearingTransition = newTopPage.AppearingTransition.CreateTransition(transitionView, true);
938 appearingTransition.TransitionWithChild = true;
939 newTransitionSet.AddTransition(appearingTransition);
943 newTransitionSet.Play();
945 return newTransitionSet;
949 /// Retrieve Tagged Views in the view tree.
951 /// <param name="taggedViews">Returned tagged view list..</param>
952 /// <param name="view">Root View to get tagged child View.</param>
953 /// <param name="isRoot">Flag to check current View is page or not</param>
954 private void RetrieveTaggedViews(List<View> taggedViews, View view, bool isRoot)
956 if (!isRoot && view.TransitionOptions != null)
958 if (!string.IsNullOrEmpty(view.TransitionOptions?.TransitionTag))
960 taggedViews.Add((view as View));
961 if (view.TransitionOptions.TransitionWithChild)
969 foreach (View child in view.Children)
971 RetrieveTaggedViews(taggedViews, child, false);
976 /// Notify accessibility states change of pages.
978 /// <param name="disappearedPage">Disappeared page</param>
979 /// <param name="appearedPage">Appeared page</param>
980 private void NotifyAccessibilityStatesChangeOfPages(Page disappearedPage, Page appearedPage)
982 if (disappearedPage != null)
984 disappearedPage.UnregisterDefaultLabel();
985 //We can call disappearedPage.NotifyAccessibilityStatesChange
986 //To reduce accessibility events, we are using currently highlighted view instead
987 View curHighlightedView = Accessibility.Accessibility.GetCurrentlyHighlightedView();
988 if (curHighlightedView != null)
990 curHighlightedView.NotifyAccessibilityStatesChange(new AccessibilityStates(AccessibilityState.Visible, AccessibilityState.Showing), AccessibilityStatesNotifyMode.Single);
994 if (appearedPage != null)
996 appearedPage.RegisterDefaultLabel();
997 appearedPage.NotifyAccessibilityStatesChange(new AccessibilityStates(AccessibilityState.Visible, AccessibilityState.Showing), AccessibilityStatesNotifyMode.Single);
1001 internal void InvokeTransitionFinished()
1003 TransitionFinished?.Invoke(this, new EventArgs());
1006 //TODO: The following transition codes will be replaced with view transition.
1007 private void InitializeAnimation()
1009 if (curAnimation != null)
1011 curAnimation.Stop();
1012 curAnimation.Clear();
1013 curAnimation = null;
1016 if (newAnimation != null)
1018 newAnimation.Stop();
1019 newAnimation.Clear();
1020 newAnimation = null;
1024 // Show and Register Content of Page to Accessibility bridge
1025 private void ShowContentOfPage(Page page)
1027 View content = (page is DialogPage) ? (page as DialogPage)?.Content : (page as ContentPage)?.Content;
1028 if (content != null)
1030 content.Show(); // Calls RegisterDefaultLabel()
1034 // Hide and Remove Content of Page from Accessibility bridge
1035 private void HideContentOfPage(Page page)
1037 View content = (page is DialogPage) ? (page as DialogPage)?.Content : (page as ContentPage)?.Content;
1038 if (content != null)
1040 content.Hide(); // Calls UnregisterDefaultLabel()