1 /*
2 * Copyright (c) 2022 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/common/container.h"
17 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
18
19 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
20 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
21 #include "core/components_ng/pattern/navigation/navigation_transition_proxy.h"
22 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
23 #include "core/components_ng/pattern/navrouter/navdestination_context.h"
24 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
25 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
26 #include "core/components_ng/pattern/text/text_layout_property.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28 #include "core/components_ng/pattern/text/text_pattern.h"
29
30 namespace OHOS::Ace::NG {
31 constexpr double HALF = 0.5;
32 constexpr float CONTENT_OFFSET_PERCENT = 0.2f;
33 constexpr float TITLE_OFFSET_PERCENT = 0.02f;
34 constexpr float REMOVE_CLIP_SIZE = 10000.0f;
35 constexpr int32_t MAX_RENDER_GROUP_TEXT_NODE_COUNT = 50;
36 constexpr int32_t OPACITY_TITLE_OUT_DELAY = 17;
37 constexpr int32_t OPACITY_TITLE_IN_DELAY = 33;
38 constexpr int32_t OPACITY_TITLE_DURATION = 150;
39 constexpr int32_t OPACITY_BACKBUTTON_IN_DELAY = 150;
40 constexpr int32_t OPACITY_BACKBUTTON_IN_DURATION = 200;
41 constexpr int32_t OPACITY_BACKBUTTON_OUT_DURATION = 67;
42 constexpr float MAX_RENDER_GROUP_TEXT_NODE_HEIGHT = 150.0f;
43 constexpr int32_t INVALID_ANIMATION_ID = -1;
44 constexpr int32_t SYSTEM_ENTER_FADE_TRANSITION_DURATION = 250;
45 constexpr int32_t SYSTEM_EXIT_FADE_TRANSITION_DURATION = 200;
46 constexpr int32_t SYSTEM_ENTER_FADE_TRANSITION_DELAY = 50;
47 constexpr int32_t SYSTEM_EXIT_FADE_TRANSITION_DELAY = 0;
48 constexpr int32_t SYSTEM_EXPLODE_TRANSITION_MASK_DURATION = 300;
49 constexpr int32_t SYSTEM_ENTER_POP_EXPLODE_OPACITY_DURATION = 250;
50 constexpr int32_t SYSTEM_ENTER_POP_EXPLODE_OPACITY_DELAY = 50;
51 constexpr int32_t SYSTEM_ENTER_PUSH_EXPLODE_OPACITY_DURATION = 300;
52 constexpr int32_t SYSTEM_ENTER_PUSH_EXPLODE_OPACITY_DELAY = 50;
53 constexpr int32_t SYSTEM_EXIT_POP_EXPLODE_OPACITY_DURATION = 150;
54 constexpr int32_t SYSTEM_EXIT_PUSH_EXPLODE_OPACITY_DELAY = 200;
55 constexpr int32_t SYSTEM_SLIDE_TRANSITION_MASK_DURATION = 350;
56 const Color SLIDE_ANIMATION_MASK_COLOR = Color::FromARGB(25, 0, 0, 0);
57
58 namespace {
BuildAnimationOption(const RefPtr<Curve> & curve,std::function<void ()> && onFinishEvent,int32_t duration=0,int32_t delay=0)59 AnimationOption BuildAnimationOption(const RefPtr<Curve>& curve, std::function<void()>&& onFinishEvent,
60 int32_t duration = 0, int32_t delay = 0)
61 {
62 AnimationOption option(curve, duration);
63 option.SetDelay(delay);
64 option.SetOnFinishEvent(std::move(onFinishEvent));
65 return option;
66 }
67 }
68
~NavDestinationGroupNode()69 NavDestinationGroupNode::~NavDestinationGroupNode()
70 {
71 if (contentNode_) {
72 contentNode_->Clean();
73 }
74 ReleaseTextNodeList();
75 }
76
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)77 RefPtr<NavDestinationGroupNode> NavDestinationGroupNode::GetOrCreateGroupNode(
78 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
79 {
80 auto frameNode = GetFrameNode(tag, nodeId);
81 CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast<NavDestinationGroupNode>(frameNode));
82 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
83 auto navDestinationNode = AceType::MakeRefPtr<NavDestinationGroupNode>(tag, nodeId, pattern);
84 navDestinationNode->InitializePatternAndContext();
85 ElementRegister::GetInstance()->AddUINode(navDestinationNode);
86 return navDestinationNode;
87 }
88
IsNeedContentTransition()89 bool NavDestinationGroupNode::IsNeedContentTransition()
90 {
91 if (systemTransitionType_ == NavigationSystemTransitionType::DEFAULT) {
92 return true;
93 }
94 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) != NavigationSystemTransitionType::NONE;
95 }
96
TransitionContentInValid()97 bool NavDestinationGroupNode::TransitionContentInValid()
98 {
99 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) == NavigationSystemTransitionType::NONE
100 && mode_ == NavDestinationMode::STANDARD;
101 }
102
IsNeedTitleTransition()103 bool NavDestinationGroupNode::IsNeedTitleTransition()
104 {
105 if (systemTransitionType_ == NavigationSystemTransitionType::DEFAULT) {
106 return true;
107 }
108 if (mode_ == NavDestinationMode::STANDARD) {
109 return (systemTransitionType_ & NavigationSystemTransitionType::TITLE) != NavigationSystemTransitionType::NONE;
110 }
111 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) != NavigationSystemTransitionType::NONE;
112 }
113
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)114 void NavDestinationGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
115 {
116 auto pattern = AceType::DynamicCast<Pattern>(GetPattern());
117 CHECK_NULL_VOID(pattern);
118 auto contentNode = GetContentNode();
119 if (!contentNode) {
120 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
121 ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::NAVDESTINATION_CONTENT_ETS_TAG, nodeId);
122 contentNode = FrameNode::GetOrCreateFrameNode(V2::NAVDESTINATION_CONTENT_ETS_TAG, nodeId,
123 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
124 SetContentNode(contentNode);
125 AddChild(contentNode);
126
127 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
128 auto navdestinationContentNode = AceType::DynamicCast<FrameNode>(contentNode);
129 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
130 .edges = SAFE_AREA_EDGE_ALL };
131 navdestinationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
132 }
133 }
134 contentNode->AddChild(child, slot);
135 }
136
DeleteChildFromGroup(int32_t slot)137 void NavDestinationGroupNode::DeleteChildFromGroup(int32_t slot)
138 {
139 auto navDestination = GetContentNode();
140 CHECK_NULL_VOID(navDestination);
141 navDestination->RemoveChildAtIndex(slot);
142 }
143
OnAttachToMainTree(bool recursive)144 void NavDestinationGroupNode::OnAttachToMainTree(bool recursive)
145 {
146 if (!UseOffscreenProcess()) {
147 ProcessShallowBuilder();
148 }
149 FrameNode::OnAttachToMainTree(recursive);
150 }
151
OnOffscreenProcess(bool recursive)152 void NavDestinationGroupNode::OnOffscreenProcess(bool recursive)
153 {
154 ProcessShallowBuilder();
155 FrameNode::OnOffscreenProcess(recursive);
156 }
157
ProcessShallowBuilder()158 void NavDestinationGroupNode::ProcessShallowBuilder()
159 {
160 if (isCacheNode_) {
161 return;
162 }
163
164 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "render navDestination content");
165 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
166 CHECK_NULL_VOID(navDestinationPattern);
167 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
168 if (shallowBuilder && !shallowBuilder->IsExecuteDeepRenderDone()) {
169 auto eventHub = GetEventHub<NavDestinationEventHub>();
170 if (eventHub) {
171 auto ctx = navDestinationPattern->GetNavDestinationContext();
172 eventHub->FireOnReady(ctx);
173 }
174 shallowBuilder->ExecuteDeepRender();
175 GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
176 AceType::DynamicCast<FrameNode>(contentNode_)
177 ->GetLayoutProperty()
178 ->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
179 }
180 }
181
GetNavDestinationCustomNode()182 RefPtr<CustomNodeBase> NavDestinationGroupNode::GetNavDestinationCustomNode()
183 {
184 return customNode_.Upgrade();
185 }
186
SetNavDestinationMode(NavDestinationMode mode)187 void NavDestinationGroupNode::SetNavDestinationMode(NavDestinationMode mode)
188 {
189 mode_ = mode;
190 auto pattern = GetPattern<NavDestinationPattern>();
191 CHECK_NULL_VOID(pattern);
192 auto context = pattern->GetNavDestinationContext();
193 CHECK_NULL_VOID(context);
194 context->SetMode(mode);
195 }
196
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const197 void NavDestinationGroupNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
198 {
199 FrameNode::ToJsonValue(json, filter);
200 /* no fixed attr below, just return */
201 if (filter.IsFastFilter()) {
202 return;
203 }
204 auto titleBarNode = DynamicCast<TitleBarNode>(titleBarNode_);
205 if (titleBarNode) {
206 std::string title = NavigationTitleUtil::GetTitleString(titleBarNode, GetPrevTitleIsCustomValue(false));
207 std::string subtitle = NavigationTitleUtil::GetSubtitleString(titleBarNode);
208 json->PutExtAttr("title", title.c_str(), filter);
209 json->PutExtAttr("subtitle", subtitle.c_str(), filter);
210 }
211 json->PutExtAttr("mode", mode_ == NavDestinationMode::DIALOG
212 ? "NavDestinationMode::DIALOG"
213 : "NavDestinationMode::STANDARD", filter);
214 }
215
InitSystemTransitionPush(bool transitionIn)216 void NavDestinationGroupNode::InitSystemTransitionPush(bool transitionIn)
217 {
218 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
219 float isRTL = GetLanguageDirection();
220 bool needContentAnimation = IsNeedContentTransition();
221 bool needTitleAnimation = IsNeedTitleTransition();
222 if (transitionIn) {
223 SetIsOnAnimation(true);
224 SetTransitionType(PageTransitionType::ENTER_PUSH);
225 auto frameSize = GetGeometryNode()->GetFrameSize();
226 if (needContentAnimation) {
227 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
228 GetRenderContext()->ClipWithRRect(
229 RectF(0.0f, 0.0f, frameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
230 } else {
231 GetRenderContext()->ClipWithRRect(
232 RectF(frameSize.Width() * HALF, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
233 RadiusF(EdgeF(0.0f, 0.0f)));
234 }
235 GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
236 }
237 if (titleBarNode && needTitleAnimation) {
238 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
239 }
240 return;
241 }
242 SetTransitionType(PageTransitionType::EXIT_PUSH);
243 SetIsOnAnimation(true);
244 GetRenderContext()->RemoveClipWithRRect();
245 if (needContentAnimation) {
246 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
247 }
248 if (NeedRemoveInPush()) {
249 GetEventHub<EventHub>()->SetEnabledInternal(false);
250 }
251 if (titleBarNode && needTitleAnimation) {
252 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
253 }
254 }
255
StartSystemTransitionPush(bool transitionIn)256 void NavDestinationGroupNode::StartSystemTransitionPush(bool transitionIn)
257 {
258 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
259 auto frameSize = GetGeometryNode()->GetFrameSize();
260 float isRTL = GetLanguageDirection();
261 bool needContentAnimation = IsNeedContentTransition();
262 bool needTitleAnimation = IsNeedTitleTransition();
263 if (transitionIn) {
264 if (needContentAnimation) {
265 GetRenderContext()->ClipWithRRect(
266 RectF(0.0f, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
267 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
268 }
269 if (titleBarNode && needTitleAnimation) {
270 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
271 }
272 return;
273 }
274 if (needContentAnimation) {
275 GetRenderContext()->UpdateTranslateInXY(
276 { -frameSize.Width() * CONTENT_OFFSET_PERCENT * isRTL, 0.0f });
277 }
278 if (titleBarNode && needTitleAnimation) {
279 titleBarNode->GetRenderContext()->UpdateTranslateInXY(
280 { frameSize.Width() * TITLE_OFFSET_PERCENT * isRTL, 0.0f });
281 }
282 }
283
SystemTransitionPushCallback(bool transitionIn,const int32_t animationId)284 void NavDestinationGroupNode::SystemTransitionPushCallback(bool transitionIn, const int32_t animationId)
285 {
286 if (animationId != animationId_) {
287 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "push animation invalid,curId: %{public}d, targetId: %{public}d",
288 animationId_, animationId);
289 return;
290 }
291 SetIsOnAnimation(false);
292 if (transitionIn) {
293 if (GetTransitionType() != PageTransitionType::ENTER_PUSH) {
294 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "curNode has another transition");
295 return;
296 }
297 GetRenderContext()->RemoveClipWithRRect();
298 return;
299 }
300 if (IsNeedContentTransition()) {
301 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
302 }
303 GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
304 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
305 auto navigation = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
306 CHECK_NULL_VOID(navigation);
307 bool isInvisible = IsNodeInvisible(navigation);
308 if (GetTransitionType() == PageTransitionType::EXIT_PUSH && isInvisible) {
309 GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
310 SetJSViewActive(false);
311 }
312 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
313 if (titleBarNode && IsNeedTitleTransition()) {
314 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
315 }
316 }
317
InitSystemTransitionPop(bool isTransitionIn)318 void NavDestinationGroupNode::InitSystemTransitionPop(bool isTransitionIn)
319 {
320 auto frameSize = GetGeometryNode()->GetFrameSize();
321 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
322 float isRTL = GetLanguageDirection();
323 bool needContentAnimation = IsNeedContentTransition();
324 bool needTitleAnimation = IsNeedTitleTransition();
325 if (isTransitionIn) {
326 SetTransitionType(PageTransitionType::ENTER_POP);
327 GetRenderContext()->RemoveClipWithRRect();
328 if (needContentAnimation) {
329 GetRenderContext()->UpdateTranslateInXY({ -frameSize.Width() * CONTENT_OFFSET_PERCENT * isRTL, 0.0f });
330 }
331 if (titleBarNode && needTitleAnimation) {
332 titleBarNode->GetRenderContext()->UpdateTranslateInXY(
333 { frameSize.Width() * TITLE_OFFSET_PERCENT * isRTL, 0.0f });
334 }
335 return;
336 }
337 SetIsOnAnimation(true);
338 SetTransitionType(PageTransitionType::EXIT_POP);
339 GetEventHub<EventHub>()->SetEnabledInternal(false);
340 if (needContentAnimation) {
341 GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
342 RadiusF(EdgeF(0.0f, 0.0f)));
343 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
344 }
345 if (titleBarNode && needTitleAnimation) {
346 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
347 }
348 }
349
StartSystemTransitionPop(bool transitionIn)350 void NavDestinationGroupNode::StartSystemTransitionPop(bool transitionIn)
351 {
352 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
353 bool needContentAnimation = IsNeedContentTransition();
354 bool needTitleAnimation = IsNeedTitleTransition();
355 if (transitionIn) {
356 if (needContentAnimation) {
357 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
358 }
359 if (titleBarNode && needTitleAnimation) {
360 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
361 }
362 return;
363 }
364 auto frameSize = GetGeometryNode()->GetFrameSize();
365 float isRTL = GetLanguageDirection();
366 if (needContentAnimation) {
367 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
368 GetRenderContext()->ClipWithRRect(
369 RectF(0.0f, 0.0f, frameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
370 } else {
371 GetRenderContext()->ClipWithRRect(
372 RectF(frameSize.Width() * HALF, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
373 RadiusF(EdgeF(0.0f, 0.0f)));
374 }
375 GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
376 }
377 if (titleBarNode && needTitleAnimation) {
378 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
379 }
380 }
381
SystemTransitionPopCallback(const int32_t animationId)382 bool NavDestinationGroupNode::SystemTransitionPopCallback(const int32_t animationId)
383 {
384 if (animationId_ != animationId) {
385 TAG_LOGW(AceLogTag::ACE_NAVIGATION,
386 "animation id is invalid, curId: %{public}d, targetId: %{public}d",
387 animationId_, animationId);
388 return false;
389 }
390 SetIsOnAnimation(false);
391 if (GetTransitionType() != PageTransitionType::EXIT_POP) {
392 // has another transition, just return
393 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "preNavDesNode has another transition");
394 return false;
395 }
396 auto preNavDesPattern = GetPattern<NavDestinationPattern>();
397 CHECK_NULL_RETURN(preNavDesPattern, false);
398
399 // NavRouter will restore the preNavDesNode and needs to set the initial state after the animation ends.
400 auto shallowBuilder = preNavDesPattern->GetShallowBuilder();
401 if (shallowBuilder && !IsCacheNode()) {
402 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
403 }
404 if (!IsCacheNode() && GetContentNode()) {
405 GetContentNode()->Clean();
406 }
407 GetEventHub<EventHub>()->SetEnabledInternal(true);
408 GetRenderContext()->RemoveClipWithRRect();
409 if (IsNeedContentTransition()) {
410 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
411 }
412 auto preTitleNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
413 if (preTitleNode && IsNeedTitleTransition()) {
414 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
415 preTitleNode->GetRenderContext()->SetOpacity(1.0);
416 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(preTitleNode);
417 CHECK_NULL_RETURN(titleBarNode, true);
418 auto preBackIcon = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
419 if (preBackIcon) {
420 preBackIcon->GetRenderContext()->SetOpacity(1.0);
421 }
422 }
423 return true;
424 }
425
InitDialogTransition(bool isZeroY)426 void NavDestinationGroupNode::InitDialogTransition(bool isZeroY)
427 {
428 if (systemTransitionType_ == NavigationSystemTransitionType::NONE
429 || systemTransitionType_ == NavigationSystemTransitionType::TITLE) {
430 return;
431 }
432 auto contentNode = AceType::DynamicCast<FrameNode>(GetContentNode());
433 CHECK_NULL_VOID(contentNode);
434 auto context = contentNode->GetRenderContext();
435 CHECK_NULL_VOID(context);
436 if (isZeroY) {
437 context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
438 return;
439 }
440 context->UpdateTransformTranslate({ 0.0f,
441 contentNode->GetGeometryNode()->GetFrameSize().Height(), 0.0f });
442 }
443
UpdateTextNodeListAsRenderGroup(bool isPopPage,const RefPtr<NavigationTransitionProxy> & proxy)444 void NavDestinationGroupNode::UpdateTextNodeListAsRenderGroup(
445 bool isPopPage, const RefPtr<NavigationTransitionProxy>& proxy)
446 {
447 if (isPopPage) {
448 CollectTextNodeAsRenderGroup(isPopPage);
449 } else {
450 CHECK_NULL_VOID(proxy);
451 auto pipeline = PipelineContext::GetCurrentContext();
452 CHECK_NULL_VOID(pipeline);
453 pipeline->AddAfterLayoutTask([weakNavDestiniation = WeakClaim(this),
454 weakProxy = WeakPtr<NavigationTransitionProxy>(proxy)] () {
455 auto navDestination = weakNavDestiniation.Upgrade();
456 CHECK_NULL_VOID(navDestination);
457 auto proxy = weakProxy.Upgrade();
458 if (proxy && proxy->GetIsFinished()) {
459 return;
460 }
461 navDestination->CollectTextNodeAsRenderGroup(false);
462 });
463 pipeline->RequestFrame();
464 }
465 }
466
CollectTextNodeAsRenderGroup(bool isPopPage)467 void NavDestinationGroupNode::CollectTextNodeAsRenderGroup(bool isPopPage)
468 {
469 ReleaseTextNodeList();
470 std::queue<RefPtr<UINode>> childrenLoopQueue;
471 childrenLoopQueue.push(contentNode_);
472
473 // only the first 50 text nodes will be marked, avoid too much time for traversal
474 // and off-screen drawing at first few frames
475 int32_t remainTextNodeNeedRenderGroup = MAX_RENDER_GROUP_TEXT_NODE_COUNT;
476 while (!childrenLoopQueue.empty() && remainTextNodeNeedRenderGroup > 0) {
477 auto currentNode = childrenLoopQueue.front();
478 childrenLoopQueue.pop();
479 CHECK_NULL_CONTINUE(currentNode);
480 for (auto& child : currentNode->GetChildren()) {
481 if (remainTextNodeNeedRenderGroup <= 0) {
482 break;
483 }
484 CHECK_NULL_CONTINUE(child);
485 childrenLoopQueue.push(child);
486 auto frameNode = AceType::DynamicCast<FrameNode>(child);
487 if (!frameNode || (frameNode->GetTag() != V2::TEXT_ETS_TAG)) {
488 continue;
489 }
490 auto layoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
491 if (!layoutProperty ||
492 (layoutProperty->GetTextOverflowValue(TextOverflow::CLIP) == TextOverflow::MARQUEE)) {
493 continue;
494 }
495 auto& renderContext = frameNode->GetRenderContext();
496 if (!renderContext || renderContext->GetRenderGroupValue(false)) {
497 continue;
498 }
499 renderContext->SetMarkNodeGroup(isPopPage ||
500 (renderContext->GetPaintRectWithoutTransform().Height() < MAX_RENDER_GROUP_TEXT_NODE_HEIGHT));
501 textNodeList_.emplace_back(WeakPtr<UINode>(child));
502 --remainTextNodeNeedRenderGroup;
503 auto pattern = AceType::DynamicCast<TextPattern>(frameNode->GetPattern());
504 CHECK_NULL_CONTINUE(pattern);
505 pattern->RegisterAfterLayoutCallback([weakRenderContext = WeakPtr<RenderContext>(renderContext)]() {
506 auto renderContext = weakRenderContext.Upgrade();
507 if (renderContext && !(renderContext->GetRenderGroupValue(false))) {
508 renderContext->SetMarkNodeGroup(
509 renderContext->GetPaintRectWithoutTransform().Height() < MAX_RENDER_GROUP_TEXT_NODE_HEIGHT);
510 }
511 });
512 }
513 }
514 }
515
ReleaseTextNodeList()516 void NavDestinationGroupNode::ReleaseTextNodeList()
517 {
518 for (auto& child : textNodeList_) {
519 auto textNode = AceType::DynamicCast<FrameNode>(child.Upgrade());
520 if (!textNode) {
521 continue;
522 }
523 auto pattern = AceType::DynamicCast<TextPattern>(textNode->GetPattern());
524 if (pattern) {
525 pattern->UnRegisterAfterLayoutCallback();
526 }
527 auto renderContext = textNode->GetRenderContext();
528 if (renderContext) {
529 renderContext->SetMarkNodeGroup(renderContext->GetRenderGroupValue(false));
530 }
531 }
532 textNodeList_.clear();
533 }
534
CleanContent()535 void NavDestinationGroupNode::CleanContent()
536 {
537 // cacheNode is cached for pip info, and is no need to clean when clean content node
538 if (IsCacheNode()) {
539 return;
540 }
541 auto pattern = GetPattern<NavDestinationPattern>();
542 CHECK_NULL_VOID(pattern);
543 auto shallowBuilder = pattern->GetShallowBuilder();
544 if (shallowBuilder) {
545 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
546 }
547 if (GetContentNode()) {
548 GetContentNode()->Clean(false, true);
549 }
550 }
551
IsNodeInvisible(const RefPtr<FrameNode> & node)552 bool NavDestinationGroupNode::IsNodeInvisible(const RefPtr<FrameNode>& node)
553 {
554 auto navigaiton = DynamicCast<NavigationGroupNode>(node);
555 CHECK_NULL_RETURN(navigaiton, false);
556 int32_t lastStandardIndex = navigaiton->GetLastStandardIndex();
557 bool isInvisible = index_ < lastStandardIndex;
558 return isInvisible;
559 }
560
TitleOpacityAnimation(bool isTransitionIn)561 std::shared_ptr<AnimationUtils::Animation> NavDestinationGroupNode::TitleOpacityAnimation(bool isTransitionIn)
562 {
563 if (!IsNeedTitleTransition()) {
564 return nullptr;
565 }
566 CHECK_NULL_RETURN(GetTitleBarNode(), nullptr);
567 auto titleNode = AceType::DynamicCast<TitleBarNode>(GetTitleBarNode());
568 CHECK_NULL_RETURN(titleNode, nullptr);
569 auto titleRenderContext = titleNode->GetRenderContext();
570 CHECK_NULL_RETURN(titleRenderContext, nullptr);
571 AnimationOption opacityOption;
572 opacityOption.SetCurve(Curves::SHARP);
573 opacityOption.SetDuration(OPACITY_TITLE_DURATION);
574 if (isTransitionIn) {
575 opacityOption.SetDelay(OPACITY_TITLE_IN_DELAY);
576 titleRenderContext->SetOpacity(0.0f);
577 return AnimationUtils::StartAnimation(opacityOption,
578 [weakRender = WeakPtr<RenderContext>(titleRenderContext)]() {
579 auto renderContext = weakRender.Upgrade();
580 CHECK_NULL_VOID(renderContext);
581 renderContext->SetOpacity(1.0f);
582 });
583 }
584 // recover after transition animation.
585 opacityOption.SetDelay(OPACITY_TITLE_OUT_DELAY);
586 titleRenderContext->SetOpacity(1.0f);
587 return AnimationUtils::StartAnimation(opacityOption,
588 [weakRender = WeakPtr<RenderContext>(titleRenderContext)]() {
589 auto renderContext = weakRender.Upgrade();
590 CHECK_NULL_VOID(renderContext);
591 renderContext->SetOpacity(0.0f);
592 });
593 }
594
BackButtonAnimation(bool isTransitionIn)595 std::shared_ptr<AnimationUtils::Animation> NavDestinationGroupNode::BackButtonAnimation(bool isTransitionIn)
596 {
597 if (!IsNeedTitleTransition()) {
598 return nullptr;
599 }
600 auto titleNode = AceType::DynamicCast<TitleBarNode>(GetTitleBarNode());
601 CHECK_NULL_RETURN(titleNode, nullptr);
602 auto backButtonNode = AceType::DynamicCast<FrameNode>(titleNode->GetBackButton());
603 CHECK_NULL_RETURN(backButtonNode, nullptr);
604 AnimationOption transitionOption;
605 transitionOption.SetCurve(Curves::SHARP);
606 auto backButtonNodeContext = backButtonNode->GetRenderContext();
607 CHECK_NULL_RETURN(backButtonNodeContext, nullptr);
608 if (isTransitionIn) {
609 transitionOption.SetDelay(OPACITY_BACKBUTTON_IN_DELAY);
610 transitionOption.SetDuration(OPACITY_BACKBUTTON_IN_DURATION);
611 backButtonNodeContext->SetOpacity(0.0f);
612 return AnimationUtils::StartAnimation(transitionOption,
613 [weakRender = WeakPtr<RenderContext>(backButtonNodeContext)]() {
614 auto renderContext = weakRender.Upgrade();
615 CHECK_NULL_VOID(renderContext);
616 renderContext->SetOpacity(1.0f);
617 });
618 }
619 transitionOption.SetDuration(OPACITY_BACKBUTTON_OUT_DURATION);
620 backButtonNodeContext->SetOpacity(1.0f);
621 return AnimationUtils::StartAnimation(transitionOption,
622 [weakRender = WeakPtr<RenderContext>(backButtonNodeContext)]() {
623 auto renderContext = weakRender.Upgrade();
624 CHECK_NULL_VOID(renderContext);
625 renderContext->SetOpacity(0.0f);
626 });
627 }
628
629
DoTransition(NavigationOperation operation,bool isEnter)630 int32_t NavDestinationGroupNode::DoTransition(NavigationOperation operation, bool isEnter)
631 {
632 if (navDestinationTransitionDelegate_) {
633 return DoCustomTransition(operation, isEnter);
634 }
635 return DoSystemTransition(operation, isEnter);
636 }
637
DoSystemTransition(NavigationOperation operation,bool isEnter)638 int32_t NavDestinationGroupNode::DoSystemTransition(NavigationOperation operation, bool isEnter)
639 {
640 auto noneSystemTransition = NavigationSystemTransitionType::NONE;
641 if ((systemTransitionType_ & NavigationSystemTransitionType::FADE) != noneSystemTransition) {
642 return DoSystemFadeTransition(isEnter);
643 }
644 if ((systemTransitionType_ & NavigationSystemTransitionType::SLIDE_RIGHT) != noneSystemTransition ||
645 (systemTransitionType_ & NavigationSystemTransitionType::SLIDE_BOTTOM) != noneSystemTransition) {
646 return DoSystemSlideTransition(operation, isEnter);
647 }
648 if ((systemTransitionType_ & NavigationSystemTransitionType::EXPLODE) != noneSystemTransition) {
649 return isEnter ? DoSystemEnterExplodeTransition(operation) : DoSystemExitExplodeTransition(operation);
650 }
651 return INVALID_ANIMATION_ID;
652 }
653
DoSystemFadeTransition(bool isEnter)654 int32_t NavDestinationGroupNode::DoSystemFadeTransition(bool isEnter)
655 {
656 auto renderContext = GetRenderContext();
657 CHECK_NULL_RETURN(renderContext, INVALID_ANIMATION_ID);
658 auto eventHub = GetEventHub<EventHub>();
659 if (!canReused_ && eventHub) {
660 eventHub->SetEnabledInternal(false);
661 }
662 animationId_ = MakeUniqueAnimationId();
663 SetIsOnAnimation(true);
664 auto option = BuildAnimationOption(Curves::SHARP, BuildTransitionFinishCallback(),
665 isEnter ? SYSTEM_ENTER_FADE_TRANSITION_DURATION : SYSTEM_EXIT_FADE_TRANSITION_DURATION,
666 isEnter ? SYSTEM_ENTER_FADE_TRANSITION_DELAY : SYSTEM_EXIT_FADE_TRANSITION_DELAY);
667 renderContext->OpacityAnimation(option, isEnter ? 0.0f : 1.0f, isEnter ? 1.0f : 0.0f);
668 return animationId_;
669 }
670
DoSystemSlideTransition(NavigationOperation operation,bool isEnter)671 int32_t NavDestinationGroupNode::DoSystemSlideTransition(NavigationOperation operation, bool isEnter)
672 {
673 auto eventHub = GetEventHub<EventHub>();
674 if (!canReused_ && eventHub) {
675 eventHub->SetEnabledInternal(false);
676 }
677 animationId_ = MakeUniqueAnimationId();
678 SetIsOnAnimation(true);
679 if ((operation == NavigationOperation::POP) ^ isEnter) {
680 // translate animation
681 bool isRight = (systemTransitionType_ & NavigationSystemTransitionType::SLIDE_RIGHT)
682 != NavigationSystemTransitionType::NONE;
683 std::function<void()> translateEvent = [weak = WeakClaim(this), isEnter, isRight, operation]() {
684 auto navDestination = weak.Upgrade();
685 CHECK_NULL_VOID(navDestination);
686 auto renderContext = navDestination->GetRenderContext();
687 CHECK_NULL_VOID(renderContext);
688 if (!isEnter) {
689 auto frameSize = navDestination->GetGeometryNode()->GetFrameSize();
690 renderContext->UpdateTranslateInXY(
691 { isRight ? frameSize.Width() : 0.0f, isRight ? 0.0f : frameSize.Height() });
692 } else {
693 renderContext->UpdateTranslateInXY({ 0.0f, 0.0f });
694 }
695 };
696 RefPtr<Curve> curve = isRight ? MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f)
697 : MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 328.0f, 36.0f);
698 auto option = BuildAnimationOption(curve, BuildTransitionFinishCallback());
699 if (!isEnter) {
700 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
701 } else {
702 auto frameSize = GetGeometryNode()->GetFrameSize();
703 GetRenderContext()->UpdateTranslateInXY(
704 { isRight ? frameSize.Width() : 0.0f, isRight ? 0.0f : frameSize.Height() });
705 }
706 AnimationUtils::Animate(option, translateEvent, option.GetOnFinishEvent());
707 } else {
708 // mask animation
709 auto option = BuildAnimationOption(
710 Curves::FRICTION, BuildTransitionFinishCallback(), SYSTEM_SLIDE_TRANSITION_MASK_DURATION);
711 auto beginColor = isEnter ? SLIDE_ANIMATION_MASK_COLOR : Color::TRANSPARENT;
712 auto endColor = !isEnter ? SLIDE_ANIMATION_MASK_COLOR : Color::TRANSPARENT;
713 DoMaskAnimation(option, beginColor, endColor);
714 }
715 return animationId_;
716 }
717
718
DoSystemEnterExplodeTransition(NavigationOperation operation)719 int32_t NavDestinationGroupNode::DoSystemEnterExplodeTransition(NavigationOperation operation)
720 {
721 auto renderContext = GetRenderContext();
722 CHECK_NULL_RETURN(renderContext, INVALID_ANIMATION_ID);
723 auto eventHub = GetEventHub<EventHub>();
724 if (!canReused_ && eventHub) {
725 eventHub->SetEnabledInternal(false);
726 }
727 animationId_ = MakeUniqueAnimationId();
728 SetIsOnAnimation(true);
729 if (operation == NavigationOperation::POP) {
730 // mask animation
731 DoMaskAnimation(BuildAnimationOption(Curves::FRICTION, nullptr, SYSTEM_EXPLODE_TRANSITION_MASK_DURATION),
732 SLIDE_ANIMATION_MASK_COLOR, Color::TRANSPARENT);
733 // opacity animation
734 auto option = BuildAnimationOption(Curves::SHARP, BuildTransitionFinishCallback(),
735 SYSTEM_ENTER_POP_EXPLODE_OPACITY_DURATION, SYSTEM_ENTER_POP_EXPLODE_OPACITY_DELAY);
736 renderContext->OpacityAnimation(option, 0.0f, 1.0f);
737 return animationId_;
738 }
739 // opacity animation
740 auto option = BuildAnimationOption(Curves::SHARP, BuildTransitionFinishCallback(),
741 SYSTEM_ENTER_PUSH_EXPLODE_OPACITY_DURATION, SYSTEM_ENTER_PUSH_EXPLODE_OPACITY_DELAY);
742 renderContext->OpacityAnimation(option, 0.0f, 1.0f);
743 // scale animation for enter-push
744 auto scaleCurve = MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 328.0f, 36.0f);
745 renderContext->ScaleAnimation(
746 BuildAnimationOption(scaleCurve, BuildTransitionFinishCallback()), 0.75f, 1.0f);
747 return animationId_;
748 }
749
DoSystemExitExplodeTransition(NavigationOperation operation)750 int32_t NavDestinationGroupNode::DoSystemExitExplodeTransition(NavigationOperation operation)
751 {
752 auto renderContext = GetRenderContext();
753 CHECK_NULL_RETURN(renderContext, INVALID_ANIMATION_ID);
754 auto eventHub = GetEventHub<EventHub>();
755 if (!canReused_ && eventHub) {
756 eventHub->SetEnabledInternal(false);
757 }
758 animationId_ = MakeUniqueAnimationId();
759 SetIsOnAnimation(true);
760 if (operation == NavigationOperation::POP) {
761 // opacity animation
762 renderContext->OpacityAnimation(
763 BuildAnimationOption(Curves::SHARP, nullptr, SYSTEM_EXIT_POP_EXPLODE_OPACITY_DURATION), 1.0f, 0.0f);
764 // scale animation
765 auto scaleCurve = MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 328.0f, 36.0f);
766 auto option = BuildAnimationOption(scaleCurve, BuildTransitionFinishCallback());
767 renderContext->ScaleAnimation(option, 1.0f, 0.8f);
768 return animationId_;
769 }
770 // opacity animation
771 renderContext->OpacityAnimation(
772 BuildAnimationOption(Curves::SHARP, nullptr, SYSTEM_EXIT_PUSH_EXPLODE_OPACITY_DELAY), 1.0f, 0.0f);
773 // mask animation
774 auto maskOption = BuildAnimationOption(
775 Curves::FRICTION, BuildTransitionFinishCallback(), SYSTEM_EXPLODE_TRANSITION_MASK_DURATION);
776 DoMaskAnimation(maskOption, Color::TRANSPARENT, SLIDE_ANIMATION_MASK_COLOR);
777 return animationId_;
778 }
779
DoMaskAnimation(const AnimationOption & option,Color begin,Color end)780 void NavDestinationGroupNode::DoMaskAnimation(const AnimationOption& option, Color begin, Color end)
781 {
782 auto renderContext = GetRenderContext();
783 CHECK_NULL_VOID(renderContext);
784 std::function<void()> maskEvent = [weak = WeakClaim(this), end]() {
785 auto navDestination = weak.Upgrade();
786 CHECK_NULL_VOID(navDestination);
787 auto renderContext = navDestination->GetRenderContext();
788 CHECK_NULL_VOID(renderContext);
789 renderContext->SetActualForegroundColor(end);
790 };
791
792 // initial property
793 renderContext->SetActualForegroundColor(begin);
794 AnimationUtils::Animate(option, maskEvent, option.GetOnFinishEvent());
795 }
796
DoCustomTransition(NavigationOperation operation,bool isEnter)797 int32_t NavDestinationGroupNode::DoCustomTransition(NavigationOperation operation, bool isEnter)
798 {
799 auto delegate = navDestinationTransitionDelegate_;
800 if (!delegate) {
801 return INVALID_ANIMATION_ID;
802 }
803 auto eventHub = GetEventHub<EventHub>();
804 if (!canReused_ && eventHub) {
805 eventHub->SetEnabledInternal(false);
806 }
807 auto allTransitions = delegate(operation, isEnter);
808 if (!allTransitions.has_value()) {
809 return INVALID_ANIMATION_ID;
810 }
811 int32_t longestAnimationDuration = INT32_MIN;
812 for (auto transition: allTransitions.value()) {
813 if (transition.duration + transition.delay > longestAnimationDuration) {
814 longestAnimationDuration = transition.duration + transition.delay;
815 }
816 }
817 if (longestAnimationDuration == INT32_MIN) {
818 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "navDestination custom transition array is empty!");
819 }
820 auto pipeline = GetContext();
821 CHECK_NULL_RETURN(pipeline, INVALID_ANIMATION_ID);
822 pipeline->FlushBuild();
823 pipeline->FlushUITasks();
824 animationId_ = MakeUniqueAnimationId();
825 bool hasRest = false;
826 for (auto transition: allTransitions.value()) {
827 StartCustomTransitionAnimation(transition, isEnter, hasRest, longestAnimationDuration);
828 }
829 return animationId_;
830 }
831
StartCustomTransitionAnimation(NavDestinationTransition & transition,bool isEnter,bool & hasResetProperties,int32_t longestAnimationDuration)832 void NavDestinationGroupNode::StartCustomTransitionAnimation(NavDestinationTransition& transition,
833 bool isEnter, bool& hasResetProperties, int32_t longestAnimationDuration)
834 {
835 AnimationOption option;
836 option.SetDuration(transition.duration);
837 option.SetCurve(transition.curve);
838 option.SetDelay(transition.delay);
839
840 std::function<void()> event =
841 [transitionEvent = std::move(transition.event), weak = WeakClaim(this), isEnter, &hasResetProperties]() {
842 // do necessary system-side tasks
843 auto navDestination = weak.Upgrade();
844 CHECK_NULL_VOID(navDestination);
845 navDestination->SetIsOnAnimation(true);
846 if (!hasResetProperties && isEnter) {
847 auto pattern = navDestination->GetPattern<NavDestinationPattern>();
848 CHECK_NULL_VOID(pattern);
849 auto navigation = AceType::DynamicCast<NavigationGroupNode>(pattern->GetNavigationNode());
850 if (navigation) {
851 /*
852 * Reset the system animation properties in custom transition
853 * animation closure to prevent animation mutation.
854 */
855 navigation->ResetSystemAnimationProperties(navDestination);
856 }
857 hasResetProperties = true;
858 }
859 // do user-set task
860 transitionEvent();
861 auto pipeline = navDestination->GetContext();
862 CHECK_NULL_VOID(pipeline);
863 pipeline->FlushBuild();
864 pipeline->FlushUITasks();
865 };
866 // only do remove or set visibility in longest custom transition animation's finish callback.
867 std::function<void()> finish = transition.duration + transition.delay == longestAnimationDuration ?
868 BuildTransitionFinishCallback(false, std::move(transition.onTransitionEnd)) :
869 std::move(transition.onTransitionEnd);
870 AnimationUtils::Animate(option, event, finish);
871 auto pattern = GetPattern<NavDestinationPattern>();
872 CHECK_NULL_VOID(pattern);
873 TAG_LOGI(AceLogTag::ACE_NAVIGATION,
874 "%{public}s trigger custom transition, duration: %{public}d, delay: %{public}d, curve: %{public}s",
875 pattern->GetName().c_str(), transition.duration, transition.delay, transition.curve->ToString().c_str());
876 }
877
MakeUniqueAnimationId()878 int32_t NavDestinationGroupNode::MakeUniqueAnimationId()
879 {
880 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
881 CHECK_NULL_RETURN(navDestinationPattern, INVALID_ANIMATION_ID);
882 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
883 CHECK_NULL_RETURN(navigationNode, INVALID_ANIMATION_ID);
884 return navigationNode->MakeUniqueAnimationId();
885 }
886
BuildTransitionFinishCallback(bool isSystemTransition,std::function<void ()> && extraOption)887 std::function<void()> NavDestinationGroupNode::BuildTransitionFinishCallback(
888 bool isSystemTransition, std::function<void()>&& extraOption)
889 {
890 std::function<void()> finish = [extraOption = std::move(extraOption), weak = WeakClaim(this),
891 animationId = animationId_, isSystemTransition]() {
892 auto navDestination = weak.Upgrade();
893 CHECK_NULL_VOID(navDestination);
894 auto destinationPattern = navDestination->GetPattern<NavDestinationPattern>();
895 CHECK_NULL_VOID(destinationPattern);
896 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "%{public}s transition finish", destinationPattern->GetName().c_str());
897 // do extraOption first
898 if (extraOption) {
899 extraOption();
900 }
901 // do necessary system-side tasks
902 if (animationId != navDestination->GetAnimationId()) {
903 return;
904 }
905 if (isSystemTransition) {
906 navDestination->ResetCustomTransitionAnimationProperties();
907 }
908 // only handle current node in latest finish callback.
909 if (!navDestination->GetCanReused()) {
910 // can't be reused means it is not in navigation stack anymore, so remove it.
911 navDestination->CleanContent();
912 auto parent = navDestination->GetParent();
913 CHECK_NULL_VOID(parent);
914 parent->RemoveChild(navDestination);
915 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
916 } else if (navDestination->HasStandardBefore()) {
917 navDestination->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
918 navDestination->SetJSViewActive(false);
919 }
920 navDestination->SetIsOnAnimation(false);
921 };
922 return finish;
923 }
924
HasStandardBefore() const925 bool NavDestinationGroupNode::HasStandardBefore() const
926 {
927 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
928 CHECK_NULL_RETURN(navDestinationPattern, false);
929 auto navigationNode =
930 AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
931 CHECK_NULL_RETURN(navigationNode, false);
932 return index_ < navigationNode->GetLastStandardIndex();
933 }
934
ResetCustomTransitionAnimationProperties()935 void NavDestinationGroupNode::ResetCustomTransitionAnimationProperties()
936 {
937 auto renderContext = GetRenderContext();
938 CHECK_NULL_VOID(renderContext);
939 renderContext->UpdateTranslateInXY({ 0.0f, 0.0f });
940 renderContext->SetOpacity(userSetOpacity_);
941 renderContext->SetActualForegroundColor(Color::TRANSPARENT);
942 }
943 } // namespace OHOS::Ace::NG
944