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