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