1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
17
18 #include "base/log/ace_checker.h"
19 #include "base/log/ace_performance_check.h"
20 #include "base/memory/ace_type.h"
21 #include "base/memory/referenced.h"
22 #include "base/perfmonitor/perf_constants.h"
23 #include "base/perfmonitor/perf_monitor.h"
24 #include "base/utils/utils.h"
25 #include "core/animation/page_transition_common.h"
26 #include "core/common/container.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/theme/app_theme.h"
29
30 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
31 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
32 #endif
33
34 #if !defined(ACE_UNITTEST)
35 #include "core/components_ng/base/transparent_node_detector.h"
36 #endif
37
38 #include "core/components_ng/base/view_stack_processor.h"
39 #include "core/components_ng/event/focus_hub.h"
40 #include "core/components_ng/pattern/button/button_layout_property.h"
41 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
42 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
43 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
44 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
45 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
46 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
47 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
48 #include "core/components_ng/pattern/navrouter/navdestination_event_hub.h"
49 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
50 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
51 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
52 #include "core/components_ng/pattern/navrouter/navrouter_event_hub.h"
53 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
54 #include "core/components_ng/pattern/stack/stack_layout_property.h"
55 #include "core/components_ng/pattern/stack/stack_model_ng.h"
56 #include "core/components_ng/pattern/stack/stack_pattern.h"
57 #include "core/components_ng/pattern/stage/page_pattern.h"
58 #include "core/components_ng/property/measure_property.h"
59 #include "core/components_ng/property/property.h"
60 #include "core/components_ng/render/render_context.h"
61 #include "core/components_v2/inspector/inspector_constants.h"
62
63 namespace OHOS::Ace::NG {
64 namespace {
65 constexpr double HALF = 0.5;
66 constexpr double PARENT_PAGE_OFFSET = 0.2;
67 constexpr double PARENT_TITLE_OFFSET = 0.02;
68 constexpr float REMOVE_CLIP_SIZE = 10000.0f;
69 constexpr int32_t MASK_DURATION = 350;
70 constexpr int32_t OPACITY_TITLE_OUT_DELAY = 17;
71 constexpr int32_t OPACITY_TITLE_IN_DELAY = 33;
72 constexpr int32_t OPACITY_TITLE_DURATION = 150;
73 constexpr int32_t OPACITY_BACKBUTTON_IN_DELAY = 150;
74 constexpr int32_t OPACITY_BACKBUTTON_IN_DURATION = 200;
75 constexpr int32_t OPACITY_BACKBUTTON_OUT_DURATION = 67;
76 constexpr int32_t DEFAULT_ANIMATION_DURATION = 450;
77 constexpr int32_t DEFAULT_REPLACE_DURATION = 150;
78 const Color MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
79 const RefPtr<InterpolatingSpring> springCurve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
80 const RefPtr<CubicCurve> replaceCurve = AceType::MakeRefPtr<CubicCurve>(0.33, 0.0, 0.67, 1.0);
81 } // namespace
82 class InspectorFilter;
83
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)84 RefPtr<NavigationGroupNode> NavigationGroupNode::GetOrCreateGroupNode(
85 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
86 {
87 auto frameNode = GetFrameNode(tag, nodeId);
88 CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast<NavigationGroupNode>(frameNode));
89 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
90 auto navigationGroupNode = AceType::MakeRefPtr<NavigationGroupNode>(tag, nodeId, pattern);
91 navigationGroupNode->InitializePatternAndContext();
92 ElementRegister::GetInstance()->AddUINode(navigationGroupNode);
93 return navigationGroupNode;
94 }
95
~NavigationGroupNode()96 NavigationGroupNode::~NavigationGroupNode()
97 {
98 auto navigationPattern = GetPattern<NavigationPattern>();
99 const auto& navDestinationNodes = navigationPattern->GetAllNavDestinationNodes();
100 for (auto iter : navDestinationNodes) {
101 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(iter.second));
102 if (navDestinationNode) {
103 navDestinationNode->GetPattern<NavDestinationPattern>()->SetCustomNode(nullptr);
104 }
105 }
106 auto context = PipelineContext::GetCurrentContext();
107 CHECK_NULL_VOID(context);
108 auto stageManager = context->GetStageManager();
109 CHECK_NULL_VOID(stageManager);
110 RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
111 CHECK_NULL_VOID(pageNode);
112 auto pagePattern = pageNode->GetPattern<PagePattern>();
113 CHECK_NULL_VOID(pagePattern);
114 CHECK_NULL_VOID(pagePattern->GetPageInfo());
115 int32_t pageId = pagePattern->GetPageInfo()->GetPageId();
116 context->RemoveNavigationNode(pageId, GetId());
117 context->DeleteNavigationNode(curId_);
118 }
119
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)120 void NavigationGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
121 {
122 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
123 CHECK_NULL_VOID(pattern);
124 auto navBar = AceType::DynamicCast<NavBarNode>(GetNavBarNode());
125 CHECK_NULL_VOID(navBar);
126 auto contentNode = navBar->GetContentNode();
127 if (!contentNode) {
128 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
129 contentNode = FrameNode::GetOrCreateFrameNode(
130 V2::NAVBAR_CONTENT_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
131 navBar->SetContentNode(contentNode);
132 navBar->AddChild(contentNode);
133
134 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
135 auto navBarContentNode = AceType::DynamicCast<FrameNode>(contentNode);
136 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
137 .edges = SAFE_AREA_EDGE_ALL };
138 navBarContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
139 }
140 }
141 contentNode->AddChild(child);
142 }
143
UpdateNavDestinationNodeWithoutMarkDirty(const RefPtr<UINode> & remainChild,bool modeChange)144 void NavigationGroupNode::UpdateNavDestinationNodeWithoutMarkDirty(const RefPtr<UINode>& remainChild, bool modeChange)
145 {
146 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
147 CHECK_NULL_VOID(pattern);
148 const auto& navDestinationNodes = pattern->GetAllNavDestinationNodes();
149
150 auto navigationContentNode = AceType::DynamicCast<FrameNode>(GetContentNode());
151 CHECK_NULL_VOID(navigationContentNode);
152 bool hasChanged = false;
153 int32_t slot = 0;
154 int32_t beforeLastStandardIndex = lastStandardIndex_;
155 auto preLastStandardNode = AceType::DynamicCast<NavDestinationGroupNode>(
156 navigationContentNode->GetChildAtIndex(beforeLastStandardIndex));
157
158 // save preLastStandardIndex_ before update and check whether standard page changed
159 preLastStandardIndex_ = lastStandardIndex_;
160 UpdateLastStandardIndex();
161
162 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "last standard page index is %{public}d", lastStandardIndex_);
163 if (!ReorderNavDestination(navDestinationNodes, navigationContentNode, slot, hasChanged)) {
164 return;
165 }
166
167 for (uint32_t index = 0; index < navDestinationNodes.size(); index++) {
168 const auto& childNode = navDestinationNodes[index];
169 const auto& uiNode = childNode.second;
170 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
171 hasChanged = (UpdateNavDestinationVisibility(navDestination, remainChild, index,
172 navDestinationNodes.size(), preLastStandardNode) || hasChanged);
173 }
174
175 RemoveRedundantNavDestination(
176 navigationContentNode, remainChild, static_cast<int32_t>(slot), hasChanged, preLastStandardNode);
177 if (modeChange) {
178 navigationContentNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
179 } else if (hasChanged) {
180 navigationContentNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
181 }
182 }
183
ReorderNavDestination(const std::vector<std::pair<std::string,RefPtr<UINode>>> & navDestinationNodes,RefPtr<FrameNode> & navigationContentNode,int32_t & slot,bool & hasChanged)184 bool NavigationGroupNode::ReorderNavDestination(
185 const std::vector<std::pair<std::string, RefPtr<UINode>>>& navDestinationNodes,
186 RefPtr<FrameNode>& navigationContentNode, int32_t& slot, bool& hasChanged)
187 {
188 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
189 CHECK_NULL_RETURN(pattern, false);
190 for (uint32_t i = 0; i != navDestinationNodes.size(); ++i) {
191 const auto& childNode = navDestinationNodes[i];
192 const auto& uiNode = childNode.second;
193 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
194 if (navDestination == nullptr) {
195 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "get destination node failed");
196 return false;
197 }
198 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
199 CHECK_NULL_RETURN(navDestinationPattern, false);
200 navDestinationPattern->SetName(childNode.first);
201 navDestinationPattern->SetCustomNode(uiNode);
202 navDestinationPattern->SetIndex(static_cast<int32_t>(i));
203 SetBackButtonEvent(navDestination);
204 navDestination->SetIndex(i);
205 auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
206 CHECK_NULL_RETURN(eventHub, false);
207 if (!eventHub->GetOnStateChange()) {
208 auto onStateChangeMap = pattern->GetOnStateChangeMap();
209 auto iter = onStateChangeMap.find(uiNode->GetId());
210 if (iter != onStateChangeMap.end()) {
211 eventHub->SetOnStateChange(iter->second);
212 pattern->DeleteOnStateChangeItem(iter->first);
213 }
214 }
215 int32_t childIndex = navigationContentNode->GetChildIndex(navDestination);
216 if (childIndex < 0) {
217 navDestination->MountToParent(navigationContentNode, slot);
218 hasChanged = true;
219 } else if (childIndex != slot) {
220 navDestination->MovePosition(slot);
221 hasChanged = true;
222 }
223 slot++;
224 }
225 return true;
226 }
227
RemoveRedundantNavDestination(RefPtr<FrameNode> & navigationContentNode,const RefPtr<UINode> & remainChild,int32_t slot,bool & hasChanged,const RefPtr<NavDestinationGroupNode> & preLastStandardNode)228 void NavigationGroupNode::RemoveRedundantNavDestination(RefPtr<FrameNode>& navigationContentNode,
229 const RefPtr<UINode>& remainChild, int32_t slot, bool& hasChanged,
230 const RefPtr<NavDestinationGroupNode>& preLastStandardNode)
231 {
232 auto pattern = GetPattern<NavigationPattern>();
233 RefPtr<UINode> maxAnimatingDestination = nullptr;
234 RefPtr<UINode> remainDestination = GetNavDestinationNode(remainChild);
235 RefPtr<UINode> curTopDestination = navigationContentNode->GetChildAtIndex(slot - 1);
236 // record remove destination size
237 int32_t removeSize = 0;
238 bool hideNodesFinish = false;
239 // record animating destination size
240 int32_t animatingSize = 0;
241 int32_t remainNodeIndex = -1;
242 int32_t beforeLastStandardIndex = preLastStandardNode == nullptr ? -1 : preLastStandardNode->GetIndex();
243 while (slot + removeSize + animatingSize < static_cast<int32_t>(navigationContentNode->GetChildren().size())) {
244 // delete useless nodes that are not at the top
245 int32_t candidateIndex = static_cast<int32_t>(navigationContentNode->GetChildren().size()) - 1 - animatingSize;
246 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
247 navigationContentNode->GetChildAtIndex(candidateIndex));
248 if (!navDestination) {
249 navigationContentNode->RemoveChildAtIndex(candidateIndex);
250 hasChanged = true;
251 continue;
252 }
253 auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
254 if (eventHub) {
255 eventHub->FireChangeEvent(false);
256 }
257 if (navDestination == remainDestination) {
258 if (pattern->IsCurTopNewInstance()) {
259 // remain the last child for push animation, and this child
260 // will be remove in push's animation finish callback
261 navDestination->SetNeedRemoveInPush(true);
262 remainNodeIndex = slot - 1;
263 navDestination->MovePosition(remainNodeIndex);
264 } else {
265 // remain the last child for pop animation
266 remainNodeIndex = slot;
267 navDestination->MovePosition(slot);
268 }
269 ++slot;
270 continue;
271 }
272 // The NavDestination in the EXIT animation needs to be cleaned in the animation onfinish callback.
273 if (navDestination->IsOnAnimation()) {
274 if (navDestination->GetTransitionType() == PageTransitionType::EXIT_POP) {
275 ++animatingSize;
276 continue;
277 }
278 if (navDestination->NeedRemoveInPush()) {
279 if (maxAnimatingDestination == nullptr) {
280 maxAnimatingDestination = navDestination;
281 }
282 ++animatingSize;
283 continue;
284 }
285 }
286 // remove content child
287 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
288 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "remove child: %{public}s", navDestinationPattern->GetName().c_str());
289 if (navDestination->GetIndex() >= beforeLastStandardIndex && !hideNodesFinish) {
290 if (navDestination->GetNavDestinationMode() == NavDestinationMode::STANDARD
291 && preLastStandardNode != navDestination) {
292 hideNodesFinish = true;
293 DealRemoveDestination(navDestination);
294 hasChanged = true;
295 continue;
296 }
297 hideNodes_.emplace_back(std::make_pair(navDestination, true));
298 navDestination->SetCanReused(false);
299 removeSize++;
300 auto index = slot + removeSize - 1;
301 // move current destination position to navigation stack size + remove navDestination nodes
302 if (index >= 0) {
303 navDestination->MovePosition(remainNodeIndex);
304 }
305 continue;
306 }
307 DealRemoveDestination(navDestination);
308 hasChanged = true;
309 }
310 if (pattern->IsCurTopNewInstance()) {
311 ReorderAnimatingDestination(
312 navigationContentNode, maxAnimatingDestination, remainDestination, curTopDestination);
313 }
314 }
315
ReorderAnimatingDestination(RefPtr<FrameNode> & navigationContentNode,RefPtr<UINode> & maxAnimatingDestination,RefPtr<UINode> & remainDestination,RefPtr<UINode> & curTopDestination)316 void NavigationGroupNode::ReorderAnimatingDestination(RefPtr<FrameNode>& navigationContentNode,
317 RefPtr<UINode>& maxAnimatingDestination, RefPtr<UINode>& remainDestination, RefPtr<UINode>& curTopDestination)
318 {
319 auto maxAnimatingIndex = navigationContentNode->GetChildIndex(maxAnimatingDestination);
320 if (maxAnimatingIndex != -1 && remainDestination) {
321 remainDestination->MovePosition(maxAnimatingIndex + 1);
322 }
323 auto remainIndex = navigationContentNode->GetChildIndex(remainDestination);
324 if (remainIndex != -1 && curTopDestination) {
325 curTopDestination->MovePosition(remainIndex + 1);
326 }
327 }
328
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const329 void NavigationGroupNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
330 {
331 FrameNode::ToJsonValue(json, filter);
332 auto navBarNode = AceType::DynamicCast<NavBarNode>(GetNavBarNode());
333 CHECK_NULL_VOID(navBarNode);
334 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
335 if (titleBarNode) {
336 std::string title = NavigationTitleUtil::GetTitleString(titleBarNode,
337 navBarNode->GetPrevTitleIsCustomValue(false));
338 std::string subtitle = NavigationTitleUtil::GetSubtitleString(titleBarNode);
339 json->PutExtAttr("title", title.c_str(), filter);
340 json->PutExtAttr("subtitle", subtitle.c_str(), filter);
341 }
342 json->PutExtAttr("menus", navBarNode->GetBarItemsString(true).c_str(), filter);
343 json->PutExtAttr("toolBar", navBarNode->GetBarItemsString(false).c_str(), filter);
344 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
345 CHECK_NULL_VOID(navBarLayoutProperty);
346 json->PutExtAttr("titleMode", navBarLayoutProperty->GetTitleModeString().c_str(), filter);
347 json->PutExtAttr("hideBackButton", navBarLayoutProperty->GetHideBackButtonValue(false), filter);
348 json->PutExtAttr("hideTitleBar", navBarLayoutProperty->GetHideTitleBarValue(false), filter);
349 json->PutExtAttr("hideToolBar", navBarLayoutProperty->GetHideToolBarValue(false), filter);
350 }
351
GetNavDestinationNode(RefPtr<UINode> uiNode)352 RefPtr<UINode> NavigationGroupNode::GetNavDestinationNode(RefPtr<UINode> uiNode)
353 {
354 if (!uiNode) {
355 return nullptr;
356 }
357 // create NavDestinationNode from uiNode stored in NavigationStack
358 while (uiNode) {
359 if (uiNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
360 // this is a navDestination node
361 return uiNode;
362 }
363 if (AceType::DynamicCast<UINode>(uiNode)) {
364 // this is an UINode, go deep further for navDestination node
365 auto children = uiNode->GetChildren();
366 uiNode = children.front();
367 continue;
368 }
369 }
370 CHECK_NULL_RETURN(uiNode, nullptr);
371 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "get navDestination node failed: id: %{public}d, %{public}s",
372 uiNode->GetId(), uiNode->GetTag().c_str());
373 return nullptr;
374 }
375
SetBackButtonEvent(const RefPtr<NavDestinationGroupNode> & navDestination)376 void NavigationGroupNode::SetBackButtonEvent(const RefPtr<NavDestinationGroupNode>& navDestination)
377 {
378 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode());
379 CHECK_NULL_VOID(titleBarNode);
380 auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
381 CHECK_NULL_VOID(backButtonNode);
382 auto backButtonEventHub = backButtonNode->GetEventHub<EventHub>();
383 CHECK_NULL_VOID(backButtonEventHub);
384 auto onBackButtonEvent = [navDestinationWeak = WeakPtr<NavDestinationGroupNode>(navDestination),
385 navigationWeak = WeakClaim(this)](GestureEvent& /*info*/) -> bool {
386 auto navDestination = navDestinationWeak.Upgrade();
387 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "click navigation back button");
388 CHECK_NULL_RETURN(navDestination, false);
389 auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
390 CHECK_NULL_RETURN(eventHub, false);
391 eventHub->SetState(NavDestinationState::ON_BACKPRESS);
392 auto navdestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
393 UIObserverHandler::GetInstance().NotifyNavigationStateChange(
394 navdestinationPattern, NavDestinationState::ON_BACKPRESS);
395 auto isOverride = eventHub->GetOnBackPressedEvent();
396 auto result = false;
397 if (isOverride) {
398 result = eventHub->FireOnBackPressedEvent();
399 }
400 if (result) {
401 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation user onBackPress return true");
402 return true;
403 }
404 auto navigation = navigationWeak.Upgrade();
405 CHECK_NULL_RETURN(navigation, false);
406 // if set hideNavBar and stack size is one, return false
407 auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(navigation->GetLayoutProperty());
408 auto pattern = AceType::DynamicCast<NavigationPattern>(navigation->GetPattern());
409 auto stack = pattern->GetNavigationStack();
410 CHECK_NULL_RETURN(stack, false);
411 if (navigationLayoutProperty->GetHideNavBarValue(false) && stack->Size() <= 1) {
412 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "set hideNavBar and stack size is no more than one");
413 return false;
414 }
415 auto isLastChild = stack->Size() == 1;
416 if (isOverride) {
417 result = navigation->HandleBack(navDestination, isLastChild, true);
418 } else {
419 result = navigation->HandleBack(navDestination, isLastChild, false);
420 }
421 // when js navigationStack is provided, modifyDone will be called by state manager.
422 auto navigationPattern = navigation->GetPattern<NavigationPattern>();
423 CHECK_NULL_RETURN(navigationPattern, false);
424 if (!navigationPattern->GetNavigationStackProvided()) {
425 navigation->MarkModifyDone();
426 navigation->MarkDirtyNode();
427 }
428
429 return result;
430 }; // backButton event
431
432 navDestination->SetNavDestinationBackButtonEvent(onBackButtonEvent);
433 backButtonEventHub->GetOrCreateGestureEventHub()->SetUserOnClick(onBackButtonEvent);
434 }
435
GetTopDestination()436 RefPtr<FrameNode> NavigationGroupNode::GetTopDestination()
437 {
438 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
439 CHECK_NULL_RETURN(pattern, nullptr);
440 auto navigationStack = pattern->GetNavigationStack();
441 CHECK_NULL_RETURN(navigationStack, nullptr);
442 auto topNavdestination = AceType::DynamicCast<FrameNode>(GetNavDestinationNode(navigationStack->Get()));
443 return topNavdestination;
444 }
445
CheckCanHandleBack(bool & isEntry)446 bool NavigationGroupNode::CheckCanHandleBack(bool& isEntry)
447 {
448 auto navigation = AceType::WeakClaim(this).Upgrade();
449 CHECK_NULL_RETURN(navigation, false);
450 auto navigationPattern = GetPattern<NavigationPattern>();
451 CHECK_NULL_RETURN(navigationPattern, false);
452
453 auto navigationStack = navigationPattern->GetNavigationStack();
454 CHECK_NULL_RETURN(navigationStack, false);
455 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
456 NavigationGroupNode::GetNavDestinationNode(navigationStack->Get()));
457 if (!navDestination) {
458 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "can't find destination node to process back press");
459 return false;
460 }
461 if (!navigationPattern->IsFinishInteractiveAnimation()) {
462 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "can't handle back press during interactive animation");
463 return true;
464 }
465 auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
466 if (navDestinationPattern->OverlayOnBackPressed()) {
467 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navDestination's ovelay consume backPressed event: %{public}s",
468 navDestinationPattern->GetName().c_str());
469 return true;
470 }
471 auto navDestinationContext = navDestinationPattern->GetNavDestinationContext();
472 CHECK_NULL_RETURN(navDestinationContext, false);
473 auto navPathInfo = navDestinationContext->GetNavPathInfo();
474 CHECK_NULL_RETURN(navPathInfo, false);
475 auto isPathEntry = navPathInfo->GetIsEntry();
476 if (isPathEntry) {
477 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "%{public}s is entry navDestination, do not consume backPressed event",
478 navDestinationPattern->GetName().c_str());
479 navPathInfo->SetIsEntry(false);
480 auto index = navDestinationContext->GetIndex();
481 navigationStack->SetIsEntryByIndex(index, false);
482 isEntry = true;
483 return false;
484 }
485 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navDestination consume back button event: %{public}s",
486 navDestinationPattern->GetName().c_str());
487 GestureEvent gestureEvent;
488 return navDestination->GetNavDestinationBackButtonEvent()(gestureEvent);
489 }
490
HandleBack(const RefPtr<FrameNode> & node,bool isLastChild,bool isOverride)491 bool NavigationGroupNode::HandleBack(const RefPtr<FrameNode>& node, bool isLastChild, bool isOverride)
492 {
493 auto navigationPattern = GetPattern<NavigationPattern>();
494 if (!isOverride && !isLastChild) {
495 navigationPattern->RemoveNavDestination();
496 return true;
497 }
498 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(node);
499 CHECK_NULL_RETURN(navDestination, false);
500
501 auto mode = navigationPattern->GetNavigationMode();
502 auto layoutProperty = GetLayoutProperty<NavigationLayoutProperty>();
503 if (isLastChild && (mode == NavigationMode::SPLIT ||
504 (mode == NavigationMode::STACK && layoutProperty->GetHideNavBar().value_or(false)))) {
505 return false;
506 }
507
508 navigationPattern->RemoveNavDestination();
509 return true;
510 }
511
TransitionWithPop(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)512 void NavigationGroupNode::TransitionWithPop(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
513 bool isNavBar)
514 {
515 CHECK_NULL_VOID(preNode);
516
517 auto preNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
518 CHECK_NULL_VOID(preNavDestination);
519 preNavDestination->SetTransitionType(PageTransitionType::EXIT_POP);
520
521 /* obtain preTitle, preBackIcon and preFrameSize of preNavDestination */
522 auto preTitleNode = AceType::DynamicCast<TitleBarNode>(preNavDestination->GetTitleBarNode());
523 CHECK_NULL_VOID(preTitleNode);
524 auto preBackIcon = AceType::DynamicCast<FrameNode>(preTitleNode->GetBackButton());
525 CHECK_NULL_VOID(preBackIcon);
526
527 auto preFrameSize = preNode->GetGeometryNode()->GetFrameSize();
528 RefPtr<TitleBarNode> curTitleBarNode;
529 if (!GetCurTitleBarNode(curTitleBarNode, curNode, isNavBar)) {
530 return;
531 }
532
533 /* create animation finish callback */
534 CleanPopAnimations();
535 AnimationFinishCallback callback = [weakPreNode = WeakPtr<NavDestinationGroupNode>(preNavDestination),
536 weakPreTitle = WeakPtr<TitleBarNode>(preTitleNode),
537 weakPreBackIcon = WeakPtr<FrameNode>(preBackIcon),
538 weakNavigation = WeakClaim(this)] {
539 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page pop transition end");
540 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation pop animation end");
541 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
542 auto navigation = weakNavigation.Upgrade();
543 auto backIcon = weakPreBackIcon.Upgrade();
544 if (navigation) {
545 navigation->isOnAnimation_ = false;
546 auto id = navigation->GetTopDestination() ? navigation->GetTopDestination()->GetAccessibilityId() : -1;
547 navigation->OnAccessibilityEvent(
548 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
549 navigation->CleanPopAnimations();
550 }
551
552 auto preNavDesNode = weakPreNode.Upgrade();
553 CHECK_NULL_VOID(preNavDesNode);
554 if (preNavDesNode->GetTransitionType() != PageTransitionType::EXIT_POP) {
555 // has another transition, just return
556 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "preNavDesNode has another transition");
557 return;
558 }
559 auto preNavDesPattern = preNavDesNode->GetPattern<NavDestinationPattern>();
560 CHECK_NULL_VOID(preNavDesPattern);
561 // NavRouter will restore the preNavDesNode and needs to set the initial state after the animation ends.
562 auto shallowBuilder = preNavDesPattern->GetShallowBuilder();
563 if (shallowBuilder && !preNavDesNode->IsCacheNode()) {
564 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
565 }
566 preNavDesNode->SetIsOnAnimation(false);
567 preNavDesNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
568 preNavDesNode->GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, REMOVE_CLIP_SIZE, REMOVE_CLIP_SIZE),
569 RadiusF(EdgeF(0.0f, 0.0f)));
570 preNavDesNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
571 auto preTitleNode = weakPreTitle.Upgrade();
572 if (preTitleNode) {
573 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
574 preTitleNode->GetRenderContext()->SetOpacity(1.0);
575 }
576 if (!preNavDesNode->IsCacheNode() && preNavDesNode->GetContentNode()) {
577 preNavDesNode->GetContentNode()->Clean();
578 }
579 if (backIcon) {
580 backIcon->GetRenderContext()->SetOpacity(1.0);
581 }
582 auto parent = preNavDesNode->GetParent();
583 CHECK_NULL_VOID(parent);
584 parent->RemoveChild(preNavDesNode);
585 auto context = PipelineContext::GetCurrentContext();
586 CHECK_NULL_VOID(context);
587 context->MarkNeedFlushMouseEvent();
588 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
589 };
590
591 /* set initial status of animation */
592 preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
593 preNode->GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, preFrameSize.Width(), REMOVE_CLIP_SIZE),
594 RadiusF(EdgeF(0.0f, 0.0f)));
595 preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
596 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
597 preNavDestination->SetIsOnAnimation(true);
598
599 if (curNode) {
600 auto curFrameSize = curNode->GetGeometryNode()->GetFrameSize();
601 curNode->GetRenderContext()->ClipWithRRect(
602 RectF(0.0f, 0.0f, REMOVE_CLIP_SIZE, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
603 float flag = CheckLanguageDirection();
604 curNode->GetRenderContext()->UpdateTranslateInXY({ -curFrameSize.Width() * PARENT_PAGE_OFFSET * flag, 0.0f });
605 curTitleBarNode->GetRenderContext()->UpdateTranslateInXY(
606 { curFrameSize.Width() * PARENT_TITLE_OFFSET * flag, 0.0f });
607 }
608
609 /* start transition animation */
610 AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
611 callback);
612 auto newPopAnimation = AnimationUtils::StartAnimation(option, [
613 this, preNode, preTitleNode, preFrameSize, curNode, curTitleBarNode]() {
614 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page pop transition start");
615 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
616 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation pop animation start");
617 /* preNode */
618 float flag = CheckLanguageDirection();
619 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
620 preNode->GetRenderContext()->ClipWithRRect(
621 RectF(0.0f, 0.0f, preFrameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
622 } else {
623 preNode->GetRenderContext()->ClipWithRRect(
624 RectF(preFrameSize.Width() * HALF, 0.0f, preFrameSize.Width(), REMOVE_CLIP_SIZE),
625 RadiusF(EdgeF(0.0f, 0.0f)));
626 }
627 preNode->GetRenderContext()->UpdateTranslateInXY({ preFrameSize.Width() * HALF * flag, 0.0f });
628 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ preFrameSize.Width() * HALF * flag, 0.0f });
629
630 /* curNode */
631 if (curNode) {
632 curNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
633 curTitleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
634 }
635 }, option.GetOnFinishEvent());
636 if (newPopAnimation) {
637 popAnimations_.emplace_back(newPopAnimation);
638 }
639
640 /* opacity for title and backIcon */
641 auto titleOpacityAnimation = TitleOpacityAnimation(preTitleNode, true);
642 if (titleOpacityAnimation) {
643 popAnimations_.emplace_back(titleOpacityAnimation);
644 }
645 auto backButtonAnimation = BackButtonAnimation(preBackIcon, false);
646 if (backButtonAnimation) {
647 popAnimations_.emplace_back(backButtonAnimation);
648 }
649
650 /* mask animation */
651 std::shared_ptr<AnimationUtils::Animation> maskAnimation;
652 if (curNode) {
653 AnimationOption maskOption = CreateAnimationOption(Curves::FRICTION, FillMode::FORWARDS, MASK_DURATION,
654 nullptr);
655 curNode->GetRenderContext()->SetActualForegroundColor(MASK_COLOR);
656 maskAnimation = AnimationUtils::StartAnimation(
657 maskOption, [curNode]() { curNode->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT); });
658 }
659 if (maskAnimation) {
660 popAnimations_.emplace_back(maskAnimation);
661 }
662
663 // clear this flag for navBar layout only
664 if (isNavBar) {
665 SetNeedSetInvisible(false);
666 }
667 isOnAnimation_ = true;
668 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
669 UiSessionManager::GetInstance().OnRouterChange(navigationPathInfo_, "navigationPopPage");
670 #endif
671 }
672
TransitionWithPush(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)673 void NavigationGroupNode::TransitionWithPush(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
674 bool isNavBar)
675 {
676 CHECK_NULL_VOID(preNode);
677 CHECK_NULL_VOID(curNode);
678
679 RefPtr<FrameNode> preTitleNode;
680 if (isNavBar) {
681 auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
682 navBarNode->SetTransitionType(PageTransitionType::EXIT_PUSH);
683 preTitleNode = navBarNode ? AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode()) : nullptr;
684 } else {
685 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
686 navDestination->SetTransitionType(PageTransitionType::EXIT_PUSH);
687 preTitleNode = navDestination ? AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode()) : nullptr;
688 }
689 CHECK_NULL_VOID(preTitleNode);
690
691 auto mode = GetNavigationMode();
692 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
693 CHECK_NULL_VOID(curNavDestination);
694 curNavDestination->SetTransitionType(PageTransitionType::ENTER_PUSH);
695 auto curTitleNode = AceType::DynamicCast<TitleBarNode>(curNavDestination->GetTitleBarNode());
696 CHECK_NULL_VOID(curTitleNode);
697
698 auto preFrameSize = preNode->GetGeometryNode()->GetFrameSize();
699 auto curFrameSize = curNode->GetGeometryNode()->GetFrameSize();
700
701 /* Create animation callback */
702 CleanPushAnimations();
703 AnimationFinishCallback callback = [weakPreNode = WeakPtr<FrameNode>(preNode),
704 weakPreTitle = WeakPtr<FrameNode>(preTitleNode),
705 weakNavigation = WeakClaim(this),
706 weakCurNode = WeakPtr<FrameNode>(curNode),
707 isNavBar] {
708 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page push transition end");
709 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
710 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation push animation end");
711 auto navigation = weakNavigation.Upgrade();
712 CHECK_NULL_VOID(navigation);
713 auto preNode = weakPreNode.Upgrade();
714 while (preNode) {
715 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
716 if (preDestination && preDestination->NeedRemoveInPush()) {
717 navigation->hideNodes_.emplace_back(std::make_pair(preDestination, true));
718 break;
719 }
720 auto preTitle = weakPreTitle.Upgrade();
721 if (preTitle) {
722 preTitle->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
723 }
724 preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
725 preNode->GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
726 bool needSetInvisible = false;
727 if (isNavBar) {
728 auto navbar = AceType::DynamicCast<NavBarNode>(preNode);
729 CHECK_NULL_VOID(navbar);
730 needSetInvisible = AceType::DynamicCast<NavBarNode>(preNode)->GetTransitionType() ==
731 PageTransitionType::EXIT_PUSH;
732 // store this flag for navBar layout only
733 navigation->SetNeedSetInvisible(needSetInvisible);
734 bool isInvisible = navbar->IsNodeInvisible(navigation);
735 if (needSetInvisible && isInvisible) {
736 navbar->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
737 navbar->SetJSViewActive(false);
738 navigation->NotifyPageHide();
739 }
740 } else {
741 preDestination->SetIsOnAnimation(false);
742 needSetInvisible = preDestination->GetTransitionType() == PageTransitionType::EXIT_PUSH;
743 bool isInvisible = preDestination->IsNodeInvisible(navigation);
744 if (needSetInvisible && isInvisible) {
745 preDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
746 preDestination->SetJSViewActive(false);
747 }
748 }
749 break;
750 }
751 navigation->RemoveDialogDestination();
752 auto id = navigation->GetTopDestination() ? navigation->GetTopDestination()->GetAccessibilityId() : -1;
753 navigation->OnAccessibilityEvent(
754 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
755 auto curNode = weakCurNode.Upgrade();
756 if (curNode) {
757 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
758 CHECK_NULL_VOID(curNavDestination);
759 if (curNavDestination->GetTransitionType() != PageTransitionType::ENTER_PUSH) {
760 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "curNode has another transition");
761 return;
762 }
763 curNavDestination->SetIsOnAnimation(false);
764 curNode->GetRenderContext()->RemoveClipWithRRect();
765 }
766 navigation->isOnAnimation_ = false;
767 navigation->CleanPushAnimations();
768 auto pattern = navigation->GetPattern<NavigationPattern>();
769 CHECK_NULL_VOID(pattern);
770 pattern->CheckContentNeedMeasure(navigation);
771 };
772
773 /* set initial status of animation */
774 /* preNode */
775 preNode->GetRenderContext()->RemoveClipWithRRect();
776 preNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
777 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
778 if (!isNavBar) {
779 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
780 preDestination->SetIsOnAnimation(true);
781 if (preDestination->NeedRemoveInPush()) {
782 preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
783 }
784 }
785 /* curNode */
786 float flag = CheckLanguageDirection();
787 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
788 curNode->GetRenderContext()->ClipWithRRect(
789 RectF(0.0f, 0.0f, curFrameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
790 } else {
791 curNode->GetRenderContext()->ClipWithRRect(
792 RectF(curFrameSize.Width() * HALF, 0.0f, curFrameSize.Width(), REMOVE_CLIP_SIZE),
793 RadiusF(EdgeF(0.0f, 0.0f)));
794 }
795 curNode->GetRenderContext()->UpdateTranslateInXY({ curFrameSize.Width() * HALF * flag, 0.0f });
796 curTitleNode->GetRenderContext()->UpdateTranslateInXY({ curFrameSize.Width() * HALF * flag, 0.0f });
797 curNavDestination->SetIsOnAnimation(true);
798
799 /* start transition animation */
800 AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
801 callback);
802 auto newPushAnimation = AnimationUtils::StartAnimation(option, [
803 this, preNode, preTitleNode, curNode, curTitleNode, preFrameSize, curFrameSize, mode]() {
804 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page push transition start");
805 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
806 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation push animation start");
807 float flag = CheckLanguageDirection();
808 // preNode
809 preNode->GetRenderContext()->UpdateTranslateInXY(
810 { -preFrameSize.Width() * PARENT_PAGE_OFFSET * flag, 0.0f });
811 preTitleNode->GetRenderContext()->UpdateTranslateInXY(
812 { preFrameSize.Width() * PARENT_TITLE_OFFSET * flag, 0.0f });
813 // curNode
814 curNode->GetRenderContext()->ClipWithRRect(
815 RectF(0.0f, 0.0f, curFrameSize.Width(), REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
816 curNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
817 curTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
818 }, option.GetOnFinishEvent());
819 if (newPushAnimation) {
820 pushAnimations_.emplace_back(newPushAnimation);
821 }
822 auto maskAnimation = MaskAnimation(preNode->GetRenderContext());
823 if (maskAnimation) {
824 pushAnimations_.emplace_back(maskAnimation);
825 }
826
827 // title opacity
828 auto titleOpacityAnimation = TitleOpacityAnimation(curTitleNode, false);
829 if (titleOpacityAnimation) {
830 pushAnimations_.emplace_back(titleOpacityAnimation);
831 }
832 // backIcon opacity
833 auto backIcon = AceType::DynamicCast<FrameNode>(curTitleNode->GetBackButton());
834 auto backButtonAnimation = BackButtonAnimation(backIcon, true);
835 if (backButtonAnimation) {
836 pushAnimations_.emplace_back(backButtonAnimation);
837 }
838 isOnAnimation_ = true;
839 if (AceChecker::IsPerformanceCheckEnabled()) {
840 int64_t startTime = GetSysTimestamp();
841 auto pipeline = AceType::DynamicCast<NG::PipelineContext>(PipelineContext::GetCurrentContext());
842 // After completing layout tasks at all nodes on the page, perform performance testing and management
843 pipeline->AddAfterLayoutTask([weakNav = WeakClaim(this), weakNode = WeakPtr<FrameNode>(curNode), startTime,
844 path = curNavDestination->GetNavDestinationPathInfo()]() {
845 auto navigation = weakNav.Upgrade();
846 CHECK_NULL_VOID(navigation);
847 auto curNode = weakNode.Upgrade();
848 int64_t endTime = GetSysTimestamp();
849 CHECK_NULL_VOID(curNode);
850 PerformanceCheckNodeMap nodeMap;
851 curNode->GetPerformanceCheckData(nodeMap);
852 AceScopedPerformanceCheck::RecordPerformanceCheckData(nodeMap, endTime - startTime, path);
853 });
854 }
855 #if !defined(ACE_UNITTEST)
856 TransparentNodeDetector::GetInstance().PostCheckNodeTransparentTask(curNode);
857 #endif
858 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
859 UiSessionManager::GetInstance().OnRouterChange(navigationPathInfo_, "navigationPushPage");
860 #endif
861 }
862
BackButtonAnimation(const RefPtr<FrameNode> & backButtonNode,bool isTransitionIn)863 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::BackButtonAnimation(
864 const RefPtr<FrameNode>& backButtonNode, bool isTransitionIn)
865 {
866 CHECK_NULL_RETURN(backButtonNode, nullptr);
867 AnimationOption transitionOption;
868 transitionOption.SetCurve(Curves::SHARP);
869 auto backButtonNodeContext = backButtonNode->GetRenderContext();
870 CHECK_NULL_RETURN(backButtonNodeContext, nullptr);
871 if (isTransitionIn) {
872 transitionOption.SetDelay(OPACITY_BACKBUTTON_IN_DELAY);
873 transitionOption.SetDuration(OPACITY_BACKBUTTON_IN_DURATION);
874 backButtonNodeContext->SetOpacity(0.0f);
875 return AnimationUtils::StartAnimation(transitionOption, [backButtonNodeContext]() {
876 CHECK_NULL_VOID(backButtonNodeContext);
877 backButtonNodeContext->SetOpacity(1.0f);
878 });
879 }
880 transitionOption.SetDuration(OPACITY_BACKBUTTON_OUT_DURATION);
881 // recover after transition animation.
882 backButtonNodeContext->SetOpacity(1.0f);
883 return AnimationUtils::StartAnimation(transitionOption, [backButtonNodeContext]() {
884 CHECK_NULL_VOID(backButtonNodeContext);
885 backButtonNodeContext->SetOpacity(0.0f);
886 });
887 }
888
MaskAnimation(const RefPtr<RenderContext> & transitionOutNodeContext)889 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::MaskAnimation(
890 const RefPtr<RenderContext>& transitionOutNodeContext)
891 {
892 AnimationOption maskOption;
893 maskOption.SetCurve(Curves::FRICTION);
894 maskOption.SetDuration(MASK_DURATION);
895 maskOption.SetFillMode(FillMode::FORWARDS);
896 transitionOutNodeContext->SetActualForegroundColor(Color::TRANSPARENT);
897 return AnimationUtils::StartAnimation(
898 maskOption, [transitionOutNodeContext]() { transitionOutNodeContext->SetActualForegroundColor(MASK_COLOR); },
899 maskOption.GetOnFinishEvent());
900 }
901
TitleOpacityAnimation(const RefPtr<FrameNode> & node,bool isTransitionOut)902 std::shared_ptr<AnimationUtils::Animation> NavigationGroupNode::TitleOpacityAnimation(
903 const RefPtr<FrameNode>& node, bool isTransitionOut)
904 {
905 auto titleNode = AceType::DynamicCast<TitleBarNode>(node);
906 CHECK_NULL_RETURN(titleNode, nullptr);
907 auto titleRenderContext = titleNode->GetRenderContext();
908 CHECK_NULL_RETURN(titleRenderContext, nullptr);
909 AnimationOption opacityOption;
910 opacityOption.SetCurve(Curves::SHARP);
911 opacityOption.SetDuration(OPACITY_TITLE_DURATION);
912 if (isTransitionOut) {
913 opacityOption.SetDelay(OPACITY_TITLE_OUT_DELAY);
914 // recover after transition animation.
915 titleRenderContext->SetOpacity(1.0f);
916 return AnimationUtils::StartAnimation(opacityOption, [titleRenderContext]() {
917 CHECK_NULL_VOID(titleRenderContext);
918 titleRenderContext->SetOpacity(0.0f);
919 });
920 }
921 opacityOption.SetDelay(OPACITY_TITLE_IN_DELAY);
922 titleRenderContext->SetOpacity(0.0f);
923 return AnimationUtils::StartAnimation(opacityOption, [titleRenderContext]() {
924 CHECK_NULL_VOID(titleRenderContext);
925 titleRenderContext->SetOpacity(1.0f);
926 });
927 }
928
TransitionWithReplace(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)929 void NavigationGroupNode::TransitionWithReplace(
930 const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode, bool isNavBar)
931 {
932 CHECK_NULL_VOID(preNode);
933 CHECK_NULL_VOID(curNode);
934 AnimationOption option;
935 option.SetCurve(replaceCurve);
936 option.SetFillMode(FillMode::FORWARDS);
937 option.SetDuration(DEFAULT_REPLACE_DURATION);
938 option.SetOnFinishEvent([weakPreNode = WeakPtr<FrameNode>(preNode), weakNavigation = WeakClaim(this),
939 isNavBar]() {
940 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation replace animation end");
941 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page replace transition end");
942 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
943 auto preNode = weakPreNode.Upgrade();
944 CHECK_NULL_VOID(preNode);
945 auto navigationNode = weakNavigation.Upgrade();
946 CHECK_NULL_VOID(navigationNode);
947 navigationNode->isOnAnimation_ = false;
948 auto id = navigationNode->GetTopDestination() ? navigationNode->GetTopDestination()->GetAccessibilityId() : -1;
949 navigationNode->OnAccessibilityEvent(
950 AccessibilityEventType::PAGE_CHANGE, id, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID);
951 navigationNode->DealNavigationExit(preNode, isNavBar);
952 auto context = PipelineContext::GetCurrentContext();
953 CHECK_NULL_VOID(context);
954 context->MarkNeedFlushMouseEvent();
955 });
956 preNode->GetEventHub<EventHub>()->SetEnabledInternal(false);
957 curNode->GetRenderContext()->UpdateOpacity(0.0f);
958 if (!isNavBar) {
959 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
960 if (navDestination) {
961 navDestination->SetIsOnAnimation(true);
962 }
963 }
964 AnimationUtils::Animate(
965 option,
966 [curNode]() {
967 ACE_SCOPED_TRACE_COMMERCIAL("Navigation page replace transition start");
968 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
969 curNode->GetRenderContext()->UpdateOpacity(1.0f);
970 },
971 option.GetOnFinishEvent());
972 isOnAnimation_ = true;
973 }
974
OnInspectorIdUpdate(const std::string & id)975 void NavigationGroupNode::OnInspectorIdUpdate(const std::string& id)
976 {
977 auto context = PipelineContext::GetCurrentContext();
978 CHECK_NULL_VOID(context);
979 context->AddOrReplaceNavigationNode(id, WeakClaim(this));
980 curId_ = id;
981 }
982
DealNavigationExit(const RefPtr<FrameNode> & preNode,bool isNavBar,bool isAnimated)983 void NavigationGroupNode::DealNavigationExit(const RefPtr<FrameNode>& preNode, bool isNavBar, bool isAnimated)
984 {
985 CHECK_NULL_VOID(preNode);
986 if (preNode->GetEventHub<EventHub>()) {
987 preNode->GetEventHub<EventHub>()->SetEnabledInternal(true);
988 }
989 if (isNavBar && isAnimated) {
990 SetNeedSetInvisible(true);
991 return;
992 }
993 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
994 CHECK_NULL_VOID(navDestinationNode);
995 navDestinationNode->SetIsOnAnimation(false);
996 auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
997 CHECK_NULL_VOID(navDestinationPattern);
998 auto navigationPattern = GetPattern<NavigationPattern>();
999 CHECK_NULL_VOID(navigationPattern);
1000 auto stack = navigationPattern->GetNavigationStack();
1001 bool isInStack = stack->FindIndex(navDestinationPattern->GetName(),
1002 navDestinationPattern->GetCustomNode(), true) != -1;
1003 if (isInStack) {
1004 RemoveDialogDestination(true);
1005 auto preContext = navDestinationNode->GetRenderContext();
1006 CHECK_NULL_VOID(preContext);
1007 preContext->UpdateZIndex(0);
1008 return;
1009 }
1010 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1011 if (shallowBuilder) {
1012 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1013 }
1014 // remove old navdestination node
1015 if (navDestinationNode->GetContentNode()) {
1016 navDestinationNode->GetContentNode()->Clean();
1017 }
1018 auto parent = AceType::DynamicCast<FrameNode>(preNode->GetParent());
1019 CHECK_NULL_VOID(parent);
1020 parent->RemoveChild(preNode);
1021 RemoveDialogDestination(true);
1022 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1023 }
1024
NotifyPageHide()1025 void NavigationGroupNode::NotifyPageHide()
1026 {
1027 auto context = PipelineContext::GetCurrentContext();
1028 CHECK_NULL_VOID(context);
1029 auto stageManager = context->GetStageManager();
1030 CHECK_NULL_VOID(stageManager);
1031 auto container = Container::Current();
1032 CHECK_NULL_VOID(container);
1033 auto pageUrlChecker = container->GetPageUrlChecker();
1034 CHECK_NULL_VOID(pageUrlChecker);
1035 RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1036 CHECK_NULL_VOID(pageNode);
1037 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
1038 CHECK_NULL_VOID(pagePattern);
1039 auto pageInfo = pagePattern->GetPageInfo();
1040 CHECK_NULL_VOID(pageInfo);
1041 pageUrlChecker->NotifyPageHide(pageInfo->GetPageUrl());
1042 }
1043
UpdateLastStandardIndex()1044 void NavigationGroupNode::UpdateLastStandardIndex()
1045 {
1046 // remove the impact of last standard index
1047 lastStandardIndex_ = -1;
1048 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1049 CHECK_NULL_VOID(navigationPattern);
1050 auto navigationStack = navigationPattern->GetNavigationStack();
1051 CHECK_NULL_VOID(navigationStack);
1052 const auto& navDestinationNodes = navigationStack->GetAllNavDestinationNodes();
1053 if (navDestinationNodes.size() == 0) {
1054 return;
1055 }
1056 for (int32_t index = static_cast<int32_t>(navDestinationNodes.size()) - 1; index >= 0; index--) {
1057 const auto& curPath = navDestinationNodes[index];
1058 const auto& uiNode = curPath.second;
1059 if (!uiNode) {
1060 continue;
1061 }
1062 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode(uiNode));
1063 if (navDestinationNode && navDestinationNode->GetNavDestinationMode() == NavDestinationMode::STANDARD) {
1064 lastStandardIndex_ = index;
1065 return;
1066 }
1067 }
1068 }
1069
UpdateNavDestinationVisibility(const RefPtr<NavDestinationGroupNode> & navDestination,const RefPtr<UINode> & remainChild,int32_t index,size_t destinationSize,const RefPtr<UINode> & preLastStandardNode)1070 bool NavigationGroupNode::UpdateNavDestinationVisibility(const RefPtr<NavDestinationGroupNode>& navDestination,
1071 const RefPtr<UINode>& remainChild, int32_t index, size_t destinationSize, const RefPtr<UINode>& preLastStandardNode)
1072 {
1073 auto eventHub = navDestination->GetEventHub<NavDestinationEventHub>();
1074 CHECK_NULL_RETURN(eventHub, false);
1075 if (index == static_cast<int32_t>(destinationSize) - 1) {
1076 // process shallow builder
1077 navDestination->ProcessShallowBuilder();
1078 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE, true);
1079 navDestination->SetJSViewActive(true);
1080 navDestination->GetEventHub<EventHub>()->SetEnabledInternal(true);
1081 // for the navDestination at the top, FireChangeEvent
1082 eventHub->FireChangeEvent(true);
1083 bool hasChanged = CheckNeedMeasure(navDestination->GetLayoutProperty()->GetPropertyChangeFlag());
1084 if (!hasChanged && NavigationLayoutAlgorithm::IsAutoHeight(GetLayoutProperty<NavigationLayoutProperty>())) {
1085 hasChanged = true;
1086 }
1087 return hasChanged;
1088 }
1089 if (index < lastStandardIndex_) {
1090 auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1091 if (navDestination->IsOnAnimation()) {
1092 return false;
1093 }
1094 if (!pattern || !pattern->GetIsOnShow()) {
1095 // push more than one standard navDestination, need to set invisible below newTopDestination
1096 auto navDestinationLayoutProperty = navDestination->GetLayoutProperty();
1097 CHECK_NULL_RETURN(navDestinationLayoutProperty, false);
1098 navDestinationLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1099 navDestination->SetJSViewActive(false);
1100 return false;
1101 }
1102 eventHub->FireChangeEvent(false);
1103 if (pattern->GetCustomNode() != remainChild) {
1104 if (navDestination->GetNavDestinationMode() == NavDestinationMode::DIALOG ||
1105 navDestination == AceType::DynamicCast<NavDestinationGroupNode>(preLastStandardNode)) {
1106 hideNodes_.insert(hideNodes_.begin(), std::pair(navDestination, false));
1107 } else {
1108 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
1109 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1110 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1111 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1112 }
1113 }
1114 return false;
1115 }
1116 auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1117 if (navDestination->GetPattern<NavDestinationPattern>()->GetCustomNode() != remainChild &&
1118 !navDestination->IsOnAnimation()) {
1119 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1120 navDestination->SetJSViewActive(true);
1121 }
1122 return false;
1123 }
1124
CreateAnimationOption(const RefPtr<Curve> & curve,FillMode mode,int32_t duration,const AnimationFinishCallback & callback)1125 AnimationOption NavigationGroupNode::CreateAnimationOption(const RefPtr<Curve>& curve, FillMode mode,
1126 int32_t duration, const AnimationFinishCallback& callback)
1127 {
1128 AnimationOption option;
1129 option.SetCurve(curve);
1130 option.SetFillMode(mode);
1131 option.SetDuration(duration);
1132 if (callback != nullptr) {
1133 option.SetOnFinishEvent(callback);
1134 }
1135 return option;
1136 }
1137
GetNavigationMode()1138 NavigationMode NavigationGroupNode::GetNavigationMode()
1139 {
1140 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1141 CHECK_NULL_RETURN(navigationPattern, NavigationMode::AUTO);
1142 return navigationPattern->GetNavigationMode();
1143 }
1144
OnDetachFromMainTree(bool recursive,PipelineContext * context)1145 void NavigationGroupNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1146 {
1147 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1148 if (pattern) {
1149 pattern->DetachNavigationStackFromParent();
1150 pattern->RemoveFromDumpManager();
1151 }
1152
1153 GroupNode::OnDetachFromMainTree(recursive, context);
1154 }
1155
FindNavigationParent(const std::string & parentName)1156 bool NavigationGroupNode::FindNavigationParent(const std::string& parentName)
1157 {
1158 auto parent = GetParent();
1159 while (parent) {
1160 if (parent->GetTag() == parentName) {
1161 AddDestinationNode(parent);
1162 return true;
1163 }
1164 parent = parent->GetParent();
1165 }
1166 return parent != nullptr;
1167 }
1168
AddDestinationNode(const RefPtr<UINode> & parent)1169 void NavigationGroupNode::AddDestinationNode(const RefPtr<UINode>& parent)
1170 {
1171 auto destinationNode = AceType::DynamicCast<NavDestinationGroupNode>(parent);
1172 if (destinationNode) {
1173 parentDestinationNode_ = destinationNode;
1174 }
1175 }
1176
OnAttachToMainTree(bool recursive)1177 void NavigationGroupNode::OnAttachToMainTree(bool recursive)
1178 {
1179 GroupNode::OnAttachToMainTree(recursive);
1180
1181 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1182 if (pattern) {
1183 pattern->AttachNavigationStackToParent();
1184 pattern->AddToDumpManager();
1185 }
1186 auto parent = GetParent();
1187 while (parent) {
1188 if (parent->GetTag() == V2::JS_VIEW_ETS_TAG) {
1189 break;
1190 }
1191 parent = parent->GetParent();
1192 }
1193 if (parent) {
1194 pattern->SetParentCustomNode(parent);
1195 } else {
1196 TAG_LOGE(AceLogTag::ACE_NAVIGATION, "parent custom node is nullptr");
1197 }
1198 bool findNavdestination = FindNavigationParent(V2::NAVDESTINATION_VIEW_ETS_TAG);
1199 auto pipelineContext = PipelineContext::GetCurrentContext();
1200 CHECK_NULL_VOID(pipelineContext);
1201 auto stageManager = pipelineContext->GetStageManager();
1202 CHECK_NULL_VOID(stageManager);
1203 RefPtr<FrameNode> pageNode = stageManager->GetLastPage();
1204 CHECK_NULL_VOID(pageNode);
1205 auto pagePattern = pageNode->GetPattern<PagePattern>();
1206 CHECK_NULL_VOID(pagePattern);
1207 CHECK_NULL_VOID(pagePattern->GetPageInfo());
1208 int32_t pageId = pagePattern->GetPageInfo()->GetPageId();
1209 if (!findNavdestination) {
1210 pipelineContext->AddNavigationNode(pageId, WeakClaim(this));
1211 }
1212 }
1213
FireHideNodeChange(NavDestinationLifecycle lifecycle)1214 void NavigationGroupNode::FireHideNodeChange(NavDestinationLifecycle lifecycle)
1215 {
1216 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1217 for (auto iter = hideNodes_.begin(); iter != hideNodes_.end(); ++iter) {
1218 auto navDestination = iter->first;
1219 if (!navDestination) {
1220 continue;
1221 }
1222 if (lifecycle == NavDestinationLifecycle::ON_WILL_DISAPPEAR) {
1223 if (iter->second) {
1224 navigationPattern->NotifyDestinationLifecycle(
1225 navDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
1226 }
1227 continue;
1228 }
1229 auto pattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1230 if (!pattern->GetIsOnShow()) {
1231 continue;
1232 }
1233 if (lifecycle == NavDestinationLifecycle::ON_WILL_HIDE) {
1234 navigationPattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1235 continue;
1236 }
1237 if (lifecycle == NavDestinationLifecycle::ON_HIDE) {
1238 navigationPattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1239 }
1240 }
1241 }
1242
CheckLanguageDirection()1243 float NavigationGroupNode::CheckLanguageDirection()
1244 {
1245 bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
1246 if (isRightToLeft) {
1247 return -1.0f;
1248 } else {
1249 return 1.0f;
1250 }
1251 }
GetCurTitleBarNode(RefPtr<TitleBarNode> & curTitleBarNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1252 bool NavigationGroupNode::GetCurTitleBarNode(
1253 RefPtr<TitleBarNode>& curTitleBarNode, const RefPtr<FrameNode>& curNode, bool isNavBar)
1254 {
1255 if (curNode) {
1256 if (isNavBar) {
1257 auto navBarNode = AceType::DynamicCast<NavBarNode>(curNode);
1258 CHECK_NULL_RETURN(navBarNode, false);
1259 navBarNode->SetTransitionType(PageTransitionType::ENTER_POP);
1260 curTitleBarNode = navBarNode ? AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode()) : nullptr;
1261 } else {
1262 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1263 CHECK_NULL_RETURN(curNavDestination, false);
1264 curNavDestination->SetTransitionType(PageTransitionType::ENTER_POP);
1265 curTitleBarNode =
1266 curNavDestination ? AceType::DynamicCast<TitleBarNode>(curNavDestination->GetTitleBarNode()) : nullptr;
1267 }
1268 CHECK_NULL_RETURN(curTitleBarNode, false);
1269 }
1270 return true;
1271 }
1272
RemoveDialogDestination(bool isReplace)1273 void NavigationGroupNode::RemoveDialogDestination(bool isReplace)
1274 {
1275 for (auto iter = hideNodes_.begin(); iter != hideNodes_.end(); iter++) {
1276 auto navDestination = iter->first;
1277 if (!navDestination) {
1278 continue;
1279 }
1280 if (!iter->second) {
1281 // navDestination node don't need to remove, update visibility invisible
1282 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
1283 navDestination->SetJSViewActive(false);
1284 if (!isReplace) {
1285 continue;
1286 }
1287 auto context = navDestination->GetRenderContext();
1288 if (!context) {
1289 continue;
1290 }
1291 context->UpdateZIndex(0);
1292 continue;
1293 }
1294 auto parent = navDestination->GetParent();
1295 if (!parent) {
1296 continue;
1297 }
1298 auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(navDestination->GetPattern());
1299 if (!navDestinationPattern) {
1300 continue;
1301 }
1302 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1303 if (shallowBuilder) {
1304 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1305 }
1306 if (navDestination->GetContentNode()) {
1307 navDestination->GetContentNode()->Clean();
1308 }
1309 parent->RemoveChild(navDestination);
1310 }
1311 hideNodes_.clear();
1312 }
1313
DealRemoveDestination(const RefPtr<NavDestinationGroupNode> & navDestination)1314 void NavigationGroupNode::DealRemoveDestination(const RefPtr<NavDestinationGroupNode>& navDestination)
1315 {
1316 // remove content child
1317 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
1318 auto pattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1319 if (navDestinationPattern->GetIsOnShow()) {
1320 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_HIDE);
1321 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_HIDE);
1322 navDestinationPattern->SetIsOnShow(false);
1323 }
1324 pattern->NotifyDestinationLifecycle(navDestination, NavDestinationLifecycle::ON_WILL_DISAPPEAR);
1325 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
1326 if (shallowBuilder) {
1327 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
1328 }
1329 if (navDestination->GetContentNode()) {
1330 navDestination->GetContentNode()->Clean();
1331 }
1332 contentNode_->RemoveChild(navDestination, true);
1333 }
1334
CreateAnimationWithDialogPop(const AnimationFinishCallback callback,const std::vector<WeakPtr<FrameNode>> preNavList,const std::vector<WeakPtr<FrameNode>> curNavList)1335 void NavigationGroupNode::CreateAnimationWithDialogPop(const AnimationFinishCallback callback,
1336 const std::vector<WeakPtr<FrameNode>> preNavList,
1337 const std::vector<WeakPtr<FrameNode>> curNavList)
1338 {
1339 // start transition animation
1340 AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
1341 callback);
1342 auto newPopAnimation = AnimationUtils::StartAnimation(option, [
1343 weakNavigation = WeakClaim(this), curNavList, preNavList]() {
1344 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
1345 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation start");
1346
1347 // do preNode transition
1348 auto navigation = weakNavigation.Upgrade();
1349 CHECK_NULL_VOID(navigation);
1350 for (auto iter: preNavList) {
1351 auto preNode = iter.Upgrade();
1352 CHECK_NULL_VOID(preNode);
1353 auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1354 if (preNavDesNode) {
1355 preNavDesNode->StartSystemTransitionPop(false);
1356 }
1357 }
1358
1359 // do currentNode transition
1360 for (auto iter: curNavList) {
1361 auto curNode = iter.Upgrade();
1362 CHECK_NULL_VOID(curNode);
1363 if (curNode->GetTag() == V2::NAVBAR_ETS_TAG) {
1364 auto curNavbar = AceType::DynamicCast<NavBarNode>(curNode);
1365 CHECK_NULL_VOID(curNavbar);
1366 curNavbar->StartSystemTransitionPop();
1367 } else {
1368 auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1369 CHECK_NULL_VOID(curDestination);
1370 curDestination->StartSystemTransitionPop(true);
1371 }
1372 }
1373 }, option.GetOnFinishEvent());
1374 if (newPopAnimation) {
1375 popAnimations_.emplace_back(newPopAnimation);
1376 }
1377 isOnAnimation_ = true;
1378 }
1379
TransitionWithDialogPop(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1380 void NavigationGroupNode::TransitionWithDialogPop(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
1381 bool isNavBar)
1382 {
1383 CHECK_NULL_VOID(preNode);
1384 std::vector<WeakPtr<FrameNode>> preNavList;
1385 InitPopPreList(preNode, preNavList);
1386 std::vector<WeakPtr<FrameNode>> curNavList;
1387 bool isNavbarNeedAnimation = lastStandardIndex_ == -1 || isNavBar;
1388 InitPopCurList(curNode, curNavList, isNavbarNeedAnimation);
1389
1390 /* create animation finish callback */
1391 CleanPopAnimations();
1392 AnimationFinishCallback callback = [preNavList, weakNavigation = WeakClaim(this)] {
1393 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation end");
1394 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
1395 auto navigation = weakNavigation.Upgrade();
1396 CHECK_NULL_VOID(navigation);
1397 navigation->isOnAnimation_ = false;
1398 navigation->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1399 navigation->CleanPopAnimations();
1400 for (auto iter = preNavList.rbegin(); iter != preNavList.rend(); ++iter) {
1401 auto preNode = (*iter).Upgrade();
1402 CHECK_NULL_VOID(preNode);
1403 auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1404 CHECK_NULL_VOID(preNavDesNode);
1405 if (preNavDesNode->SystemTransitionPopCallback(false)) {
1406 auto parent = preNavDesNode->GetParent();
1407 CHECK_NULL_VOID(parent);
1408 parent->RemoveChild(preNavDesNode);
1409 }
1410 navigation->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1411 }
1412 navigation->RemoveDialogDestination();
1413 auto context = PipelineContext::GetCurrentContext();
1414 CHECK_NULL_VOID(context);
1415 context->MarkNeedFlushMouseEvent();
1416 };
1417 CreateAnimationWithDialogPop(callback, preNavList, curNavList);
1418 }
1419
CreateAnimationWithDialogPush(const AnimationFinishCallback callback,const std::vector<WeakPtr<FrameNode>> prevNavList,const std::vector<WeakPtr<FrameNode>> curNavList)1420 void NavigationGroupNode::CreateAnimationWithDialogPush(const AnimationFinishCallback callback,
1421 const std::vector<WeakPtr<FrameNode>> prevNavList, const std::vector<WeakPtr<FrameNode>> curNavList)
1422 {
1423 // start transition animation
1424 AnimationOption option = CreateAnimationOption(springCurve, FillMode::FORWARDS, DEFAULT_ANIMATION_DURATION,
1425 callback);
1426 auto newPushAnimation = AnimationUtils::StartAnimation(option,
1427 [weakNavigation = WeakClaim(this), prevNavList, curNavList]() {
1428 PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
1429 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation start");
1430 auto navigation = weakNavigation.Upgrade();
1431 CHECK_NULL_VOID(navigation);
1432
1433 // preNode do EXIT PUSH animation
1434 for (auto iter : prevNavList) {
1435 auto preNode = iter.Upgrade();
1436 CHECK_NULL_VOID(preNode);
1437 if (preNode->GetTag() == V2::NAVBAR_ETS_TAG &&
1438 navigation->GetNavigationMode() == NavigationMode::STACK) {
1439 auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
1440 CHECK_NULL_VOID(navBarNode);
1441 navBarNode->StartSystemTransitionPush();
1442 } else {
1443 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1444 CHECK_NULL_VOID(preDestination);
1445 preDestination->StartSystemTransitionPush(false);
1446 }
1447 }
1448 // curNode do ENTER PUSH animation
1449 for (auto iter : curNavList) {
1450 auto curNode = iter.Upgrade();
1451 CHECK_NULL_VOID(curNode);
1452 auto curDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1453 if (curDestination) {
1454 curDestination->StartSystemTransitionPush(true);
1455 }
1456 }
1457 }, option.GetOnFinishEvent());
1458 if (newPushAnimation) {
1459 pushAnimations_.emplace_back(newPushAnimation);
1460 }
1461 isOnAnimation_ = true;
1462 }
1463
PreNodeFinishCallback(const RefPtr<FrameNode> & preNode)1464 void NavigationGroupNode::PreNodeFinishCallback(const RefPtr<FrameNode>& preNode)
1465 {
1466 CHECK_NULL_VOID(preNode);
1467 if (preNode->GetTag() == V2::NAVBAR_ETS_TAG) {
1468 auto preNavbar = AceType::DynamicCast<NavBarNode>(preNode);
1469 CHECK_NULL_VOID(preNavbar);
1470 preNavbar->SystemTransitionPushAction(false);
1471 bool needSetInvisible = preNavbar->GetTransitionType() == PageTransitionType::EXIT_PUSH;
1472 SetNeedSetInvisible(needSetInvisible);
1473 if (needSetInvisible && GetNavigationMode() == NavigationMode::STACK) {
1474 auto property = preNavbar->GetLayoutProperty();
1475 CHECK_NULL_VOID(property);
1476 property->UpdateVisibility(VisibleType::INVISIBLE);
1477 preNavbar->SetJSViewActive(false);
1478 NotifyPageHide();
1479 }
1480 return;
1481 }
1482 if (preNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1483 auto preDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1484 if (preDestination && preDestination->NeedRemoveInPush()) {
1485 hideNodes_.emplace_back(std::make_pair(preDestination, true));
1486 }
1487 preDestination->SystemTransitionPushCallback(false);
1488 }
1489 }
1490
TransitionWithDialogPush(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isNavBar)1491 void NavigationGroupNode::TransitionWithDialogPush(const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode,
1492 bool isNavBar)
1493 {
1494 if (!preNode || !curNode) {
1495 TAG_LOGE(AceLogTag::ACE_NAVIGATION, "dialog push animation terminated");
1496 return;
1497 }
1498 CleanPushAnimations();
1499
1500 // initialization
1501 bool isNavbarNeedAnimation = preLastStandardIndex_ == -1 || isNavBar;
1502 std::vector<WeakPtr<FrameNode>> prevNavList;
1503 InitPushPreList(preNode, prevNavList, isNavbarNeedAnimation);
1504 std::vector<WeakPtr<FrameNode>> curNavList;
1505 InitPushCurList(curNode, curNavList);
1506 AnimationFinishCallback callback = [weakNavigation = WeakClaim(this), prevNavList, curNavList] {
1507 PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
1508 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation end");
1509 auto navigation = weakNavigation.Upgrade();
1510 CHECK_NULL_VOID(navigation);
1511 for (auto iter : prevNavList) {
1512 auto preNode = iter.Upgrade();
1513 CHECK_NULL_VOID(preNode);
1514 navigation->PreNodeFinishCallback(preNode);
1515 }
1516 for (auto iter : curNavList) {
1517 auto curNode = iter.Upgrade();
1518 CHECK_NULL_VOID(curNode);
1519 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1520 CHECK_NULL_VOID(curNavDestination);
1521 curNavDestination->SystemTransitionPushCallback(true);
1522 }
1523 navigation->RemoveDialogDestination();
1524 navigation->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1525 navigation->isOnAnimation_ = false;
1526 navigation->CleanPushAnimations();
1527 };
1528 CreateAnimationWithDialogPush(callback, prevNavList, curNavList);
1529 }
1530
InitDialogTransition(const RefPtr<NavDestinationGroupNode> & node,bool isTransitionIn)1531 void NavigationGroupNode::InitDialogTransition(const RefPtr<NavDestinationGroupNode>& node, bool isTransitionIn)
1532 {
1533 CHECK_NULL_VOID(node);
1534 auto contentNode = AceType::DynamicCast<FrameNode>(node->GetContentNode());
1535 CHECK_NULL_VOID(contentNode);
1536 auto context = contentNode->GetRenderContext();
1537 CHECK_NULL_VOID(context);
1538 if (isTransitionIn) {
1539 context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1540 return;
1541 }
1542 context->UpdateTransformTranslate({ 0.0f,
1543 contentNode->GetGeometryNode()->GetFrameSize().Height(), 0.0f });
1544 }
1545
StartDialogtransition(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,bool isTransitionIn)1546 void NavigationGroupNode::StartDialogtransition(const RefPtr<FrameNode>& preNode,
1547 const RefPtr<FrameNode>& curNode, bool isTransitionIn)
1548 {
1549 AnimationOption option;
1550 const RefPtr<InterpolatingSpring> curve =
1551 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1552 const float defaultAmplitudePx = 0.005f;
1553 curve->UpdateMinimumAmplitudeRatio(defaultAmplitudePx);
1554 option.SetCurve(curve);
1555 option.SetFillMode(FillMode::FORWARDS);
1556 if (isTransitionIn) {
1557 DialogTransitionPushAnimation(preNode, curNode, option);
1558 } else {
1559 DialogTransitionPopAnimation(preNode, curNode, option);
1560 }
1561 }
1562
DialogTransitionPushAnimation(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,AnimationOption option)1563 void NavigationGroupNode::DialogTransitionPushAnimation(const RefPtr<FrameNode>& preNode,
1564 const RefPtr<FrameNode>& curNode, AnimationOption option)
1565 {
1566 CHECK_NULL_VOID(curNode);
1567 auto curNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1568 CHECK_NULL_VOID(curNavdestination);
1569 int32_t end = curNavdestination->GetIndex();
1570 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1571 CHECK_NULL_VOID(navigationPattern);
1572 const auto& navDestinationNodesCur = navigationPattern->GetAllNavDestinationNodes();
1573 int32_t start = 0;
1574 if (preNode && preNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1575 auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1576 CHECK_NULL_VOID(navdestination);
1577 start = navdestination->GetIndex() + 1;
1578 }
1579 // find the nodes need to do upward ENTER translation
1580 std::vector<WeakPtr<NavDestinationGroupNode>> curNavList;
1581 for (int32_t index = start; index <= end; index++) {
1582 auto navdestination = GetNavDestinationNode(navDestinationNodesCur[index].second);
1583 CHECK_NULL_VOID(navdestination);
1584 auto curNode = AceType::DynamicCast<FrameNode>(navdestination);
1585 CHECK_NULL_VOID(curNode);
1586 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1587 CHECK_NULL_VOID(curNavDestination);
1588 curNavDestination->InitDialogTransition(false);
1589 curNavList.emplace_back(WeakPtr<NavDestinationGroupNode>(curNavDestination));
1590 }
1591 CleanPushAnimations();
1592 option.SetOnFinishEvent([weakNavigation = WeakClaim(this)] {
1593 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation end");
1594 auto navigation = weakNavigation.Upgrade();
1595 CHECK_NULL_VOID(navigation);
1596 navigation->CleanPushAnimations();
1597 });
1598 auto newPushAnimation = AnimationUtils::StartAnimation(option,
1599 [curNavList]() {
1600 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog push animation start");
1601 for (auto iter: curNavList) {
1602 auto curNode = iter.Upgrade();
1603 if (curNode) {
1604 curNode->InitDialogTransition(true);
1605 }
1606 }
1607 },
1608 option.GetOnFinishEvent());
1609 if (newPushAnimation) {
1610 pushAnimations_.emplace_back(newPushAnimation);
1611 }
1612 }
1613
FindNodesPoped(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode)1614 std::vector<WeakPtr<NavDestinationGroupNode>> NavigationGroupNode::FindNodesPoped(
1615 const RefPtr<FrameNode>& preNode, const RefPtr<FrameNode>& curNode)
1616 {
1617 std::vector<WeakPtr<NavDestinationGroupNode>> preNavList;
1618 auto preNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1619 CHECK_NULL_RETURN(preNavdestinationNode, preNavList);
1620 auto end = preNavdestinationNode->GetIndex();
1621 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1622 CHECK_NULL_RETURN(navigationPattern, preNavList);
1623 const auto& navDestinationNodesPre = navigationPattern->GetAllNavDestinationNodesPrev();
1624 int32_t start = 0;
1625 if (curNode && curNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
1626 auto curNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1627 CHECK_NULL_RETURN(curNavdestination, preNavList);
1628 start = curNavdestination->GetIndex() + 1;
1629 }
1630 // find the nodes need to do downward EXIT translation
1631 for (int32_t index = start; index <= end; index++) {
1632 auto node = GetNavDestinationNode(navDestinationNodesPre[index].second.Upgrade());
1633 if (node) {
1634 auto preNode = AceType::DynamicCast<FrameNode>(node);
1635 CHECK_NULL_RETURN(preNode, preNavList);
1636 auto preNavDesNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1637 CHECK_NULL_RETURN(preNavDesNode, preNavList);
1638 preNavDesNode->InitDialogTransition(true);
1639 preNavList.emplace_back(WeakPtr<NavDestinationGroupNode>(preNavDesNode));
1640 }
1641 }
1642 return preNavList;
1643 }
1644
DialogTransitionPopAnimation(const RefPtr<FrameNode> & preNode,const RefPtr<FrameNode> & curNode,AnimationOption option)1645 void NavigationGroupNode::DialogTransitionPopAnimation(const RefPtr<FrameNode>& preNode,
1646 const RefPtr<FrameNode>& curNode, AnimationOption option)
1647 {
1648 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1649 CHECK_NULL_VOID(navigationPattern);
1650 auto preNavList = FindNodesPoped(preNode, curNode);
1651 CleanPopAnimations();
1652 option.SetOnFinishEvent(
1653 [preNavList, weakNavigation = WeakClaim(this)] {
1654 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation end");
1655 for (auto iter: preNavList) {
1656 auto preNode = iter.Upgrade();
1657 CHECK_NULL_VOID(preNode);
1658 auto parent = preNode->GetParent();
1659 CHECK_NULL_VOID(parent);
1660 parent->RemoveChild(preNode);
1661 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1662 }
1663 auto context = PipelineContext::GetCurrentContext();
1664 CHECK_NULL_VOID(context);
1665 context->MarkNeedFlushMouseEvent();
1666 auto navigation = weakNavigation.Upgrade();
1667 CHECK_NULL_VOID(navigation);
1668 navigation->CleanPopAnimations();
1669 });
1670 auto newPopAnimation = AnimationUtils::StartAnimation(
1671 option, [weakNavigation = WeakClaim(this), preNavList]() {
1672 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "navigation dialog pop animation start");
1673 auto navigation = weakNavigation.Upgrade();
1674 CHECK_NULL_VOID(navigation);
1675 for (auto iter: preNavList) {
1676 auto preNode = iter.Upgrade();
1677 CHECK_NULL_VOID(preNode);
1678 preNode->InitDialogTransition(false);
1679 }
1680 }, option.GetOnFinishEvent());
1681 if (newPopAnimation) {
1682 popAnimations_.emplace_back(newPopAnimation);
1683 }
1684 }
1685
InitPopPreList(const RefPtr<FrameNode> & preNode,std::vector<WeakPtr<FrameNode>> & preNavList)1686 void NavigationGroupNode::InitPopPreList(const RefPtr<FrameNode>& preNode, std::vector<WeakPtr<FrameNode>>& preNavList)
1687 {
1688 // find all the nodes need to do EXIT_POP
1689 int32_t preStartIndex = preLastStandardIndex_;
1690 if (preStartIndex == -1) {
1691 // eg. clear + push page1
1692 preStartIndex = 0;
1693 }
1694 auto preNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1695 CHECK_NULL_VOID(preNavdestinationNode);
1696 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1697 CHECK_NULL_VOID(navigationPattern);
1698 const auto& preNavDestinationNodes = navigationPattern->GetAllNavDestinationNodesPrev();
1699
1700 // find the nodes need to do EXIT_POP
1701 for (int32_t index = preStartIndex; index < static_cast<int32_t>(preNavDestinationNodes.size()); index++) {
1702 auto node = GetNavDestinationNode(preNavDestinationNodes[index].second.Upgrade());
1703 CHECK_NULL_VOID(node);
1704 auto preNode = AceType::DynamicCast<FrameNode>(node);
1705 CHECK_NULL_VOID(preNode);
1706 auto preNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1707 if (preNavDestination) {
1708 preNavDestination->InitSystemTransitionPop(false);
1709 preNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1710 }
1711 }
1712 }
1713
InitPopCurList(const RefPtr<FrameNode> & curNode,std::vector<WeakPtr<FrameNode>> & curNavList,bool isNavbarNeedAnimation)1714 void NavigationGroupNode::InitPopCurList(const RefPtr<FrameNode>& curNode, std::vector<WeakPtr<FrameNode>>& curNavList,
1715 bool isNavbarNeedAnimation)
1716 {
1717 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1718 CHECK_NULL_VOID(navigationPattern);
1719 auto curNavdestionNodes = navigationPattern->GetAllNavDestinationNodes();
1720 auto curStartIndex = lastStandardIndex_;
1721
1722 // navBar + D or navBar should be in animation
1723 if (isNavbarNeedAnimation) {
1724 curStartIndex = 0;
1725 }
1726 // if navBar should be in animation, do initialization and visibility should be true
1727 if (isNavbarNeedAnimation && navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1728 auto preNode = AceType::DynamicCast<FrameNode>(GetNavBarNode());
1729 if (preNode) {
1730 auto navBarNode = AceType::DynamicCast<NavBarNode>(preNode);
1731 CHECK_NULL_VOID(navBarNode);
1732 navBarNode->InitSystemTransitionPop();
1733 curNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1734 SetNeedSetInvisible(false);
1735 }
1736 }
1737 int32_t size = static_cast<int32_t>(curNavdestionNodes.size());
1738 if (size == 0) {
1739 return;
1740 }
1741 // find the nodes need to do ENTER_POP
1742 for (int32_t index = curStartIndex; index < size; index++) {
1743 auto node = GetNavDestinationNode(curNavdestionNodes[index].second);
1744 CHECK_NULL_VOID(node);
1745 auto curNode = AceType::DynamicCast<FrameNode>(node);
1746 if (curNode) {
1747 auto navdestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1748 CHECK_NULL_VOID(navdestination);
1749 navdestination->InitSystemTransitionPop(true);
1750 curNavList.emplace_back(WeakPtr<FrameNode>(curNode));
1751 }
1752 }
1753 }
1754
InitPushPreList(const RefPtr<FrameNode> & preNode,std::vector<WeakPtr<FrameNode>> & prevNavList,bool isNavbarNeedAnimation)1755 void NavigationGroupNode::InitPushPreList(const RefPtr<FrameNode>& preNode,
1756 std::vector<WeakPtr<FrameNode>>& prevNavList, bool isNavbarNeedAnimation)
1757 {
1758 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1759 CHECK_NULL_VOID(navigationPattern);
1760 auto stack = navigationPattern->GetNavigationStack();
1761 auto& preNavdestinationNodes = navigationPattern->GetAllNavDestinationNodesPrev();
1762 auto preStartIndex = preLastStandardIndex_;
1763
1764 // find the pre last standard index, if there is no pre standard or pre node is single navbar
1765 if (isNavbarNeedAnimation) {
1766 preStartIndex = 0;
1767 }
1768 // if pre node is nav bar or one of preNodes is nav bar and only stack with navbar's animation
1769 if (isNavbarNeedAnimation&& navigationPattern->GetNavigationMode() == NavigationMode::STACK) {
1770 auto preNode = AceType::DynamicCast<FrameNode>(GetNavBarNode());
1771 CHECK_NULL_VOID(preNode);
1772 auto preNavbar = AceType::DynamicCast<NavBarNode>(preNode);
1773 if (preNavbar) {
1774 SetNeedSetInvisible(false);
1775 preNavbar->SystemTransitionPushAction(true);
1776 prevNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1777 }
1778 }
1779 int32_t size = static_cast<int32_t>(preNavdestinationNodes.size());
1780 if (size == 0) {
1781 return;
1782 }
1783 // find the nodes need to do EXIT_PUSH
1784 for (int32_t index = preStartIndex; index < size; index++) {
1785 auto node = GetNavDestinationNode(preNavdestinationNodes[index].second.Upgrade());
1786 CHECK_NULL_VOID(node);
1787 auto preNode = AceType::DynamicCast<FrameNode>(node);
1788 CHECK_NULL_VOID(preNode);
1789 auto preNavdestination = AceType::DynamicCast<NavDestinationGroupNode>(preNode);
1790 if (preNavdestination) {
1791 preNavdestination->InitSystemTransitionPush(false);
1792 prevNavList.emplace_back(WeakPtr<FrameNode>(preNode));
1793 }
1794 }
1795 }
1796
InitPushCurList(const RefPtr<FrameNode> & curNode,std::vector<WeakPtr<FrameNode>> & curNavList)1797 void NavigationGroupNode::InitPushCurList(const RefPtr<FrameNode>& curNode, std::vector<WeakPtr<FrameNode>>& curNavList)
1798 {
1799 // find the nodes need to do ENTER_PUSH
1800 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(GetPattern());
1801 CHECK_NULL_VOID(navigationPattern);
1802 auto curNavdestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1803 CHECK_NULL_VOID(curNavdestinationNode);
1804 auto curEndIndex = curNavdestinationNode->GetIndex();
1805 auto curStartIndex = lastStandardIndex_;
1806 auto stack = navigationPattern->GetNavigationStack();
1807 for (int32_t index = curStartIndex; index <= curEndIndex; index++) {
1808 auto node = GetNavDestinationNode(stack->Get(index));
1809 CHECK_NULL_VOID(node);
1810 auto curNode = AceType::DynamicCast<FrameNode>(node);
1811 CHECK_NULL_VOID(curNode);
1812 auto curNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(curNode);
1813 CHECK_NULL_VOID(curNavDestination);
1814 curNavDestination->InitSystemTransitionPush(true);
1815 curNavList.emplace_back(WeakPtr<FrameNode>(curNode));
1816 }
1817 }
1818 } // namespace OHOS::Ace::NG
1819