• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/components_ng/pattern/navigation/nav_bar_pattern.h"
17 
18 #include <algorithm>
19 
20 #include "base/i18n/localization.h"
21 #include "base/subwindow/subwindow_manager.h"
22 #include "base/utils/system_properties.h"
23 #include "core/components_ng/pattern/image/image_layout_property.h"
24 #include "core/components_ng/pattern/image/image_pattern.h"
25 #include "core/components_ng/pattern/menu/menu_view.h"
26 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
27 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
28 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
29 #include "core/components_ng/pattern/navigation/navigation_toolbar_util.h"
30 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
31 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
32 
33 namespace OHOS::Ace::NG {
34 namespace {
35 // titlebar ZINDEX
36 constexpr static int32_t DEFAULT_TITLEBAR_ZINDEX = 2;
BuildMoreItemNodeAction(const RefPtr<FrameNode> & buttonNode,const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode,const RefPtr<NavBarNode> & navBarNode,const MenuParam & menuParam)37 void BuildMoreItemNodeAction(const RefPtr<FrameNode>& buttonNode, const RefPtr<BarItemNode>& barItemNode,
38     const RefPtr<FrameNode>& barMenuNode, const RefPtr<NavBarNode>& navBarNode, const MenuParam& menuParam)
39 {
40     auto eventHub = barItemNode->GetOrCreateEventHub<BarItemEventHub>();
41     CHECK_NULL_VOID(eventHub);
42 
43     auto context = PipelineContext::GetCurrentContext();
44     auto clickCallback = [weakContext = WeakPtr<PipelineContext>(context),
45                             id = barItemNode->GetId(),
46                             param = menuParam,
47                             weakMenu = WeakPtr<FrameNode>(barMenuNode),
48                             weakBarItemNode = WeakPtr<BarItemNode>(barItemNode),
49                             weakNavBarNode = WeakPtr<NavBarNode>(navBarNode)]() {
50         auto context = weakContext.Upgrade();
51         CHECK_NULL_VOID(context);
52 
53         auto overlayManager = context->GetOverlayManager();
54         CHECK_NULL_VOID(overlayManager);
55 
56         auto menu = weakMenu.Upgrade();
57         CHECK_NULL_VOID(menu);
58 
59         auto barItemNode = weakBarItemNode.Upgrade();
60         CHECK_NULL_VOID(barItemNode);
61 
62         auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
63         CHECK_NULL_VOID(menuNode);
64 
65         auto menuPattern = menuNode->GetPattern<MenuPattern>();
66         CHECK_NULL_VOID(menuPattern);
67 
68         auto navBarNode = weakNavBarNode.Upgrade();
69         CHECK_NULL_VOID(navBarNode);
70 
71         auto navBarPattern = navBarNode->GetPattern<NavBarPattern>();
72         CHECK_NULL_VOID(navBarPattern);
73 
74         // navigation menu show like select.
75         menuPattern->SetIsSelectMenu(true);
76         OffsetF offset(0.0f, 0.0f);
77         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
78             auto symbol = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
79             CHECK_NULL_VOID(symbol);
80             auto symbolProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
81             CHECK_NULL_VOID(symbolProperty);
82             auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
83             symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
84             symbolEffectOptions.SetIsTxtActive(true);
85             symbolEffectOptions.SetIsTxtActiveSource(0);
86             symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
87             symbol->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
88         } else {
89             offset = navBarPattern->GetShowMenuOffset(barItemNode, menuNode);
90         }
91 
92         if (param.isShowInSubWindow) {
93             auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
94             if (wrapperPattern && wrapperPattern->GetMenuStatus() == MenuStatus::ON_HIDE_ANIMATION) {
95                 //if on hide animation, avoid displaying the menu again
96                 return;
97             }
98             SubwindowManager::GetInstance()->ShowMenuNG(menu, param, barItemNode, offset);
99             return;
100         }
101         overlayManager->ShowMenu(id, offset, menu);
102     };
103     eventHub->SetItemAction(clickCallback);
104 
105     auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
106     CHECK_NULL_VOID(gestureEventHub);
107     auto callback = [action = clickCallback](GestureEvent& info) {
108         if (info.GetSourceDevice() == SourceType::KEYBOARD) {
109             return;
110         }
111         action();
112     };
113     gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(callback));
114 }
115 
CreateMenuItems(const int32_t menuNodeId,const std::vector<NG::BarItem> & menuItems,const RefPtr<NavBarNode> & navBarNode,bool isCreateLandscapeMenu)116 RefPtr<FrameNode> CreateMenuItems(const int32_t menuNodeId, const std::vector<NG::BarItem>& menuItems,
117     const RefPtr<NavBarNode>& navBarNode, bool isCreateLandscapeMenu)
118 {
119     auto menuNode = FrameNode::GetOrCreateFrameNode(
120         V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
121     CHECK_NULL_RETURN(menuNode, nullptr);
122     menuNode->Clean();
123     menuNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
124     auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
125     CHECK_NULL_RETURN(rowProperty, nullptr);
126     rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
127     CHECK_NULL_RETURN(navBarNode, nullptr);
128     auto frameNode = navBarNode->GetParent();
129     CHECK_NULL_RETURN(frameNode, nullptr);
130     auto theme = NavigationGetTheme(frameNode->GetThemeScopeId());
131     CHECK_NULL_RETURN(theme, nullptr);
132     auto navBarPattern = AceType::DynamicCast<NavBarPattern>(navBarNode->GetPattern());
133     auto navBarMaxNum = navBarPattern->GetMaxMenuNum();
134     auto mostMenuItemCount =
135         navBarMaxNum < 0 ? theme->GetMostMenuItemCountInBar() : static_cast<uint32_t>(navBarMaxNum);
136     mostMenuItemCount = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
137                                                                                                   : mostMenuItemCount;
138     navBarPattern->SetMaxMenuNum(mostMenuItemCount);
139     bool needMoreButton = menuItems.size() > mostMenuItemCount;
140 
141     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
142     CHECK_NULL_RETURN(navigationGroupNode, nullptr);
143     auto hub = navigationGroupNode->GetOrCreateEventHub<EventHub>();
144     CHECK_NULL_RETURN(hub, nullptr);
145     auto isButtonEnabled = hub->IsEnabled();
146 
147     std::string parentId = navigationGroupNode->GetInspectorId().value_or("");
148     int32_t count = 0;
149     std::vector<OptionParam> params;
150     OptionParam param;
151     for (const auto& menuItem : menuItems) {
152         ++count;
153         if (needMoreButton && (count > static_cast<int32_t>(mostMenuItemCount) - 1)) {
154             param = { menuItem.text.value_or(""), menuItem.icon.value_or(""), menuItem.isEnabled.value_or(true),
155                 menuItem.action, menuItem.iconSymbol.value_or(nullptr) };
156             param.SetSymbolUserDefinedIdealFontSize(theme->GetMenuIconSize());
157             params.push_back(param);
158         } else {
159             auto menuItemNode = NavigationTitleUtil::CreateMenuItemButton(theme);
160             int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
161             auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
162                 V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
163             NavigationTitleUtil::UpdateBarItemNodeWithItem(barItemNode, menuItem, isButtonEnabled, theme);
164             auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
165             CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
166             barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
167 
168             auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
169             NavigationTitleUtil::InitTitleBarButtonEvent(
170                 menuItemNode, iconNode, false, menuItem, menuItem.isEnabled.value_or(true));
171 
172             // read navigation menu button
173             NavigationTitleUtil::SetAccessibility(menuItemNode, menuItem.text.value_or(""));
174 
175             // set navigation titleBar menu inspectorId
176             std::string menuItemValue = menuItemNode->GetTag() + std::to_string(count);
177             // Field field;
178             NavigationTitleUtil::SetInnerChildId(menuItemNode, NG::NAV_FIELD,
179                 menuNode->GetTag(), menuItemValue, parentId);
180 
181             barItemNode->MountToParent(menuItemNode);
182             barItemNode->MarkModifyDone();
183             menuItemNode->MarkModifyDone();
184             menuNode->AddChild(menuItemNode);
185         }
186     }
187 
188     // build more button
189     if (needMoreButton) {
190         int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
191         auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
192             V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
193         auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
194         CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
195         barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
196         NavigationTitleUtil::BuildMoreIemNode(barItemNode, isButtonEnabled, theme);
197         auto menuItemNode = NavigationTitleUtil::CreateMenuItemButton(theme);
198         MenuParam menuParam;
199         menuParam.isShowInSubWindow = false;
200         if (SystemProperties::GetDeviceType() == DeviceType::TWO_IN_ONE) {
201             menuParam.isShowInSubWindow = true;
202         }
203         auto targetId = barItemNode->GetId();
204         auto targetTag = barItemNode->GetTag();
205         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
206             menuParam.placement = Placement::BOTTOM_RIGHT;
207             targetId = menuItemNode->GetId();
208             targetTag = menuItemNode->GetTag();
209         }
210         NavigationMenuOptions menuOptions = navBarPattern->GetMenuOptions();
211         if (menuOptions.mbOptions.bgOptions.blurStyleOption.has_value()) {
212             menuParam.backgroundBlurStyleOption = menuOptions.mbOptions.bgOptions.blurStyleOption.value();
213         }
214         if (menuOptions.mbOptions.bgOptions.effectOption.has_value()) {
215             menuParam.backgroundEffectOption = menuOptions.mbOptions.bgOptions.effectOption.value();
216         }
217         auto barMenuNode = MenuView::Create(
218             std::move(params), targetId, targetTag, MenuType::NAVIGATION_MENU, menuParam);
219         BuildMoreItemNodeAction(menuItemNode, barItemNode, barMenuNode, navBarNode, menuParam);
220         auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
221         NavigationTitleUtil::InitTitleBarButtonEvent(menuItemNode, iconNode, true);
222 
223         // read navigation "more" button
224         std::string message  = theme->GetMoreMessage();
225         NavigationTitleUtil::SetAccessibility(menuItemNode, message);
226 
227         // set navigation titleBar "more" button inspectorId
228         NavigationTitleUtil::SetInnerChildId(menuItemNode, NG::NAV_FIELD, menuNode->GetTag(), "More", parentId);
229 
230         barItemNode->MountToParent(menuItemNode);
231         barItemNode->MarkModifyDone();
232         menuItemNode->MarkModifyDone();
233         menuNode->AddChild(menuItemNode);
234         isCreateLandscapeMenu ? navBarNode->SetLandscapeMenuNode(barMenuNode) : navBarNode->SetMenuNode(barMenuNode);
235     }
236     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
237     CHECK_NULL_RETURN(titleBarNode, nullptr);
238     auto titlePattern = titleBarNode->GetPattern<TitleBarPattern>();
239     CHECK_NULL_RETURN(titlePattern, nullptr);
240     titlePattern->InitMenuDragAndLongPressEvent(menuNode, menuItems);
241     return menuNode;
242 }
243 
BuildMenu(const RefPtr<NavBarNode> & navBarNode,const RefPtr<TitleBarNode> & titleBarNode)244 void BuildMenu(const RefPtr<NavBarNode>& navBarNode, const RefPtr<TitleBarNode>& titleBarNode)
245 {
246     if (navBarNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::REPLACE) {
247         titleBarNode->RemoveChild(titleBarNode->GetMenu());
248         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
249     }
250     if (navBarNode->GetPrevMenuIsCustomValue(false)) {
251         if (navBarNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::NONE) {
252             return;
253         }
254         titleBarNode->SetMenu(navBarNode->GetMenu());
255         titleBarNode->AddChild(titleBarNode->GetMenu());
256         navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
257     } else {
258         navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
259         auto navBarPattern = navBarNode->GetPattern<NavBarPattern>();
260         CHECK_NULL_VOID(navBarPattern);
261         auto titleBarMenuItems = navBarPattern->GetTitleBarMenuItems();
262         auto toolBarMenuItems = navBarPattern->GetToolBarMenuItems();
263 
264         if (navBarPattern->HasMenuNodeId()) {
265             auto menuNode = CreateMenuItems(navBarPattern->GetMenuNodeId(), titleBarMenuItems, navBarNode, false);
266             CHECK_NULL_VOID(menuNode);
267             navBarNode->SetMenu(menuNode);
268         }
269 
270         titleBarMenuItems.insert(titleBarMenuItems.end(), toolBarMenuItems.begin(), toolBarMenuItems.end());
271         auto landscapeMenuNode =
272             CreateMenuItems(navBarPattern->GetLandscapeMenuNodeId(), titleBarMenuItems, navBarNode, true);
273         CHECK_NULL_VOID(landscapeMenuNode);
274         navBarNode->SetLandscapeMenu(landscapeMenuNode);
275     }
276 }
277 
BuildTitleBar(const RefPtr<NavBarNode> & navBarNode,const RefPtr<TitleBarNode> & titleBarNode)278 void BuildTitleBar(const RefPtr<NavBarNode>& navBarNode, const RefPtr<TitleBarNode>& titleBarNode)
279 {
280     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
281     CHECK_NULL_VOID(titleBarLayoutProperty);
282 
283     // Update back button visibility
284     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
285     if (backButtonNode) {
286         auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty();
287         CHECK_NULL_VOID(backButtonLayoutProperty);
288         backButtonLayoutProperty->UpdateVisibility(
289             titleBarLayoutProperty->GetHideBackButtonValue(false) ? VisibleType::GONE : VisibleType::VISIBLE);
290     }
291 
292     // update main title
293     auto mainTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
294     if (mainTitleNode && !navBarNode->GetPrevTitleIsCustomValue(false)) {
295         auto textLayoutProperty = mainTitleNode->GetLayoutProperty<TextLayoutProperty>();
296         CHECK_NULL_VOID(textLayoutProperty);
297         auto theme = NavigationGetTheme();
298         CHECK_NULL_VOID(theme);
299         if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
300             textLayoutProperty->UpdateFontSize(theme->GetTitleFontSize());
301         } else {
302             textLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
303         }
304         mainTitleNode->MarkModifyDone();
305     }
306 
307     // update menu
308     BuildMenu(navBarNode, titleBarNode);
309 }
310 } // namespace
311 
MountTitleBar(const RefPtr<FrameNode> & host,bool & needRunTitleBarAnimation)312 void NavBarPattern::MountTitleBar(
313     const RefPtr<FrameNode>& host, bool& needRunTitleBarAnimation)
314 {
315     needRunTitleBarAnimation = false;
316     auto hostNode = AceType::DynamicCast<NavBarNode>(host);
317     CHECK_NULL_VOID(hostNode);
318     auto navBarLayoutProperty = hostNode->GetLayoutProperty<NavBarLayoutProperty>();
319     CHECK_NULL_VOID(navBarLayoutProperty);
320     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
321     CHECK_NULL_VOID(titleBarNode);
322     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
323     CHECK_NULL_VOID(titleBarLayoutProperty);
324     auto navBarPattern = AceType::DynamicCast<NavBarPattern>(hostNode->GetPattern());
325     auto hasCustomMenu = hostNode->GetPrevMenuIsCustomValue(false) && hostNode->GetMenu();
326     // menu is not consume menu, menu item and tool bar menus need all empty
327     auto hideMenu = !hostNode->GetPrevMenuIsCustomValue(false) && navBarPattern->GetTitleBarMenuItems().empty() &&
328                     navBarPattern->GetToolBarMenuItems().empty();
329     if (!titleBarNode->GetTitle() && !titleBarNode->GetSubtitle() && !titleBarNode->GetBackButton() && !hasCustomMenu &&
330         hideMenu) {
331         titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
332         return;
333     }
334     titleBarLayoutProperty->UpdateTitleMode(navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE));
335     titleBarLayoutProperty->UpdateHideBackButton(navBarLayoutProperty->GetHideBackButtonValue(false));
336     BuildTitleBar(hostNode, titleBarNode);
337     bool hideTitleBar = navBarLayoutProperty->GetHideTitleBarValue(false);
338     // At the initial state, animation is not required.
339     if (!currHideTitleBar_.has_value() ||
340         !navBarLayoutProperty->GetIsAnimatedTitleBarValue(false)) {
341         currHideTitleBar_ = hideTitleBar;
342         HideOrShowTitleBarImmediately(hostNode, hideTitleBar);
343         return;
344     }
345     titleBarNode->MarkModifyDone();
346     titleBarNode->MarkDirtyNode();
347 
348     // Animation is needed only when the status changed.
349     needRunTitleBarAnimation = currHideTitleBar_.value() != hideTitleBar;
350     currHideTitleBar_ = hideTitleBar;
351 }
352 
GetShowMenuOffset(const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & menuNode)353 OffsetF NavBarPattern::GetShowMenuOffset(const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& menuNode)
354 {
355     auto imageNode = barItemNode->GetChildAtIndex(0);
356     CHECK_NULL_RETURN(imageNode, OffsetF(0.0f, 0.0f));
357 
358     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
359     CHECK_NULL_RETURN(imageFrameNode, OffsetF(0.0f, 0.0f));
360     auto imgOffset = imageFrameNode->GetOffsetRelativeToWindow();
361     auto imageSize = imageFrameNode->GetGeometryNode()->GetFrameSize();
362 
363     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
364     CHECK_NULL_RETURN(menuLayoutProperty, OffsetF(0.0f, 0.0f));
365     menuLayoutProperty->UpdateTargetSize(imageSize);
366 
367     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
368     if (isRightToLeft) {
369         imgOffset.SetX(imgOffset.GetX() + imageSize.Width());
370     }
371     imgOffset.SetY(imgOffset.GetY() + imageSize.Height());
372     return imgOffset;
373 }
374 
OnAttachToFrameNode()375 void NavBarPattern::OnAttachToFrameNode()
376 {
377     auto host = GetHost();
378     CHECK_NULL_VOID(host);
379     NavDestinationPatternBase::InitOnTouchEvent(host);
380     auto pipelineContext = host->GetContextWithCheck();
381     CHECK_NULL_VOID(pipelineContext);
382     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
383 
384     auto theme = NavigationGetTheme();
385     CHECK_NULL_VOID(theme);
386     if (theme && theme->GetNavBarUnfocusEffectEnable()) {
387         pipelineContext->AddWindowFocusChangedCallback(host->GetId());
388     }
389     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
390         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
391             .edges = SAFE_AREA_EDGE_ALL };
392         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
393     }
394 }
395 
OnCoordScrollStart()396 void NavBarPattern::OnCoordScrollStart()
397 {
398     if (isHideTitlebar_ || titleMode_ != NavigationTitleMode::FREE) {
399         auto eventHub = GetOrCreateEventHub<NavBarEventHub>();
400         CHECK_NULL_VOID(eventHub);
401         eventHub->FireOnCoordScrollStartAction();
402         return;
403     }
404     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
405     CHECK_NULL_VOID(hostNode);
406     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
407     CHECK_NULL_VOID(titleNode);
408     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
409     CHECK_NULL_VOID(titlePattern);
410     titlePattern->OnCoordScrollStart();
411 }
412 
OnCoordScrollUpdate(float offset,float currentOffset)413 float NavBarPattern::OnCoordScrollUpdate(float offset, float currentOffset)
414 {
415     if (isHideTitlebar_ || titleMode_ != NavigationTitleMode::FREE) {
416         auto eventHub = GetOrCreateEventHub<NavBarEventHub>();
417         CHECK_NULL_RETURN(eventHub, 0.0f);
418         eventHub->FireOnCoordScrollUpdateAction(currentOffset);
419         return 0.0f;
420     }
421     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
422     CHECK_NULL_RETURN(hostNode, 0.0f);
423     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
424     CHECK_NULL_RETURN(titleNode, 0.0f);
425     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
426     CHECK_NULL_RETURN(titlePattern, 0.0f);
427     return titlePattern->OnCoordScrollUpdate(offset);
428 }
429 
OnCoordScrollEnd()430 void NavBarPattern::OnCoordScrollEnd()
431 {
432     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "OnCoordScroll end");
433     if (titleMode_ != NavigationTitleMode::FREE) {
434         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "titleMode_ is not free");
435         auto eventHub = GetOrCreateEventHub<NavBarEventHub>();
436         CHECK_NULL_VOID(eventHub);
437         eventHub->FireOnCoordScrollEndAction();
438         return;
439     }
440     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
441     CHECK_NULL_VOID(hostNode);
442     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
443     CHECK_NULL_VOID(titleNode);
444     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
445     titlePattern->OnCoordScrollEnd();
446 }
447 
OnModifyDone()448 void NavBarPattern::OnModifyDone()
449 {
450     Pattern::OnModifyDone();
451     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
452     CHECK_NULL_VOID(hostNode);
453     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
454     CHECK_NULL_VOID(titleBarNode);
455     auto titleBarRenderContext = titleBarNode->GetRenderContext();
456     CHECK_NULL_VOID(titleBarRenderContext);
457     // set the titlebar to float on the top
458     titleBarRenderContext->UpdateZIndex(DEFAULT_TITLEBAR_ZINDEX);
459     bool needRunTitleBarAnimation = false;
460     MountTitleBar(hostNode, needRunTitleBarAnimation);
461     bool needRunToolBarAnimation = false;
462     NavigationToolbarUtil::MountToolBar(hostNode, needRunToolBarAnimation);
463     HandleTitleBarAndToolBarAnimation(
464         hostNode, needRunTitleBarAnimation, needRunToolBarAnimation);
465     UpdateHideBarProperty();
466     ExpandContentSafeAreaIfNeeded();
467     auto navBarLayoutProperty = hostNode->GetLayoutProperty<NavBarLayoutProperty>();
468     CHECK_NULL_VOID(navBarLayoutProperty);
469     titleMode_ = navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
470 
471     auto parent = hostNode->GetParent();
472     CHECK_NULL_VOID(parent);
473     titleBarNode->SetInnerParentId(parent->GetInspectorId().value_or(""));
474     auto layoutPolicy = navBarLayoutProperty->GetLayoutPolicyProperty();
475     if (layoutPolicy.has_value()) {
476         auto content = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
477         CHECK_NULL_VOID(content);
478         content->GetLayoutProperty()->UpdateLayoutPolicyProperty(
479             layoutPolicy.value().widthLayoutPolicy_.value_or(LayoutCalPolicy::NO_MATCH), true);
480         content->GetLayoutProperty()->UpdateLayoutPolicyProperty(
481             layoutPolicy.value().heightLayoutPolicy_.value_or(LayoutCalPolicy::NO_MATCH), false);
482     }
483 }
484 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)485 void NavBarPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
486 {
487     auto navBarNode = AceType::DynamicCast<NavBarNode>(GetHost());
488     CHECK_NULL_VOID(navBarNode);
489     if (preWidth_.has_value() && preWidth_.value() != width) {
490         AbortBarAnimation();
491     }
492     preWidth_ = width;
493     // change menu num in landscape and orientation
494     do {
495         if (navBarNode->GetPrevMenuIsCustomValue(false)) {
496             break;
497         }
498         auto targetNum = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
499                                                                                                   : MAX_MENU_NUM_SMALL;
500         if (targetNum == maxMenuNums_) {
501             break;
502         }
503         maxMenuNums_ = targetNum;
504         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
505         CHECK_NULL_VOID(titleBarNode);
506         BuildMenu(navBarNode, titleBarNode);
507         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
508     } while (0);
509 }
510 
OnDetachFromFrameNode(FrameNode * frameNode)511 void NavBarPattern::OnDetachFromFrameNode(FrameNode* frameNode)
512 {
513     CHECK_NULL_VOID(frameNode);
514     auto pipeline = frameNode->GetContextWithCheck();
515     CHECK_NULL_VOID(pipeline);
516     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
517     NavDestinationPatternBase::RemoveOnTouchEvent(frameNode);
518 }
519 
CanCoordScrollUp(float offset) const520 bool NavBarPattern::CanCoordScrollUp(float offset) const
521 {
522     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
523     CHECK_NULL_RETURN(hostNode, false);
524     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
525     CHECK_NULL_RETURN(titleNode, false);
526     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
527     CHECK_NULL_RETURN(titlePattern, false);
528     return (Negative(offset) && !titlePattern->IsCurrentMinTitle()) || IsNeedHandleScroll();
529 }
530 
GetTitleBarHeightLessThanMaxBarHeight() const531 float NavBarPattern::GetTitleBarHeightLessThanMaxBarHeight() const
532 {
533     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
534     CHECK_NULL_RETURN(hostNode, 0.f);
535     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
536     CHECK_NULL_RETURN(titleBarNode, 0.f);
537     auto titlePattern = titleBarNode->GetPattern<TitleBarPattern>();
538     CHECK_NULL_RETURN(titlePattern, 0.f);
539     return titlePattern->GetTitleBarHeightLessThanMaxBarHeight();
540 }
541 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)542 bool NavBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
543 {
544     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
545     CHECK_NULL_RETURN(hostNode, false);
546     hostNode->AdjustRenderContextIfNeeded();
547     return false;
548 }
549 
BeforeCreateLayoutWrapper()550 void NavBarPattern::BeforeCreateLayoutWrapper()
551 {
552     auto eventHub = GetOrCreateEventHub<NavBarEventHub>();
553     CHECK_NULL_VOID(eventHub);
554     eventHub->FireBeforeCreateLayoutWrapperCallBack();
555 }
556 } // namespace OHOS::Ace::NG
557