• 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/navigation_title_util.h"
17 
18 #include "base/i18n/localization.h"
19 #include "base/utils/utf_helper.h"
20 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
21 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
22 #include "core/common/container.h"
23 #include "core/components_ng/base/view_abstract.h"
24 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
25 #include "core/components_ng/pattern/button/button_layout_property.h"
26 #include "core/components_ng/pattern/button/button_pattern.h"
27 #include "core/components_ng/pattern/grid/grid_pattern.h"
28 #include "core/components_ng/pattern/image/image_layout_property.h"
29 #include "core/components_ng/pattern/image/image_pattern.h"
30 #include "core/components_ng/pattern/menu/menu_view.h"
31 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
32 #include "core/components_ng/pattern/navigation/bar_item_event_hub.h"
33 #include "core/components_ng/pattern/navigation/bar_item_pattern.h"
34 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
35 #include "core/components_ng/pattern/navigation/navdestination_node_base.h"
36 #include "core/components_ng/pattern/navigation/navdestination_pattern_base.h"
37 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
38 #include "core/components_ng/pattern/navigation/title_bar_node.h"
39 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
40 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
41 #include "core/components_ng/pattern/text/text_pattern.h"
42 
43 namespace OHOS::Ace::NG {
44 namespace {
45 constexpr Dimension TITLEBAR_VERTICAL_PADDING = 56.0_vp;
46 constexpr int32_t TITLEBAR_OPACITY_ANIMATION_DURATION = 120;
47 const RefPtr<CubicCurve> TITLEBAR_OPACITY_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.4, 0.0, 0.4, 1.0);
48 }
49 
BuildMoreButton(bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme,const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & menuNode,std::vector<OptionParam> && params,const std::string & field,const std::string & parentId,bool isCreateLandscapeMenu)50 bool NavigationTitleUtil::BuildMoreButton(bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme,
51     const RefPtr<NavDestinationNodeBase>& nodeBase, const RefPtr<FrameNode>& menuNode,
52     std::vector<OptionParam>&& params, const std::string& field, const std::string& parentId,
53     bool isCreateLandscapeMenu)
54 {
55     auto barItemNode = CreateBarItemNode(isButtonEnabled, theme);
56     CHECK_NULL_RETURN(barItemNode, false);
57     auto menuItemNode = CreateMenuItemButton(theme);
58     CHECK_NULL_RETURN(menuItemNode, false);
59     CHECK_NULL_RETURN(nodeBase, false);
60     auto navDestinationPattern = nodeBase->GetPattern<NavDestinationPattern>();
61     CHECK_NULL_RETURN(navDestinationPattern, false);
62     MenuParam menuParam;
63     menuParam.isShowInSubWindow = false;
64     menuParam.placement = Placement::BOTTOM_RIGHT;
65     NavigationMenuOptions menuOptions = navDestinationPattern->GetMenuOptions();
66     if (menuOptions.mbOptions.bgOptions.blurStyleOption.has_value()) {
67         menuParam.backgroundBlurStyleOption = menuOptions.mbOptions.bgOptions.blurStyleOption.value();
68     }
69     if (menuOptions.mbOptions.bgOptions.effectOption.has_value()) {
70         menuParam.backgroundEffectOption = menuOptions.mbOptions.bgOptions.effectOption.value();
71     }
72     auto barMenuNode = MenuView::Create(
73         std::move(params), menuItemNode->GetId(), menuItemNode->GetTag(), MenuType::NAVIGATION_MENU, menuParam);
74     BuildMoreItemNodeAction(menuItemNode, barItemNode, barMenuNode);
75     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
76     InitTitleBarButtonEvent(menuItemNode, iconNode, true);
77 
78     // read navdestination "more" button
79     std::string message = theme ? theme->GetMoreMessage() : "";
80     SetAccessibility(menuItemNode, message);
81 
82     // set navdestination titleBar "more" button inspectorId
83     SetInnerChildId(menuItemNode, field, menuNode->GetTag(), "More", parentId);
84 
85     barItemNode->MountToParent(menuItemNode);
86     barItemNode->MarkModifyDone();
87     menuItemNode->MarkModifyDone();
88     CHECK_NULL_RETURN(menuNode, false);
89     menuNode->AddChild(menuItemNode);
90     if (isCreateLandscapeMenu) {
91         nodeBase->SetLandscapeMenuNode(barMenuNode);
92     } else {
93         nodeBase->SetMenuNode(barMenuNode);
94     }
95     return true;
96 }
97 
CreateMenuItems(const int32_t menuNodeId,const std::vector<NG::BarItem> & menuItems,const RefPtr<NavDestinationNodeBase> & navDestinationNodeBase,bool isButtonEnabled,const std::string & field,const std::string & parentId,bool isCreateLandscapeMenu)98 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItems(const int32_t menuNodeId,
99     const std::vector<NG::BarItem>& menuItems, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase,
100     bool isButtonEnabled, const std::string& field, const std::string& parentId, bool isCreateLandscapeMenu)
101 {
102     auto menuNode = FrameNode::GetOrCreateFrameNode(
103         V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
104     CHECK_NULL_RETURN(menuNode, nullptr);
105     menuNode->Clean();
106     menuNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
107     auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
108     CHECK_NULL_RETURN(rowProperty, nullptr);
109     rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
110     auto theme = NavigationGetTheme(navDestinationNodeBase->GetThemeScopeId());
111     CHECK_NULL_RETURN(theme, nullptr);
112     auto mostMenuItemCount = GetOrInitMaxMenuNums(theme, navDestinationNodeBase);
113     bool needMoreButton = menuItems.size() > mostMenuItemCount;
114 
115     int32_t count = 0;
116     std::vector<OptionParam> params;
117     OptionParam param;
118     for (const auto& menuItem : menuItems) {
119         ++count;
120         if (needMoreButton && (count > static_cast<int32_t>(mostMenuItemCount) - 1)) {
121             param = { menuItem.text.value_or(""), menuItem.icon.value_or(""), menuItem.isEnabled.value_or(true),
122                 menuItem.action, menuItem.iconSymbol.value_or(nullptr) };
123             param.SetSymbolUserDefinedIdealFontSize(theme->GetMenuIconSize());
124             params.push_back(param);
125         } else {
126             auto menuItemNode = CreateMenuItemNode(theme, menuItem, isButtonEnabled);
127             CHECK_NULL_RETURN(menuItemNode, nullptr);
128 
129             // set titleBar menuitem inspectorId
130             std::string menuItemId = menuItemNode->GetTag() + std::to_string(count);
131             NavigationTitleUtil::SetInnerChildId(menuItemNode, field, menuNode->GetTag(), menuItemId, parentId);
132 
133             // read menu button
134             SetAccessibility(menuItemNode, menuItem.text.value_or(""));
135             menuNode->AddChild(menuItemNode);
136         }
137     }
138 
139     // build more button
140     if (needMoreButton) {
141         bool buildMoreButtonResult = BuildMoreButton(isButtonEnabled, theme, navDestinationNodeBase,
142             menuNode, std::move(params), field, parentId, isCreateLandscapeMenu);
143         if (!buildMoreButtonResult) {
144             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "build more button node failed");
145             return nullptr;
146         }
147     }
148     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNodeBase->GetTitleBarNode());
149     CHECK_NULL_RETURN(titleBarNode, nullptr);
150     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
151     CHECK_NULL_RETURN(titleBarPattern, nullptr);
152     titleBarPattern->InitMenuDragAndLongPressEvent(menuNode, menuItems);
153     return menuNode;
154 }
155 
GetOrInitMaxMenuNums(const RefPtr<NavigationBarTheme> & theme,const RefPtr<NavDestinationNodeBase> & navDestinationNodeBase)156 uint32_t NavigationTitleUtil::GetOrInitMaxMenuNums(
157     const RefPtr<NavigationBarTheme>& theme, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase)
158 {
159     auto patternBase = navDestinationNodeBase->GetPattern<NavDestinationPatternBase>();
160     CHECK_NULL_RETURN(patternBase, 0);
161     auto navDesMaxNum = patternBase->GetMaxMenuNum();
162     auto mostMenuItemCount =
163         navDesMaxNum < 0 ? theme->GetMostMenuItemCountInBar() : static_cast<uint32_t>(navDesMaxNum);
164     mostMenuItemCount = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
165                                                                                                  : mostMenuItemCount;
166     patternBase->SetMaxMenuNum(mostMenuItemCount);
167     return mostMenuItemCount;
168 }
169 
BuildMoreItemNodeAction(const RefPtr<FrameNode> & buttonNode,const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode)170 void NavigationTitleUtil::BuildMoreItemNodeAction(const RefPtr<FrameNode>& buttonNode,
171     const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& barMenuNode)
172 {
173     auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
174     CHECK_NULL_VOID(eventHub);
175 
176     auto context = PipelineContext::GetCurrentContext();
177     auto clickCallback = [weakContext = WeakPtr<PipelineContext>(context), id = barItemNode->GetId(),
178                              weakMenu = WeakPtr<FrameNode>(barMenuNode)]() {
179         auto context = weakContext.Upgrade();
180         CHECK_NULL_VOID(context);
181 
182         auto overlayManager = context->GetOverlayManager();
183         CHECK_NULL_VOID(overlayManager);
184 
185         auto menu = weakMenu.Upgrade();
186         CHECK_NULL_VOID(menu);
187         overlayManager->ShowMenu(id, OffsetF(0.0f, 0.0f), menu);
188     };
189     eventHub->SetItemAction(clickCallback);
190 
191     auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
192     CHECK_NULL_VOID(gestureEventHub);
193     auto callback = [action = clickCallback](GestureEvent& info) {
194         if (info.GetSourceDevice() == SourceType::KEYBOARD) {
195             return;
196         }
197         action();
198     };
199     gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(callback));
200 }
201 
CreateMenuItemNode(const RefPtr<NavigationBarTheme> & theme,const BarItem & menuItem,bool isButtonEnabled)202 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemNode(
203     const RefPtr<NavigationBarTheme>& theme, const BarItem& menuItem, bool isButtonEnabled)
204 {
205     auto menuItemNode = CreateMenuItemButton(theme);
206     CHECK_NULL_RETURN(menuItemNode, nullptr);
207 
208     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
209     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
210         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
211     UpdateBarItemNodeWithItem(barItemNode, menuItem, isButtonEnabled, theme);
212     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
213     InitTitleBarButtonEvent(menuItemNode, iconNode, false, menuItem, menuItem.isEnabled.value_or(true));
214     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
215     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
216     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
217 
218     barItemNode->MountToParent(menuItemNode);
219     barItemNode->MarkModifyDone();
220     menuItemNode->MarkModifyDone();
221     return menuItemNode;
222 }
223 
CreateMenuItemButton(const RefPtr<NavigationBarTheme> & theme)224 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemButton(const RefPtr<NavigationBarTheme>& theme)
225 {
226     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
227     CHECK_NULL_RETURN(buttonPattern, nullptr);
228     buttonPattern->setComponentButtonType(ComponentButtonType::NAVIGATION);
229     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
230         buttonPattern->SetBlendColor(theme->GetBackgroundPressedColor(), theme->GetBackgroundHoverColor());
231         buttonPattern->SetFocusBorderColor(theme->GetBackgroundFocusOutlineColor());
232         buttonPattern->SetFocusBorderWidth(theme->GetBackgroundFocusOutlineWeight());
233     } else {
234         buttonPattern->SetFocusBorderColor(theme->GetToolBarItemFocusColor());
235         buttonPattern->SetFocusBorderWidth(theme->GetToolBarItemFocusBorderWidth());
236     }
237     auto menuItemNode = FrameNode::CreateFrameNode(
238         V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), buttonPattern);
239     CHECK_NULL_RETURN(menuItemNode, nullptr);
240     auto focusHub = menuItemNode->GetOrCreateFocusHub();
241     CHECK_NULL_RETURN(focusHub, nullptr);
242     focusHub->SetFocusDependence(FocusDependence::SELF);
243     auto menuItemLayoutProperty = menuItemNode->GetLayoutProperty<ButtonLayoutProperty>();
244     CHECK_NULL_RETURN(menuItemLayoutProperty, nullptr);
245     menuItemLayoutProperty->UpdateType(ButtonType::NORMAL);
246     auto renderContext = menuItemNode->GetRenderContext();
247     CHECK_NULL_RETURN(renderContext, nullptr);
248     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
249         auto iconBackgroundWidth = theme->GetIconBackgroundWidth();
250         auto iconBackgroundHeight = theme->GetIconBackgroundHeight();
251         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
252             CalcSize(CalcLength(iconBackgroundWidth), CalcLength(iconBackgroundHeight)));
253         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(theme->GetCornerRadius()));
254         renderContext->UpdateBackgroundColor(theme->GetCompBackgroundColor());
255         PaddingProperty padding;
256         padding.SetEdges(CalcLength(MENU_BUTTON_PADDING));
257         menuItemLayoutProperty->UpdatePadding(padding);
258         MarginProperty margin;
259         margin.right = CalcLength(theme->GetCompPadding());
260         margin.end = CalcLength(theme->GetCompPadding());
261         menuItemLayoutProperty->UpdateMargin(margin);
262     } else {
263         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
264             CalcSize(CalcLength(BACK_BUTTON_SIZE), CalcLength(BACK_BUTTON_SIZE)));
265         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(BUTTON_RADIUS_SIZE));
266         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
267         PaddingProperty padding;
268         padding.SetEdges(CalcLength(BUTTON_PADDING));
269         menuItemLayoutProperty->UpdatePadding(padding);
270     }
271     return menuItemNode;
272 }
273 
CreateBarItemTextNode(const std::string & text)274 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemTextNode(const std::string& text)
275 {
276     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
277     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, nodeId, AceType::MakeRefPtr<TextPattern>());
278     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
279     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
280     textLayoutProperty->UpdateContent(text);
281     textLayoutProperty->UpdateFontSize(TEXT_FONT_SIZE);
282     textLayoutProperty->UpdateTextColor(TEXT_COLOR);
283     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
284     return textNode;
285 }
286 
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)287 void UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
288 {
289     CHECK_NULL_VOID(symbolProperty);
290     auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
291     symbolEffectOptions.SetIsTxtActive(isActive);
292     symbolEffectOptions.SetIsTxtActiveSource(0);
293     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
294 }
295 
CreateBarItemIconNode(const BarItem & barItem,const bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)296 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemIconNode(
297     const BarItem& barItem, const bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
298 {
299     CHECK_NULL_RETURN(theme, nullptr);
300 
301     Color iconColor = theme->GetMenuIconColor();
302     double iconOpacity = theme->GetAlphaDisabled();
303     auto iconWidth = theme->GetMenuIconSize();
304     auto iconHeight = theme->GetMenuIconSize();
305     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
306         iconColor = theme->GetIconColor();
307         iconOpacity = theme->GetIconDisableAlpha();
308         iconWidth = theme->GetIconWidth();
309         iconHeight = theme->GetIconHeight();
310     }
311 
312     if (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr) {
313         auto iconNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
314             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
315         CHECK_NULL_RETURN(iconNode, nullptr);
316         auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
317         CHECK_NULL_RETURN(symbolProperty, nullptr);
318         if (isButtonEnabled) {
319             symbolProperty->UpdateSymbolColorList({ iconColor });
320         } else {
321             symbolProperty->UpdateSymbolColorList({ iconColor.BlendOpacity(iconOpacity) });
322         }
323         barItem.iconSymbol.value()(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)));
324         UpdateSymbolEffect(symbolProperty, false);
325         symbolProperty->UpdateFontSize(iconWidth);
326         iconNode->MarkModifyDone();
327         return iconNode;
328     }
329     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
330     ImageSourceInfo info(barItem.icon.value());
331     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, nodeId, AceType::MakeRefPtr<ImagePattern>());
332     auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
333     CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
334     if (isButtonEnabled) {
335         info.SetFillColor(iconColor);
336     } else {
337         info.SetFillColor(iconColor.BlendOpacity(iconOpacity));
338     }
339     imageLayoutProperty->UpdateImageSourceInfo(info);
340     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconWidth), CalcLength(iconHeight)));
341     iconNode->MarkModifyDone();
342     return iconNode;
343 }
344 
InitTitleBarButtonEvent(const RefPtr<FrameNode> & buttonNode,const RefPtr<FrameNode> & iconNode,bool isMoreButton,const BarItem & menuItem,bool isButtonEnabled)345 void NavigationTitleUtil::InitTitleBarButtonEvent(const RefPtr<FrameNode>& buttonNode,
346     const RefPtr<FrameNode>& iconNode, bool isMoreButton, const BarItem& menuItem, bool isButtonEnabled)
347 {
348     auto eventHub = buttonNode->GetOrCreateInputEventHub();
349     CHECK_NULL_VOID(eventHub);
350 
351     if (isMoreButton) {
352         auto hoverTask = [weakTargetNode = WeakPtr<FrameNode>(buttonNode)](bool isHover) {
353             auto targetNode = weakTargetNode.Upgrade();
354             CHECK_NULL_VOID(targetNode);
355             auto popupParam = AceType::MakeRefPtr<PopupParam>();
356             auto theme = NavigationGetTheme();
357             CHECK_NULL_VOID(theme);
358             popupParam->SetMessage(theme->GetMoreMessage());
359             popupParam->SetIsShow(isHover);
360             popupParam->SetBlockEvent(false);
361             ViewAbstract::BindPopup(popupParam, targetNode, nullptr);
362         };
363         eventHub->AddOnHoverEvent(AceType::MakeRefPtr<InputEvent>(std::move(hoverTask)));
364         return;
365     }
366 
367     if (menuItem.action) {
368         auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
369         CHECK_NULL_VOID(gestureEventHub);
370         auto clickCallback = [action = menuItem.action, weakNode = WeakPtr<FrameNode>(iconNode)](GestureEvent& info) {
371             if (info.GetSourceDevice() == SourceType::KEYBOARD) {
372                 return;
373             }
374             if (action) {
375                 action();
376             }
377             auto symbol = weakNode.Upgrade();
378             CHECK_NULL_VOID(symbol);
379             if (symbol->GetTag() == V2::SYMBOL_ETS_TAG) {
380                 auto symbolProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
381                 CHECK_NULL_VOID(symbolProperty);
382                 auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
383                 symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
384                 symbolEffectOptions.SetIsTxtActive(true);
385                 symbolEffectOptions.SetIsTxtActiveSource(0);
386                 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
387                 symbol->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
388             }
389         };
390         gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(clickCallback));
391     }
392 
393     auto buttonEvent = buttonNode->GetEventHub<ButtonEventHub>();
394     CHECK_NULL_VOID(buttonEvent);
395     buttonEvent->SetEnabled(isButtonEnabled);
396     auto focusHub = buttonNode->GetFocusHub();
397     CHECK_NULL_VOID(focusHub);
398     focusHub->SetEnabled(isButtonEnabled);
399 }
400 
UpdateBarItemNodeWithItem(const RefPtr<BarItemNode> & barItemNode,const BarItem & barItem,const bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)401 void NavigationTitleUtil::UpdateBarItemNodeWithItem(const RefPtr<BarItemNode>& barItemNode, const BarItem& barItem,
402     const bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
403 {
404     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN) && barItem.text.has_value() &&
405         !barItem.text.value().empty()) {
406         auto textNode = CreateBarItemTextNode(barItem.text.value());
407         barItemNode->SetTextNode(textNode);
408         barItemNode->AddChild(textNode);
409     }
410     if ((barItem.icon.has_value()) || (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr)) {
411         auto iconNode = CreateBarItemIconNode(barItem, isButtonEnabled, theme);
412         barItemNode->SetIconNode(iconNode);
413         barItemNode->AddChild(iconNode);
414     }
415     if (barItem.action) {
416         auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
417         CHECK_NULL_VOID(eventHub);
418         eventHub->SetItemAction(barItem.action);
419     }
420     auto barItemPattern = barItemNode->GetPattern<BarItemPattern>();
421     barItemNode->MarkModifyDone();
422 }
423 
BuildImageMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)424 void BuildImageMoreItemNode(
425     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
426 {
427     int32_t imageNodeId = ElementRegister::GetInstance()->MakeUniqueId();
428     auto imageNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageNodeId, AceType::MakeRefPtr<ImagePattern>());
429     CHECK_NULL_VOID(imageNode);
430     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
431     CHECK_NULL_VOID(imageLayoutProperty);
432     CHECK_NULL_VOID(theme);
433 
434     auto info = ImageSourceInfo("");
435     info.SetResourceId(theme->GetMoreResourceId());
436     if (isButtonEnabled) {
437         info.SetFillColor(theme->GetMenuIconColor());
438     } else {
439         info.SetFillColor(theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()));
440     }
441 
442     imageLayoutProperty->UpdateImageSourceInfo(info);
443     auto iconSize = theme->GetMenuIconSize();
444     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
445     imageNode->MarkModifyDone();
446 
447     barItemNode->SetIsMoreItemNode(true);
448     barItemNode->SetIconNode(imageNode);
449     barItemNode->AddChild(imageNode);
450     barItemNode->MarkModifyDone();
451 }
452 
BuildSymbolMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)453 void BuildSymbolMoreItemNode(
454     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
455 {
456     CHECK_NULL_VOID(theme);
457     auto iconSize = theme->GetMenuIconSize();
458     auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
459         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
460     CHECK_NULL_VOID(symbolNode);
461     auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
462     CHECK_NULL_VOID(symbolProperty);
463     symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetMoreSymbolId()));
464     symbolProperty->UpdateFontSize(iconSize);
465     if (isButtonEnabled) {
466         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor() });
467     } else {
468         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()) });
469     }
470     symbolNode->MarkModifyDone();
471     barItemNode->SetIsMoreItemNode(true);
472     barItemNode->SetIconNode(symbolNode);
473     barItemNode->AddChild(symbolNode);
474     barItemNode->MarkModifyDone();
475 }
476 
BuildMoreIemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)477 void NavigationTitleUtil::BuildMoreIemNode(
478     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
479 {
480     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
481         SystemProperties::IsNeedSymbol()) {
482         BuildSymbolMoreItemNode(barItemNode, isButtonEnabled, theme);
483     } else {
484         BuildImageMoreItemNode(barItemNode, isButtonEnabled, theme);
485     }
486 }
487 
CreateBarItemNode(bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)488 RefPtr<BarItemNode> NavigationTitleUtil::CreateBarItemNode(
489     bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
490 {
491     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
492     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
493         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
494     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
495     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
496     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
497     BuildMoreIemNode(barItemNode, isButtonEnabled, theme);
498     return barItemNode;
499 }
500 
CreatePopupDialogNode(const RefPtr<FrameNode> targetNode,const std::vector<NG::BarItem> & menuItems,int32_t index,int32_t themeScopeId)501 RefPtr<FrameNode> NavigationTitleUtil::CreatePopupDialogNode(
502     const RefPtr<FrameNode> targetNode, const std::vector<NG::BarItem>& menuItems, int32_t index, int32_t themeScopeId)
503 {
504     CHECK_NULL_RETURN(targetNode, nullptr);
505     RefPtr<BarItemNode> barItemNode = AceType::DynamicCast<BarItemNode>(targetNode->GetFirstChild());
506     CHECK_NULL_RETURN(barItemNode, nullptr);
507     auto accessibilityProperty = targetNode->GetAccessibilityProperty<AccessibilityProperty>();
508     CHECK_NULL_RETURN(accessibilityProperty, nullptr);
509     ImageSourceInfo imageSourceInfo;
510     std::string message;
511     RefPtr<FrameNode> dialogNode;
512     if (barItemNode->IsMoreItemNode()) {
513         auto theme = NavigationGetTheme();
514         CHECK_NULL_RETURN(theme, nullptr);
515         message = theme->GetMoreMessage();
516         if (message.empty()) {
517             message = accessibilityProperty->GetAccessibilityText();
518         }
519         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
520             auto symbolNode = AceType::DynamicCast<FrameNode>(barItemNode->GetFirstChild());
521             CHECK_NULL_RETURN(symbolNode, nullptr);
522             dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, symbolNode);
523             return dialogNode;
524         }
525         imageSourceInfo.SetResourceId(theme->GetMoreResourceId());
526         dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo, themeScopeId);
527         return dialogNode;
528     }
529     if (index < 0 || index >= static_cast<int32_t>(menuItems.size())) {
530         return nullptr;
531     }
532     auto menuItem = menuItems.at(index);
533     if (menuItem.text.has_value() && !menuItem.text.value().empty()) {
534         message = menuItem.text.value();
535     } else {
536         message = accessibilityProperty->GetAccessibilityText();
537     }
538     if (menuItem.iconSymbol.has_value() && menuItem.iconSymbol.value() != nullptr) {
539         return CreateSymbolDialog(message, barItemNode, themeScopeId);
540     }
541     if (menuItem.icon.has_value() && !menuItem.icon.value().empty()) {
542         imageSourceInfo = ImageSourceInfo(menuItem.icon.value());
543     }
544     dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo, themeScopeId);
545     return dialogNode;
546 }
547 
CreateSymbolDialog(const std::string & message,const RefPtr<FrameNode> & targetNode,int32_t themeScopeId)548 RefPtr<FrameNode> NavigationTitleUtil::CreateSymbolDialog(
549     const std::string& message, const RefPtr<FrameNode>& targetNode, int32_t themeScopeId)
550 {
551     auto barItemNode = AceType::DynamicCast<BarItemNode>(targetNode);
552     CHECK_NULL_RETURN(barItemNode, nullptr);
553     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetIconNode());
554     CHECK_NULL_RETURN(iconNode, nullptr);
555     return AgingAdapationDialogUtil::ShowLongPressDialog(message, iconNode);
556 }
557 
SetAccessibility(const RefPtr<FrameNode> & node,const std::string & message)558 void NavigationTitleUtil::SetAccessibility(const RefPtr<FrameNode>& node, const std::string& message)
559 {
560     CHECK_NULL_VOID(node);
561     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
562     CHECK_NULL_VOID(accessibilityProperty);
563     accessibilityProperty->SetAccessibilityText(message);
564     accessibilityProperty->SetAccessibilityGroup(true);
565 }
566 
GetTitleString(const RefPtr<TitleBarNode> & titleBarNode,bool isCustom)567 std::string NavigationTitleUtil::GetTitleString(const RefPtr<TitleBarNode>& titleBarNode, bool isCustom)
568 {
569     if (isCustom) {
570         return "";
571     }
572     CHECK_NULL_RETURN(titleBarNode, "");
573     auto title = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
574     CHECK_NULL_RETURN(title, "");
575     if (title->GetTag() != V2::TEXT_ETS_TAG) {
576         return "";
577     }
578     auto textLayoutProperty = title->GetLayoutProperty<TextLayoutProperty>();
579     CHECK_NULL_RETURN(textLayoutProperty, "");
580     return UtfUtils::Str16ToStr8(textLayoutProperty->GetContentValue(u""));
581 }
582 
GetSubtitleString(const RefPtr<TitleBarNode> & titleBarNode)583 std::string NavigationTitleUtil::GetSubtitleString(const RefPtr<TitleBarNode>& titleBarNode)
584 {
585     CHECK_NULL_RETURN(titleBarNode, "");
586     auto subtitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
587     CHECK_NULL_RETURN(subtitle, "");
588     if (subtitle->GetTag() != V2::TEXT_ETS_TAG) {
589         return "";
590     }
591     auto textLayoutProperty = subtitle->GetLayoutProperty<TextLayoutProperty>();
592     CHECK_NULL_RETURN(textLayoutProperty, "");
593     return UtfUtils::Str16ToStr8(textLayoutProperty->GetContentValue(u""));
594 }
595 
ParseCalcDimensionToPx(const std::optional<CalcDimension> & value,const float titleBarWidth)596 float NavigationTitleUtil::ParseCalcDimensionToPx(const std::optional<CalcDimension>& value, const float titleBarWidth)
597 {
598     float result = 0.0f;
599     if (value.value().Unit() == DimensionUnit::PERCENT) {
600         result = value.value().Value() * titleBarWidth;
601     } else {
602         result = value.value().ConvertToPx();
603     }
604     return result;
605 }
606 
CreateOrUpdateMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo,bool ignoreMainTitle)607 void NavigationTitleUtil::CreateOrUpdateMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
608     const NG::NavigationTitleInfo& titleInfo, bool ignoreMainTitle)
609 {
610     CHECK_NULL_VOID(titleBarNode);
611     if (ignoreMainTitle) {
612         return;
613     }
614     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
615     if (!titleInfo.hasMainTitle) {
616         // remove main title if any.
617         titleBarNode->RemoveChild(mainTitle);
618         titleBarNode->SetTitle(nullptr);
619         return;
620     }
621 
622     if (mainTitle) {
623         // update main title
624         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
625         CHECK_NULL_VOID(textLayoutProperty);
626         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
627         textLayoutProperty->UpdateContent(titleInfo.title);
628         return;
629     }
630     // create and init main title
631     mainTitle = FrameNode::CreateFrameNode(
632         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
633     auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
634     CHECK_NULL_VOID(textLayoutProperty);
635     textLayoutProperty->UpdateContent(titleInfo.title);
636     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
637     CHECK_NULL_VOID(titleBarPattern);
638     titleBarPattern->SetNeedResetMainTitleProperty(true);
639     titleBarNode->SetTitle(mainTitle);
640     titleBarNode->AddChild(mainTitle);
641 }
642 
CreateOrUpdateSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)643 void NavigationTitleUtil::CreateOrUpdateSubtitle(const RefPtr<TitleBarNode>& titleBarNode,
644     const NG::NavigationTitleInfo& titleInfo)
645 {
646     CHECK_NULL_VOID(titleBarNode);
647     auto subTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
648     if (!titleInfo.hasSubTitle) {
649         // remove subtitle if any.
650         titleBarNode->RemoveChild(subTitle);
651         titleBarNode->SetSubtitle(nullptr);
652         return;
653     }
654     if (subTitle) {
655         // update subtitle
656         auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
657         CHECK_NULL_VOID(textLayoutProperty);
658         textLayoutProperty->UpdateContent(titleInfo.subtitle);
659         auto renderContext = subTitle->GetRenderContext();
660         CHECK_NULL_VOID(renderContext);
661         renderContext->UpdateOpacity(1.0);
662         return;
663     }
664     // create and init subtitle
665     subTitle = FrameNode::CreateFrameNode(
666         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
667     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
668     CHECK_NULL_VOID(textLayoutProperty);
669     textLayoutProperty->UpdateContent(titleInfo.subtitle);
670     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
671     CHECK_NULL_VOID(titleBarPattern);
672     titleBarPattern->SetNeedResetSubTitleProperty(true);
673     titleBarNode->SetSubtitle(subTitle);
674     titleBarNode->AddChild(subTitle);
675 }
676 
CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)677 void NavigationTitleUtil::CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
678     const NG::NavigationTitleInfo& titleInfo)
679 {
680     CHECK_NULL_VOID(titleBarNode);
681     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
682     if (!titleInfo.hasMainTitle) {
683         // remove main title if any.
684         titleBarNode->RemoveChild(mainTitle);
685         titleBarNode->SetTitle(nullptr);
686         return;
687     }
688     if (mainTitle) {
689         // update main title
690         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
691         CHECK_NULL_VOID(textLayoutProperty);
692         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
693         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
694             textLayoutProperty->UpdateHeightAdaptivePolicy(titleInfo.hasSubTitle ?
695             TextHeightAdaptivePolicy::MAX_LINES_FIRST : TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
696         }
697         textLayoutProperty->UpdateContent(titleInfo.title);
698         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
699         return;
700     }
701     // create and init main title
702     mainTitle = FrameNode::CreateFrameNode(
703         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
704     auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
705     CHECK_NULL_VOID(textLayoutProperty);
706     textLayoutProperty->UpdateContent(titleInfo.title);
707     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
708     CHECK_NULL_VOID(titleBarPattern);
709     titleBarPattern->SetNeedResetMainTitleProperty(true);
710     titleBarNode->SetTitle(mainTitle);
711     titleBarNode->AddChild(mainTitle);
712 }
713 
CreateOrUpdateDestinationSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)714 void NavigationTitleUtil::CreateOrUpdateDestinationSubtitle(const RefPtr<TitleBarNode>& titleBarNode,
715     const NG::NavigationTitleInfo& titleInfo)
716 {
717     CHECK_NULL_VOID(titleBarNode);
718     auto subTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
719     if (!titleInfo.hasSubTitle) {
720         // remove subtitle if any.
721         titleBarNode->RemoveChild(subTitle);
722         titleBarNode->SetSubtitle(nullptr);
723         return;
724     }
725     if (subTitle) {
726         // update subtitle
727         auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
728         CHECK_NULL_VOID(textLayoutProperty);
729         textLayoutProperty->UpdateContent(titleInfo.subtitle);
730         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
731         return;
732     }
733     // create and init subtitle
734     subTitle = FrameNode::CreateFrameNode(
735         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
736     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
737     CHECK_NULL_VOID(textLayoutProperty);
738     textLayoutProperty->UpdateContent(titleInfo.subtitle);
739     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
740     CHECK_NULL_VOID(titleBarPattern);
741     titleBarPattern->SetNeedResetSubTitleProperty(true);
742     titleBarNode->SetSubtitle(subTitle);
743     titleBarNode->AddChild(subTitle);
744 }
745 
FoldStatusChangedAnimation(const RefPtr<FrameNode> & host)746 void NavigationTitleUtil::FoldStatusChangedAnimation(const RefPtr<FrameNode>& host)
747 {
748     CHECK_NULL_VOID(host);
749     auto pipelineContext = host->GetContext();
750     CHECK_NULL_VOID(pipelineContext);
751     auto titleBar = AceType::DynamicCast<TitleBarNode>(host);
752     CHECK_NULL_VOID(titleBar);
753     auto pattern = titleBar->GetPattern<TitleBarPattern>();
754     CHECK_NULL_VOID(pattern);
755 
756     if (!pipelineContext->IsHoverModeChange() || !IsNeedHoverModeAction(titleBar)) {
757         // Since only expanded to hover or hover to expanded need this animation.
758         return;
759     }
760 
761     AnimationOption option;
762     option.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
763     auto renderNodeContext = host->GetRenderContext();
764     CHECK_NULL_VOID(renderNodeContext);
765     option.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
766     renderNodeContext->UpdateOpacity(1.0f);
767     option.SetOnFinishEvent([weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext),
768                                 weakHost = WeakPtr<FrameNode>(host)]() {
769         auto host = weakHost.Upgrade();
770         CHECK_NULL_VOID(host);
771         auto renderContext = weakRenderNodeContext.Upgrade();
772         CHECK_NULL_VOID(renderContext);
773         AnimationOption finishOption;
774         finishOption.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
775         finishOption.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
776         auto parent = AceType::DynamicCast<FrameNode>(host->GetParent());
777         CHECK_NULL_VOID(parent);
778         parent->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
779         AnimationUtils::Animate(
780             finishOption, [weakRenderNodeContext = WeakPtr<RenderContext>(renderContext)]() {
781                 auto renderNodeContext = weakRenderNodeContext.Upgrade();
782                 CHECK_NULL_VOID(renderNodeContext);
783                 renderNodeContext->UpdateOpacity(1.0f);
784             });
785     });
786     AnimationUtils::Animate(
787         option,
788         [weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext)]() {
789             auto renderContext = weakRenderNodeContext.Upgrade();
790             CHECK_NULL_VOID(renderContext);
791             renderContext->UpdateOpacity(0.0f);
792         },
793         option.GetOnFinishEvent());
794 }
795 
IsNeedHoverModeAction(const RefPtr<TitleBarNode> & titleBarNode)796 bool NavigationTitleUtil::IsNeedHoverModeAction(const RefPtr<TitleBarNode>& titleBarNode)
797 {
798     CHECK_NULL_RETURN(titleBarNode, false);
799     auto pattern = titleBarNode->GetPattern<TitleBarPattern>();
800     CHECK_NULL_RETURN(pattern, false);
801     auto options = pattern->GetTitleBarOptions();
802     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
803     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
804     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
805     if (parentType == TitleBarParentType::NAVBAR &&
806         titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::MINI) == NavigationTitleMode::FREE) {
807         return false;
808     }
809     if (!options.enableHoverMode || options.brOptions.barStyle == NG::BarStyle::STANDARD) {
810         return false;
811     }
812     RefPtr<NavigationGroupNode> navigationGroupNode;
813     if (parentType == TitleBarParentType::NAVBAR) {
814         auto navBarNode = AceType::DynamicCast<NavBarNode>(titleBarNode->GetParent());
815         CHECK_NULL_RETURN(navBarNode, false);
816         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navBarNode->GetParent());
817     } else {
818         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(titleBarNode->GetParent());
819         CHECK_NULL_RETURN(navDestination, false);
820         auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
821         CHECK_NULL_RETURN(navDestinationPattern, false);
822         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
823     }
824     CHECK_NULL_RETURN(navigationGroupNode, false);
825     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigationGroupNode->GetPattern());
826     CHECK_NULL_RETURN(navigationPattern, false);
827     auto pageNode = navigationPattern->GetNavBasePageNode();
828     CHECK_NULL_RETURN(pageNode, false);
829     auto foldCreaseRects = pattern->GetFoldCreaseRects();
830     auto parentNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetParent());
831     CHECK_NULL_RETURN(parentNode, false);
832     bool isParentFullPage = pageNode->GetGeometryNode()->GetFrameSize().Height()
833         == parentNode->GetGeometryNode()->GetFrameSize().Height();
834     return !foldCreaseRects.empty() && isParentFullPage;
835 }
836 
CalculateTitlebarOffset(const RefPtr<UINode> & titleBarNode)837 float NavigationTitleUtil::CalculateTitlebarOffset(const RefPtr<UINode>& titleBarNode)
838 {
839     CHECK_NULL_RETURN(titleBarNode, 0.0f);
840     auto titleBar = AceType::DynamicCast<TitleBarNode>(titleBarNode);
841     CHECK_NULL_RETURN(titleBar, 0.0f);
842     if (!IsNeedHoverModeAction(titleBar)) {
843         return 0.0f;
844     }
845     auto pattern = titleBar->GetPattern<TitleBarPattern>();
846     CHECK_NULL_RETURN(pattern, false);
847     auto foldCreaseRects = pattern->GetFoldCreaseRects();
848     auto pipelineContext = titleBar->GetContext();
849     CHECK_NULL_RETURN(pipelineContext, 0.0f);
850     if (!pipelineContext->IsHalfFoldHoverStatus()) {
851         return 0.0f;
852     }
853     auto safeArea = pipelineContext->GetSafeAreaWithoutProcess();
854     auto length = safeArea.top_.Length();
855     auto foldCrease = foldCreaseRects.front();
856 
857     // offsetY = The Y of the foldCrease + Adapt vertical displacement of hover state - the height of the status bar.
858     return foldCrease.GetOffset().GetY() + TITLEBAR_VERTICAL_PADDING.ConvertToPx() - length;
859 }
860 
UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & barNode,float translate,bool isTitle)861 void NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase>& nodeBase,
862     const RefPtr<FrameNode>& barNode, float translate, bool isTitle)
863 {
864     CHECK_NULL_VOID(nodeBase);
865     CHECK_NULL_VOID(barNode);
866     auto renderContext = barNode->GetRenderContext();
867     CHECK_NULL_VOID(renderContext);
868     auto option = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
869     option.y = CalcDimension(translate, DimensionUnit::PX);
870     renderContext->UpdateTransformTranslate(option);
871     auto barHeight = renderContext->GetPaintRectWithoutTransform().Height();
872     float opacity = 1.0f;
873     if (!NearZero(barHeight)) {
874         opacity = 1.0f - std::clamp(std::abs(translate) / barHeight, 0.0f, 1.0f);
875     }
876     renderContext->UpdateOpacity(opacity);
877     if (isTitle) {
878         return;
879     }
880     auto divider = AceType::DynamicCast<FrameNode>(nodeBase->GetToolBarDividerNode());
881     CHECK_NULL_VOID(divider);
882     auto dividerRenderContext = divider->GetRenderContext();
883     CHECK_NULL_VOID(dividerRenderContext);
884     dividerRenderContext->UpdateTransformTranslate(option);
885     dividerRenderContext->UpdateOpacity(opacity);
886 }
887 
IsTitleBarHasOffsetY(const RefPtr<FrameNode> & titleBarNode)888 bool NavigationTitleUtil::IsTitleBarHasOffsetY(const RefPtr<FrameNode>& titleBarNode)
889 {
890     return titleBarNode && titleBarNode->IsVisible() && !NearZero(CalculateTitlebarOffset(titleBarNode));
891 }
892 } // namespace OHOS::Ace::NG
893