• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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/navdestination_pattern_base.h"
17 
18 #include "core/components_ng/pattern/navigation/navdestination_node_base.h"
19 
20 namespace OHOS::Ace::NG {
21 namespace {
22 constexpr int32_t DEFAULT_ANIMATION_DURATION = 500;
23 } // namespace
24 
UpdateLayoutPropertyBeforeAnimation(const RefPtr<NavDestinationNodeBase> & navNodeBase,bool needRunTitleBarAnimation,bool needRunToolBarAnimation,bool hideTitleBar,bool hideToolBar)25 void NavDestinationPatternBase::UpdateLayoutPropertyBeforeAnimation(const RefPtr<NavDestinationNodeBase>& navNodeBase,
26     bool needRunTitleBarAnimation, bool needRunToolBarAnimation, bool hideTitleBar, bool hideToolBar)
27 {
28     CHECK_NULL_VOID(navNodeBase);
29     auto property = navNodeBase->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
30     CHECK_NULL_VOID(property);
31     if (needRunTitleBarAnimation && titleBarAnimationCount_ == 0) {
32         property->UpdateTitleBarTranslateState(hideTitleBar ?
33             BarTranslateState::TRANSLATE_ZERO : BarTranslateState::TRANSLATE_HEIGHT);
34         if (!hideTitleBar) {
35             UpdateTitleBarProperty(property, false, navNodeBase);
36         }
37     }
38     if (needRunToolBarAnimation && toolBarAnimationCount_ == 0) {
39         property->UpdateToolBarTranslateState(hideToolBar ?
40             BarTranslateState::TRANSLATE_ZERO : BarTranslateState::TRANSLATE_HEIGHT);
41         if (!hideToolBar) {
42             UpdateToolBarAndDividerProperty(property, false, navNodeBase);
43         }
44     }
45 }
46 
HandleTitleBarAndToolBarAnimation(const RefPtr<NavDestinationNodeBase> & navNodeBase,bool needRunTitleBarAnimation,bool needRunToolBarAnimation)47 void NavDestinationPatternBase::HandleTitleBarAndToolBarAnimation(const RefPtr<NavDestinationNodeBase>& navNodeBase,
48     bool needRunTitleBarAnimation, bool needRunToolBarAnimation)
49 {
50     if (!(needRunToolBarAnimation || needRunTitleBarAnimation)) {
51         return;
52     }
53 
54     CHECK_NULL_VOID(navNodeBase);
55     auto pipeline = navNodeBase->GetContext();
56     CHECK_NULL_VOID(pipeline);
57     auto property = navNodeBase->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
58     CHECK_NULL_VOID(property);
59     bool hideTitleBar = property->GetHideTitleBarValue(false);
60     bool hideToolBar = property->GetHideToolBarValue(false);
61     UpdateLayoutPropertyBeforeAnimation(navNodeBase, needRunTitleBarAnimation,
62         needRunToolBarAnimation, hideTitleBar, hideToolBar);
63 
64     auto task = [weakPattern = WeakClaim(this), needRunTitleBarAnimation, needRunToolBarAnimation,
65         hideTitleBar, hideToolBar]() mutable {
66         auto pattern = weakPattern.Upgrade();
67         CHECK_NULL_VOID(pattern);
68         auto node = AceType::DynamicCast<NavDestinationNodeBase>(pattern->GetHost());
69         CHECK_NULL_VOID(node);
70         auto property = node->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
71         CHECK_NULL_VOID(property);
72         if (pattern->IsNeedHideToolBarForNavWidth()) {
73             property->ResetToolBarTranslateState();
74             needRunToolBarAnimation = false;
75         }
76         if (!(needRunToolBarAnimation || needRunTitleBarAnimation)) {
77             return;
78         }
79 
80         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(node->GetTitleBarNode());
81         if (needRunTitleBarAnimation && !hideTitleBar && titleBarNode && pattern->GetTitleBarAnimationCount() == 0) {
82             pattern->UpdateTitleBarTranslateAndOpacity(true, titleBarNode, pattern->GetTitleBarHeight());
83         }
84         auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(node->GetToolBarNode());
85         auto toolBarDividerNode = AceType::DynamicCast<FrameNode>(node->GetToolBarDividerNode());
86         if (needRunToolBarAnimation && !hideToolBar && toolBarNode && pattern->GetToolBarAnimationCount() == 0) {
87             pattern->UpdateToolBarAndDividerTranslateAndOpacity(true, toolBarNode,
88                 pattern->GetToolBarHeight(), toolBarDividerNode, pattern->GetToolBarDividerHeight());
89         }
90 
91         pattern->StartAnimation(needRunTitleBarAnimation, hideTitleBar, needRunToolBarAnimation, hideToolBar);
92     };
93     pipeline->AddAfterLayoutTask(std::move(task));
94 }
95 
UpdateTitleBarProperty(const RefPtr<LayoutProperty> & navBarLayoutProperty,bool hide,const RefPtr<NavDestinationNodeBase> & hostNode)96 void NavDestinationPatternBase::UpdateTitleBarProperty(const RefPtr<LayoutProperty>& navBarLayoutProperty, bool hide,
97     const RefPtr<NavDestinationNodeBase>& hostNode)
98 {
99     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
100     CHECK_NULL_VOID(titleBarNode);
101     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty();
102     CHECK_NULL_VOID(titleBarLayoutProperty);
103     if (hide) {
104         titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
105         titleBarNode->SetJSViewActive(false);
106     } else {
107         titleBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
108         titleBarNode->SetJSViewActive(true);
109         auto&& opts = navBarLayoutProperty->GetSafeAreaExpandOpts();
110         if (opts) {
111             titleBarLayoutProperty->UpdateSafeAreaExpandOpts(*opts);
112         }
113     }
114 }
115 
UpdateTitleBarTranslateAndOpacity(bool hide,const RefPtr<TitleBarNode> & titleBarNode,float titleBarHeight)116 void NavDestinationPatternBase::UpdateTitleBarTranslateAndOpacity(
117     bool hide, const RefPtr<TitleBarNode>& titleBarNode, float titleBarHeight)
118 {
119     if (titleBarNode) {
120         auto renderContext = titleBarNode->GetRenderContext();
121         if (renderContext) {
122             auto offset = renderContext->GetTranslateXYProperty();
123             offset.SetY(hide ? -titleBarHeight : 0.0f);
124             renderContext->UpdateTranslateInXY(offset);
125             renderContext->UpdateOpacity(hide ? 0.0f : 1.0f);
126         }
127     }
128 }
129 
UpdateToolBarAndDividerProperty(const RefPtr<LayoutProperty> & navBarLayoutProperty,bool hide,const RefPtr<NavDestinationNodeBase> & hostNode)130 void NavDestinationPatternBase::UpdateToolBarAndDividerProperty(const RefPtr<LayoutProperty>& navBarLayoutProperty,
131     bool hide, const RefPtr<NavDestinationNodeBase>& hostNode)
132 {
133     auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(hostNode->GetToolBarNode());
134     CHECK_NULL_VOID(toolBarNode);
135     auto toolBarLayoutProperty = toolBarNode->GetLayoutProperty();
136     CHECK_NULL_VOID(toolBarLayoutProperty);
137     auto toolBarDividerNode = AceType::DynamicCast<FrameNode>(hostNode->GetToolBarDividerNode());
138     RefPtr<LayoutProperty> toolBarDividerLayoutProperty = nullptr;
139     if (toolBarDividerNode) {
140         toolBarDividerLayoutProperty = toolBarDividerNode->GetLayoutProperty();
141     }
142     if (hide || !toolBarNode->HasValidContent()) {
143         toolBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
144         toolBarNode->SetActive(false);
145         if (toolBarDividerLayoutProperty) {
146             toolBarDividerLayoutProperty->UpdateVisibility(VisibleType::GONE);
147         }
148     } else {
149         toolBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
150         toolBarNode->SetActive(true);
151         if (toolBarDividerLayoutProperty) {
152             toolBarDividerLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
153         }
154 
155         auto&& opts = navBarLayoutProperty->GetSafeAreaExpandOpts();
156         if (opts) {
157             toolBarLayoutProperty->UpdateSafeAreaExpandOpts(*opts);
158         }
159     }
160 }
161 
UpdateToolBarAndDividerTranslateAndOpacity(bool hide,const RefPtr<NavToolbarNode> & toolBarNode,float toolBarHeight,const RefPtr<FrameNode> & toolbarDividerNode,float toolBarDividerHeight)162 void NavDestinationPatternBase::UpdateToolBarAndDividerTranslateAndOpacity(bool hide,
163     const RefPtr<NavToolbarNode>& toolBarNode, float toolBarHeight, const RefPtr<FrameNode>& toolbarDividerNode,
164     float toolBarDividerHeight)
165 {
166     float opacity = hide ? 0.0f : 1.0f;
167     float offsetY = hide ? (toolBarHeight + toolBarDividerHeight) : 0;
168     if (toolBarNode) {
169         auto renderContext = toolBarNode->GetRenderContext();
170         if (renderContext) {
171             renderContext->UpdateTranslateInXY({ 0.0f, offsetY });
172             renderContext->UpdateOpacity(opacity);
173         }
174     }
175     if (toolbarDividerNode) {
176         auto dividerContext = toolbarDividerNode->GetRenderContext();
177         if (dividerContext) {
178             dividerContext->UpdateTranslateInXY({ 0.0f, offsetY });
179             dividerContext->UpdateOpacity(opacity);
180         }
181     }
182 }
183 
HideOrShowTitleBarImmediately(const RefPtr<NavDestinationNodeBase> & hostNode,bool hide)184 void NavDestinationPatternBase::HideOrShowTitleBarImmediately(const RefPtr<NavDestinationNodeBase>& hostNode, bool hide)
185 {
186     auto navBarPattern = hostNode->GetPattern<NavDestinationPatternBase>();
187     CHECK_NULL_VOID(navBarPattern);
188     auto navBarLayoutProperty = hostNode->GetLayoutProperty();
189     CHECK_NULL_VOID(navBarLayoutProperty);
190     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
191     CHECK_NULL_VOID(titleBarNode);
192     UpdateTitleBarProperty(navBarLayoutProperty, hide, hostNode);
193     UpdateTitleBarTranslateAndOpacity(hide, titleBarNode, navBarPattern->GetTitleBarHeight());
194     titleBarNode->MarkModifyDone();
195     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
196 }
197 
HideOrShowToolBarImmediately(const RefPtr<NavDestinationNodeBase> & hostNode,bool hide)198 void NavDestinationPatternBase::HideOrShowToolBarImmediately(const RefPtr<NavDestinationNodeBase>& hostNode, bool hide)
199 {
200     auto navDestinationPatternBase = hostNode->GetPattern<NavDestinationPatternBase>();
201     CHECK_NULL_VOID(navDestinationPatternBase);
202     auto navBarLayoutProperty = hostNode->GetLayoutProperty();
203     CHECK_NULL_VOID(navBarLayoutProperty);
204     auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(hostNode->GetToolBarNode());
205     CHECK_NULL_VOID(toolBarNode);
206     auto toolBarDividerNode = AceType::DynamicCast<FrameNode>(hostNode->GetToolBarDividerNode());
207     UpdateToolBarAndDividerProperty(navBarLayoutProperty, hide, hostNode);
208     UpdateToolBarAndDividerTranslateAndOpacity(hide, toolBarNode, GetToolBarHeight(),
209         toolBarDividerNode, GetToolBarDividerHeight());
210     toolBarNode->MarkModifyDone();
211     toolBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
212 }
213 
BarAnimationPropertyCallback(bool needRunTitleBarAnimation,bool hideTitle,bool needRunToolBarAnimation,bool hideTool)214 void NavDestinationPatternBase::BarAnimationPropertyCallback(
215     bool needRunTitleBarAnimation, bool hideTitle, bool needRunToolBarAnimation, bool hideTool)
216 {
217     auto node = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
218     CHECK_NULL_VOID(node);
219     auto property = node->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
220     CHECK_NULL_VOID(property);
221     auto context = node->GetContext();
222     CHECK_NULL_VOID(context);
223     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(node->GetTitleBarNode());
224     auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(node->GetToolBarNode());
225     auto toolBarDividerNode = AceType::DynamicCast<FrameNode>(node->GetToolBarDividerNode());
226     if (needRunTitleBarAnimation && titleBarNode) {
227         property->UpdateTitleBarTranslateState(hideTitle ?
228             BarTranslateState::TRANSLATE_HEIGHT : BarTranslateState::TRANSLATE_ZERO);
229     }
230     if (needRunToolBarAnimation && toolBarNode) {
231         property->UpdateToolBarTranslateState(hideTool ?
232             BarTranslateState::TRANSLATE_HEIGHT : BarTranslateState::TRANSLATE_ZERO);
233     }
234     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
235     context->FlushUITasks();
236     if (needRunTitleBarAnimation && titleBarNode) {
237         UpdateTitleBarTranslateAndOpacity(hideTitle, titleBarNode, GetTitleBarHeight());
238     }
239     if (needRunToolBarAnimation && toolBarNode) {
240         UpdateToolBarAndDividerTranslateAndOpacity(hideTool, toolBarNode, GetToolBarHeight(),
241             toolBarDividerNode, GetToolBarDividerHeight());
242     }
243 }
244 
BarAnimationFinishCallback(bool needRunTitleBarAnimation,bool needRunToolBarAnimation,int32_t animationId)245 void NavDestinationPatternBase::BarAnimationFinishCallback(
246     bool needRunTitleBarAnimation, bool needRunToolBarAnimation, int32_t animationId)
247 {
248     if (needRunTitleBarAnimation) {
249         OnTitleBarAnimationFinish();
250     }
251     if (needRunToolBarAnimation) {
252         OnToolBarAnimationFinish();
253     }
254     RemoveAnimation(animationId);
255 }
256 
StartAnimation(bool needRunTitleBarAnimation,bool hideTitle,bool needRunToolBarAnimation,bool hideTool)257 void NavDestinationPatternBase::StartAnimation(
258     bool needRunTitleBarAnimation, bool hideTitle, bool needRunToolBarAnimation, bool hideTool)
259 {
260     auto propertyCallback = [needRunTitleBarAnimation, hideTitle, needRunToolBarAnimation, hideTool,
261                                 weakPattern = AceType::WeakClaim(this)]() {
262         auto pattern = weakPattern.Upgrade();
263         CHECK_NULL_VOID(pattern);
264         pattern->BarAnimationPropertyCallback(needRunTitleBarAnimation, hideTitle, needRunToolBarAnimation, hideTool);
265     };
266     auto finishCallback = [needRunTitleBarAnimation, needRunToolBarAnimation,
267                               weakPattern = AceType::WeakClaim(this), animationId = nextBarAnimationId_]() {
268         auto pattern = weakPattern.Upgrade();
269         CHECK_NULL_VOID(pattern);
270         pattern->BarAnimationFinishCallback(needRunTitleBarAnimation, needRunToolBarAnimation, animationId);
271     };
272 
273     AnimationOption option;
274     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
275     option.SetDuration(DEFAULT_ANIMATION_DURATION);
276     if (needRunTitleBarAnimation) {
277         OnTitleBarAnimationStart();
278     }
279     if (needRunToolBarAnimation) {
280         OnToolBarAnimationStart();
281     }
282     auto animation = AnimationUtils::StartAnimation(option, propertyCallback, finishCallback);
283     barAnimations_.emplace(nextBarAnimationId_, animation);
284     nextBarAnimationId_++;
285 }
286 
OnTitleBarAnimationFinish()287 void NavDestinationPatternBase::OnTitleBarAnimationFinish()
288 {
289     titleBarAnimationCount_--;
290     if (titleBarAnimationCount_ > 0) {
291         return;
292     }
293 
294     auto node = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
295     CHECK_NULL_VOID(node);
296     auto property = node->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
297     CHECK_NULL_VOID(property);
298     property->ResetTitleBarTranslateState();
299     HideOrShowTitleBarImmediately(node, property->GetHideTitleBarValue(false));
300 }
301 
OnToolBarAnimationFinish()302 void NavDestinationPatternBase::OnToolBarAnimationFinish()
303 {
304     toolBarAnimationCount_--;
305     if (toolBarAnimationCount_ > 0) {
306         return;
307     }
308 
309     auto node = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
310     CHECK_NULL_VOID(node);
311     auto property = node->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
312     CHECK_NULL_VOID(property);
313     property->ResetToolBarTranslateState();
314     HideOrShowToolBarImmediately(node, property->GetHideToolBarValue(false));
315 }
316 
AbortBarAnimation()317 void NavDestinationPatternBase::AbortBarAnimation()
318 {
319     for (const auto& pair : barAnimations_) {
320         if (pair.second) {
321             AnimationUtils::StopAnimation(pair.second);
322         }
323     }
324     barAnimations_.clear();
325 }
326 
RemoveAnimation(int32_t id)327 void NavDestinationPatternBase::RemoveAnimation(int32_t id)
328 {
329     auto it = barAnimations_.find(id);
330     if (it != barAnimations_.end()) {
331         barAnimations_.erase(it);
332     }
333 }
334 } // namespace OHOS::Ace::NG