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/title_bar_pattern.h"
17
18 #include <sstream>
19
20 #include "core/animation/spring_curve.h"
21 #include "core/common/ace_application_info.h"
22 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
23 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/pattern/image/image_layout_property.h"
26 #include "core/components_ng/pattern/image/image_render_property.h"
27 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
28 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
29 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
30 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
31 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
32 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
33 #include "core/components_ng/pattern/navigation/title_bar_node.h"
34 #include "core/components_ng/pattern/text/text_layout_property.h"
35 #include "core/components_ng/pattern/text/text_pattern.h"
36 #include "core/components_v2/inspector/inspector_constants.h"
37 #include "core/components_v2/inspector/utils.h"
38
39 namespace OHOS::Ace::NG {
40 namespace {
41 constexpr int32_t DEFAULT_ANIMATION_DURATION = 200;
42 constexpr int32_t TITLE_RATIO = 2;
43
TextLayoutPropertyToString(const RefPtr<TextLayoutProperty> & property)44 std::string TextLayoutPropertyToString(const RefPtr<TextLayoutProperty>& property)
45 {
46 CHECK_NULL_RETURN(property, "");
47 std::stringstream ss;
48 auto fontSize = property->GetFontSize();
49 ss << "FontSize: " << (fontSize.has_value() ? fontSize.value().ToString() : "NA") << ", ";
50
51 auto adaptMinFontSize = property->GetAdaptMinFontSize();
52 ss << "AdaptMinFontSize: " << (adaptMinFontSize.has_value() ? adaptMinFontSize.value().ToString() : "NA") << ", ";
53
54 auto adaptMaxFontSize = property->GetAdaptMaxFontSize();
55 ss << "AdaptMaxFontSize: " << (adaptMaxFontSize.has_value() ? adaptMaxFontSize.value().ToString() : "NA") << ", ";
56
57 auto heightAdaptivePolicy = property->GetHeightAdaptivePolicy();
58 ss << "TextHeightAdaptivePolicy: " << (heightAdaptivePolicy.has_value() ?
59 V2::ConvertWrapTextHeightAdaptivePolicyToString(heightAdaptivePolicy.value()) : "NA") << ", ";
60
61 auto textColor = property->GetTextColor();
62 ss << "TextColor: " << (textColor.has_value() ? textColor.value().ToString() : "NA") << ", ";
63
64 auto fontWeight = property->GetFontWeight();
65 ss << "fontWeight: " << (fontWeight.has_value() ?
66 V2::ConvertWrapFontWeightToStirng(fontWeight.value()) :"NA") << ", ";
67
68 auto textShadow = property->GetTextShadow();
69 ss << "TextShadow: " << (textShadow.has_value() ? "hasValue" : "NA") << ", ";
70
71 auto maxLines = property->GetMaxLines();
72 ss << "MaxLines: " << (maxLines.has_value() ? std::to_string(maxLines.value()) : "NA");
73
74 return ss.str();
75 }
76
DumpTitleProperty(const RefPtr<TextLayoutProperty> & property,bool isMainTitle)77 void DumpTitleProperty(const RefPtr<TextLayoutProperty>& property, bool isMainTitle)
78 {
79 std::string info;
80 if (isMainTitle) {
81 info.append("MainTitle: ");
82 } else {
83 info.append("SubTitle: ");
84 }
85 info.append(TextLayoutPropertyToString(property));
86 DumpLog::GetInstance().AddDesc(info);
87 }
88
SetTextColor(const RefPtr<FrameNode> & textNode,const Color & color)89 void SetTextColor(const RefPtr<FrameNode>& textNode, const Color& color)
90 {
91 CHECK_NULL_VOID(textNode);
92 auto textPattern = textNode->GetPattern<TextPattern>();
93 CHECK_NULL_VOID(textPattern);
94 auto property = textNode->GetLayoutPropertyPtr<TextLayoutProperty>();
95 CHECK_NULL_VOID(property);
96 property->UpdateTextColor(color);
97 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, color, textNode);
98 ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, ForegroundColorStrategy, textNode);
99 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, textNode);
100 }
101
SetImageSourceInfoFillColor(ImageSourceInfo & imageSourceInfo)102 void SetImageSourceInfoFillColor(ImageSourceInfo& imageSourceInfo)
103 {
104 auto theme = NavigationGetTheme();
105 if (theme) {
106 imageSourceInfo.SetFillColor(theme->GetIconColor());
107 }
108 }
109
SetBackButtonImgAboveVersionTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)110 void SetBackButtonImgAboveVersionTen(const RefPtr<FrameNode>& backButtonNode,
111 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
112 RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
113 {
114 // API >= 10
115 if (!backButtonNode || !titleBarLayoutProperty || !backButtonImageLayoutProperty) {
116 return;
117 }
118 if (titleBarLayoutProperty->HasPixelMap() && titleBarLayoutProperty->GetPixelMapValue() != nullptr) {
119 auto pixelMap = titleBarLayoutProperty->GetPixelMapValue();
120 ImageSourceInfo imageSourceInfo = ImageSourceInfo(pixelMap);
121 SetImageSourceInfoFillColor(imageSourceInfo);
122 backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
123 backButtonNode->MarkModifyDone();
124 return;
125 }
126
127 ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
128 SetImageSourceInfoFillColor(imageSourceInfo);
129 backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
130 backButtonNode->MarkModifyDone();
131 }
132
SetBackButtonImgBelowVersionTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)133 void SetBackButtonImgBelowVersionTen(const RefPtr<FrameNode>& backButtonNode,
134 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
135 RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
136 {
137 // API < 10
138 if (!backButtonNode || !titleBarLayoutProperty || !backButtonImageLayoutProperty) {
139 return;
140 }
141 ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
142 SetImageSourceInfoFillColor(imageSourceInfo);
143 backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
144 backButtonNode->MarkModifyDone();
145 }
146
HandleDefaultIconForNavDestination(const RefPtr<TitleBarNode> & hostNode,const RefPtr<FrameNode> & backButtonImageNode)147 void HandleDefaultIconForNavDestination(
148 const RefPtr<TitleBarNode>& hostNode, const RefPtr<FrameNode>& backButtonImageNode)
149 {
150 auto navDestinationNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
151 CHECK_NULL_VOID(navDestinationNode);
152 auto theme = NavigationGetTheme();
153 CHECK_NULL_VOID(theme);
154 auto navDestinationEventHub = navDestinationNode->GetEventHub<EventHub>();
155 CHECK_NULL_VOID(navDestinationEventHub);
156 auto paintProperty = backButtonImageNode->GetPaintProperty<ImageRenderProperty>();
157 CHECK_NULL_VOID(paintProperty);
158 // If use defalut icon, need to set fill-color
159 if (!navDestinationEventHub->IsEnabled()) {
160 paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor().BlendOpacity(theme->GetAlphaDisabled()));
161 } else {
162 paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor());
163 }
164 backButtonImageNode->MarkModifyDone();
165 }
166
IsImageBackIcon(const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)167 bool IsImageBackIcon(const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
168 {
169 CHECK_NULL_RETURN(titleBarLayoutProperty, false);
170 if (titleBarLayoutProperty->HasIsValidImage() && titleBarLayoutProperty->GetIsValidImageValue()) {
171 return true;
172 }
173
174 return false;
175 }
176
ApplyImageSourceInfo(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)177 void ApplyImageSourceInfo(const RefPtr<FrameNode>& backButtonNode,
178 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
179 RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
180 {
181 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
182 SetBackButtonImgBelowVersionTen(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
183 } else {
184 SetBackButtonImgAboveVersionTen(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
185 }
186 }
187
ApplyThemeIconSize(RefPtr<TextLayoutProperty> & symbolProperty)188 void ApplyThemeIconSize(RefPtr<TextLayoutProperty>& symbolProperty)
189 {
190 CHECK_NULL_VOID(symbolProperty);
191 auto theme = NavigationGetTheme();
192 if (theme) {
193 symbolProperty->UpdateFontSize(theme->GetIconWidth());
194 }
195 }
196
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)197 void UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
198 {
199 CHECK_NULL_VOID(symbolProperty);
200 auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
201 symbolEffectOptions.SetIsTxtActive(isActive);
202 symbolEffectOptions.SetIsTxtActiveSource(0);
203 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
204 }
205
UpdateSymbolBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)206 void UpdateSymbolBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode,
207 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
208 {
209 auto theme = NavigationGetTheme();
210 auto backIconSymbol = titleBarLayoutProperty->GetBackIconSymbol();
211 if (backIconSymbol != nullptr) {
212 // symbol -> symbol
213 auto symbolProperty = backButtonIconNode->GetLayoutProperty<TextLayoutProperty>();
214 CHECK_NULL_VOID(symbolProperty);
215 symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
216 if (theme) {
217 symbolProperty->UpdateSymbolColorList({ theme->GetIconColor() });
218 }
219 // User-defined color overrides the default color of the theme
220 backIconSymbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(backButtonIconNode)));
221 ApplyThemeIconSize(symbolProperty);
222 UpdateSymbolEffect(symbolProperty, false);
223 backButtonIconNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
224 } else if (IsImageBackIcon(titleBarLayoutProperty)) {
225 // symbol -> image
226 auto backButtonImageNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_IMAGE_ETS_TAG,
227 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
228 CHECK_NULL_VOID(backButtonImageNode);
229
230 auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
231 CHECK_NULL_VOID(backButtonImageLayoutProperty);
232 backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
233 ApplyImageSourceInfo(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
234 backButtonImageNode->MountToParent(backButtonNode);
235 backButtonNode->RemoveChild(backButtonIconNode);
236 backButtonImageNode->MarkModifyDone();
237 } else {
238 auto symbolProperty = backButtonIconNode->GetLayoutProperty<TextLayoutProperty>();
239 CHECK_NULL_VOID(symbolProperty);
240 symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetBackSymbolId()));
241 symbolProperty->UpdateSymbolColorList({ theme->GetBackButtonIconColor() });
242 if (theme) {
243 symbolProperty->UpdateFontSize(theme->GetIconWidth());
244 }
245 backButtonIconNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
246 }
247 }
248
CreateDefaultBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode)249 void CreateDefaultBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode)
250 {
251 auto theme = NavigationGetTheme();
252 CHECK_NULL_VOID(theme);
253 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
254 backButtonNode->RemoveChild(backButtonIconNode);
255 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
256 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
257 CHECK_NULL_VOID(symbolNode);
258 auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
259 CHECK_NULL_VOID(symbolProperty);
260 symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
261 auto iconColor = theme->GetIconColor();
262 symbolProperty->UpdateSymbolColorList({ iconColor });
263 symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetBackSymbolId()));
264 symbolProperty->UpdateFontSize(theme->GetIconWidth());
265 symbolNode->MountToParent(backButtonNode);
266 symbolNode->MarkDirtyNode();
267 symbolNode->MarkModifyDone();
268 } else {
269 auto backButtonImageLayoutProperty = backButtonIconNode->GetLayoutProperty<ImageLayoutProperty>();
270 CHECK_NULL_VOID(backButtonImageLayoutProperty);
271
272 ImageSourceInfo imageSourceInfo;
273 auto iconColor = theme->GetBackButtonIconColor();
274 auto backResourceId = theme->GetBackResourceId();
275
276 imageSourceInfo.SetResourceId(backResourceId);
277 imageSourceInfo.SetFillColor(iconColor);
278 backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
279 backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
280 backButtonIconNode->MarkModifyDone();
281 }
282 }
283
UpdateImageBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)284 void UpdateImageBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode,
285 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
286 {
287 auto backIconSymbol = titleBarLayoutProperty->GetBackIconSymbol();
288 auto theme = NavigationGetTheme();
289 if (backIconSymbol != nullptr) {
290 // image -> symbol
291 backButtonNode->RemoveChild(backButtonIconNode);
292 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
293 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
294 CHECK_NULL_VOID(symbolNode);
295 auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
296 CHECK_NULL_VOID(symbolProperty);
297 symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
298 if (theme) {
299 symbolProperty->UpdateSymbolColorList({ theme->GetIconColor() });
300 }
301 backIconSymbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(symbolNode)));
302 ApplyThemeIconSize(symbolProperty);
303 UpdateSymbolEffect(symbolProperty, false);
304 symbolNode->MountToParent(backButtonNode);
305 symbolNode->MarkDirtyNode();
306 symbolNode->MarkModifyDone();
307 } else if (IsImageBackIcon(titleBarLayoutProperty)) {
308 // image -> image
309 auto backButtonImageNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_IMAGE_ETS_TAG,
310 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
311 CHECK_NULL_VOID(backButtonImageNode);
312 ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
313 auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
314 CHECK_NULL_VOID(backButtonImageLayoutProperty);
315 backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
316 ApplyImageSourceInfo(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
317 backButtonImageNode->MountToParent(backButtonNode);
318 backButtonNode->RemoveChild(backButtonIconNode);
319 backButtonImageNode->MarkModifyDone();
320 } else {
321 CreateDefaultBackButton(backButtonNode, backButtonIconNode);
322 }
323 }
324
MountBackButton(const RefPtr<TitleBarNode> & hostNode)325 void MountBackButton(const RefPtr<TitleBarNode>& hostNode)
326 {
327 auto theme = NavigationGetTheme();
328 CHECK_NULL_VOID(theme);
329 auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
330 CHECK_NULL_VOID(titleBarLayoutProperty);
331 auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
332 CHECK_NULL_VOID(backButtonNode);
333 auto backButtonIconNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetChildren().front());
334 CHECK_NULL_VOID(backButtonIconNode);
335 auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
336 if (backButtonIconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
337 UpdateSymbolBackButton(backButtonNode, backButtonIconNode, titleBarLayoutProperty);
338 } else {
339 UpdateImageBackButton(backButtonNode, backButtonIconNode, titleBarLayoutProperty);
340 }
341 std::string parentId = hostNode->GetInnerParentId();
342 if (parentType == TitleBarParentType::NAVBAR) {
343 auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
344 CHECK_NULL_VOID(navBarNode);
345 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
346 CHECK_NULL_VOID(navBarLayoutProperty);
347 auto hideBackButton = navBarLayoutProperty->GetHideBackButtonValue(false);
348 auto backButtonLayoutProperty = AceType::DynamicCast<FrameNode>(backButtonNode)->GetLayoutProperty();
349 CHECK_NULL_VOID(backButtonLayoutProperty);
350 backButtonLayoutProperty->UpdateVisibility(hideBackButton ? VisibleType::GONE : VisibleType::VISIBLE);
351 backButtonNode->SetJSViewActive(hideBackButton ? false : true);
352
353 // set navigation titleBar backButton inspectorId
354 NavigationTitleUtil::SetInnerChildId(backButtonNode, NG::NAV_FIELD,
355 backButtonNode->GetTag(), "Back", parentId);
356 backButtonNode->MarkModifyDone();
357 return;
358 }
359
360 // set navdestination titleBar backButton inspectorId
361 NavigationTitleUtil::SetInnerChildId(backButtonNode, NG::DES_FIELD,
362 backButtonNode->GetTag(), "Back", parentId);
363 if (!titleBarLayoutProperty->HasNoPixMap()) {
364 if (parentType == TitleBarParentType::NAV_DESTINATION) {
365 HandleDefaultIconForNavDestination(hostNode, backButtonIconNode);
366 }
367 backButtonNode->MarkModifyDone();
368 return;
369 }
370 }
371 } // namespace
372
MountSubTitle(const RefPtr<TitleBarNode> & hostNode)373 void TitleBarPattern::MountSubTitle(const RefPtr<TitleBarNode>& hostNode)
374 {
375 CHECK_NULL_VOID(hostNode);
376 auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
377 CHECK_NULL_VOID(titleBarLayoutProperty);
378 auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
379 CHECK_NULL_VOID(subtitleNode);
380
381 // set titleBar subTitle inspectorId
382 auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
383 std::string parentId = hostNode->GetInnerParentId();
384 std::string field = NG::NAV_FIELD;
385 if (parentType == TitleBarParentType::NAV_DESTINATION) {
386 field = NG::DES_FIELD;
387 }
388 NavigationTitleUtil::SetInnerChildId(subtitleNode, field, subtitleNode->GetTag(), "SubTitle", parentId);
389
390 if (options_.textOptions.subTitleApplyFunc || shouldResetSubTitleProperty_) {
391 auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
392 ResetSubTitleProperty(subtitleNode, titleMode, parentType == TitleBarParentType::NAV_DESTINATION);
393 shouldResetSubTitleProperty_ = false;
394 }
395
396 subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
397 subtitleNode->MarkModifyDone();
398 }
399
InitTitleParam()400 void TitleBarPattern::InitTitleParam()
401 {
402 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
403 CHECK_NULL_VOID(titleBarNode);
404 if (titleBarNode->GetSubtitle()) {
405 tempTitleBarHeight_.SetValue(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.Value());
406 } else {
407 tempTitleBarHeight_.SetValue(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.Value());
408 }
409 overDragOffset_ = 0.0f;
410 tempTitleOffsetY_ = 0.0f;
411 fontSize_.reset();
412 opacity_.reset();
413 isFreeTitleUpdated_ = false;
414 auto theme = NavigationGetTheme();
415 CHECK_NULL_VOID(theme);
416 titleSpaceVertical_ = theme->GetTitleSpaceVertical();
417 }
418
IsHidden()419 bool TitleBarPattern::IsHidden()
420 {
421 auto host = GetHost();
422 auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
423 CHECK_NULL_RETURN(navBarNode, false);
424 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
425 CHECK_NULL_RETURN(navBarLayoutProperty, false);
426 return navBarLayoutProperty->GetHideTitleBar().value_or(false);
427 }
428
UpdateNavBarTitleProperty(const RefPtr<TitleBarNode> & hostNode)429 void TitleBarPattern::UpdateNavBarTitleProperty(const RefPtr<TitleBarNode>& hostNode)
430 {
431 auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
432 CHECK_NULL_VOID(titleNode);
433 auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetParent());
434 CHECK_NULL_VOID(navBarNode);
435 auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
436 CHECK_NULL_VOID(titleBarLayoutProperty);
437
438 // if title node is custom node markModifyDone and return
439 if (navBarNode->GetPrevTitleIsCustomValue(false)) {
440 titleNode->MarkModifyDone();
441 return;
442 }
443
444 // set navbar titleBar main title inspectorId
445 std::string parentId = hostNode->GetInnerParentId();
446 NavigationTitleUtil::SetInnerChildId(titleNode, NG::NAV_FIELD, titleNode->GetTag(), "MainTitle", parentId);
447
448 // update main title layout property
449 if (options_.textOptions.mainTitleApplyFunc || shouldResetMainTitleProperty_) {
450 auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
451 ResetMainTitleProperty(titleNode, titleBarLayoutProperty, titleMode, hostNode->GetSubtitle() != nullptr, false);
452 shouldResetMainTitleProperty_ = false;
453 }
454
455 titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
456 titleNode->MarkModifyDone();
457 }
458
UpdateNavDesTitleProperty(const RefPtr<TitleBarNode> & hostNode)459 void TitleBarPattern::UpdateNavDesTitleProperty(const RefPtr<TitleBarNode>& hostNode)
460 {
461 auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
462 CHECK_NULL_VOID(titleBarLayoutProperty);
463 auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(hostNode->GetParent());
464 CHECK_NULL_VOID(navDestinationGroupNode);
465 auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
466 CHECK_NULL_VOID(titleNode);
467
468 // if navdestination titleBar main title is custom, just return
469 if (navDestinationGroupNode->GetPrevTitleIsCustomValue(false)) {
470 titleNode->MarkModifyDone();
471 return;
472 }
473 // if navdestination titleBar main title is not custom, set inspectorId
474 std::string parentId = hostNode->GetInnerParentId();
475 NavigationTitleUtil::SetInnerChildId(titleNode, NG::DES_FIELD, titleNode->GetTag(),
476 "MainTitle", parentId);
477
478 if (options_.textOptions.mainTitleApplyFunc || shouldResetMainTitleProperty_) {
479 auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
480 ResetMainTitleProperty(titleNode, titleBarLayoutProperty, titleMode, hostNode->GetSubtitle() != nullptr, true);
481 shouldResetMainTitleProperty_ = false;
482 }
483
484 titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
485 titleNode->MarkModifyDone();
486 }
487
ResetMainTitleProperty(const RefPtr<FrameNode> & textNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,NavigationTitleMode titleMode,bool hasSubTitle,bool parentIsNavDest)488 void TitleBarPattern::ResetMainTitleProperty(const RefPtr<FrameNode>& textNode,
489 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
490 NavigationTitleMode titleMode, bool hasSubTitle, bool parentIsNavDest)
491 {
492 // update main title layout property
493 auto titleLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
494 CHECK_NULL_VOID(titleLayoutProperty);
495
496 std::string contentStr;
497 if (titleLayoutProperty->HasContent()) {
498 contentStr = titleLayoutProperty->GetContentValue(std::string());
499 }
500 titleLayoutProperty->Reset();
501 titleLayoutProperty->UpdateContent(contentStr);
502
503 auto theme = NavigationGetTheme();
504 CHECK_NULL_VOID(theme);
505 auto titleFontSize = theme->GetTitleFontSizeBig();
506 auto maxFontSize = theme->GetTitleFontSizeBig();
507 auto miniTitleFontSize = theme->GetTitleFontSize();
508 auto miniTitleFontSizeMin = theme->GetTitleFontSizeMin();
509 auto textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
510 Color color = theme->GetTitleColor();
511 FontWeight mainTitleWeight = FontWeight::MEDIUM;
512 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
513 titleFontSize = theme->GetMainTitleFontSizeL();
514 maxFontSize = theme->GetMainTitleFontSizeL();
515 miniTitleFontSize = theme->GetMainTitleFontSizeM();
516 miniTitleFontSizeMin = theme->GetMainTitleFontSizeS();
517 textHeightAdaptivePolicy = hasSubTitle ? TextHeightAdaptivePolicy::MAX_LINES_FIRST :
518 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
519 color = theme->GetMainTitleFontColor();
520 mainTitleWeight = FontWeight::BOLD;
521 }
522 SetTextColor(textNode, color);
523 titleLayoutProperty->UpdateFontWeight(mainTitleWeight);
524 titleLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
525 titleLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
526 auto maxLines = hasSubTitle ? 1 : TITLEBAR_MAX_LINES;
527 titleLayoutProperty->UpdateMaxLines(maxLines);
528 titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_TITLE_FONT_SIZE);
529
530 if (!parentIsNavDest) {
531 titleLayoutProperty->UpdateHeightAdaptivePolicy(textHeightAdaptivePolicy);
532 }
533
534 if (parentIsNavDest) {
535 titleLayoutProperty->ResetFontSize();
536 titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSizeMin);
537 titleLayoutProperty->UpdateHeightAdaptivePolicy(hasSubTitle ? TextHeightAdaptivePolicy::MAX_LINES_FIRST :
538 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
539 } else if (titleMode == NavigationTitleMode::MINI) {
540 if (titleBarLayoutProperty->HasHideBackButton() && titleBarLayoutProperty->GetHideBackButtonValue()) {
541 titleLayoutProperty->UpdateFontSize(miniTitleFontSize);
542 titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSize);
543 } else {
544 titleLayoutProperty->UpdateFontSize(miniTitleFontSizeMin);
545 titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSizeMin);
546 }
547 UpdateSubTitleOpacity(1.0);
548 } else if (titleMode == NavigationTitleMode::FULL) {
549 titleLayoutProperty->UpdateFontSize(titleFontSize);
550 titleLayoutProperty->UpdateAdaptMaxFontSize(maxFontSize);
551 UpdateSubTitleOpacity(1.0);
552 } else {
553 if (fontSize_.has_value()) {
554 titleLayoutProperty->UpdateFontSize(fontSize_.value());
555 titleLayoutProperty->UpdateAdaptMaxFontSize(fontSize_.value());
556 } else {
557 titleLayoutProperty->UpdateFontSize(titleFontSize);
558 titleLayoutProperty->UpdateAdaptMaxFontSize(maxFontSize);
559 }
560 if (opacity_.has_value()) {
561 UpdateSubTitleOpacity(opacity_.value());
562 } else {
563 UpdateSubTitleOpacity(1.0);
564 }
565 }
566 }
567
ResetSubTitleProperty(const RefPtr<FrameNode> & textNode,NavigationTitleMode titleMode,bool parentIsNavDest)568 void TitleBarPattern::ResetSubTitleProperty(const RefPtr<FrameNode>& textNode,
569 NavigationTitleMode titleMode, bool parentIsNavDest)
570 {
571 CHECK_NULL_VOID(textNode);
572 auto titleLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
573 CHECK_NULL_VOID(titleLayoutProperty);
574 std::string contentStr;
575 if (titleLayoutProperty->HasContent()) {
576 contentStr = titleLayoutProperty->GetContentValue(std::string());
577 }
578 titleLayoutProperty->Reset();
579 titleLayoutProperty->UpdateContent(contentStr);
580
581 auto theme = NavigationGetTheme();
582 CHECK_NULL_VOID(theme);
583 auto subTitleSize = theme->GetSubTitleFontSize();
584 Color color = theme->GetSubTitleColor();
585 auto textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
586 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
587 subTitleSize = theme->GetSubTitleFontSizeS();
588 color = theme->GetSubTitleFontColor();
589 textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MAX_LINES_FIRST;
590 }
591 if (parentIsNavDest) {
592 titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MAX_LINES_FIRST);
593 } else if (titleMode == NavigationTitleMode::MINI) {
594 titleLayoutProperty->UpdateHeightAdaptivePolicy(textHeightAdaptivePolicy);
595 } else if (titleMode == NavigationTitleMode::FREE) {
596 UpdateSubTitleOpacity(opacity_.value_or(1.0f));
597 } else {
598 UpdateSubTitleOpacity(1.0);
599 }
600 titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_SUBTITLE_FONT_SIZE);
601 titleLayoutProperty->UpdateAdaptMaxFontSize(subTitleSize);
602 titleLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
603 titleLayoutProperty->UpdateMaxLines(1);
604 titleLayoutProperty->UpdateFontWeight(FontWeight::REGULAR); // ohos_id_text_font_family_regular
605 titleLayoutProperty->UpdateFontSize(subTitleSize);
606 titleLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
607 SetTextColor(textNode, color);
608 }
609
MountTitle(const RefPtr<TitleBarNode> & hostNode)610 void TitleBarPattern::MountTitle(const RefPtr<TitleBarNode>& hostNode)
611 {
612 CHECK_NULL_VOID(hostNode);
613 UpdateNavDesTitleProperty(hostNode);
614 UpdateNavBarTitleProperty(hostNode);
615 }
616
OnModifyDone()617 void TitleBarPattern::OnModifyDone()
618 {
619 Pattern::OnModifyDone();
620 if (isInitialTitle_) {
621 InitTitleParam();
622 }
623 auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
624 CHECK_NULL_VOID(hostNode);
625 MountBackButton(hostNode);
626 MountTitle(hostNode);
627 MountSubTitle(hostNode);
628 ApplyTitleModifierIfNeeded(hostNode);
629 auto pipeline = hostNode->GetContext();
630 CHECK_NULL_VOID(pipeline);
631 if (GreatOrEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
632 auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
633 CHECK_NULL_VOID(backButtonNode);
634 InitBackButtonLongPressEvent(backButtonNode);
635 }
636 auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
637 CHECK_NULL_VOID(titleBarLayoutProperty);
638 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
639 isInitialTitle_ || !isTitleChanged_) {
640 return;
641 }
642 isTitleChanged_ = false;
643 if (NearEqual(GetTempTitleBarHeight(), static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) ||
644 NearEqual(GetTempTitleBarHeight(), static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()))) {
645 tempTitleBarHeight_.SetValue(hostNode->GetSubtitle() ? FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.Value()
646 : FULL_SINGLE_LINE_TITLEBAR_HEIGHT.Value());
647 }
648 }
649
ApplyTitleModifierIfNeeded(const RefPtr<TitleBarNode> & hostNode)650 void TitleBarPattern::ApplyTitleModifierIfNeeded(const RefPtr<TitleBarNode>& hostNode)
651 {
652 isFontSizeSettedByDeveloper_ = false;
653 CHECK_NULL_VOID(hostNode);
654 auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
655 if (options_.textOptions.mainTitleApplyFunc && titleNode) {
656 ApplyTitleModifier(titleNode, options_.textOptions.mainTitleApplyFunc, true);
657 }
658 auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
659 if (options_.textOptions.subTitleApplyFunc && subtitleNode) {
660 ApplyTitleModifier(subtitleNode, options_.textOptions.subTitleApplyFunc, false);
661 }
662 }
663
ApplyTitleModifier(const RefPtr<FrameNode> & textNode,const TextStyleApplyFunc & applyFunc,bool needCheckFontSizeIsSetted)664 void TitleBarPattern::ApplyTitleModifier(const RefPtr<FrameNode>& textNode,
665 const TextStyleApplyFunc& applyFunc, bool needCheckFontSizeIsSetted)
666 {
667 CHECK_NULL_VOID(textNode);
668 CHECK_NULL_VOID(applyFunc);
669 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
670 CHECK_NULL_VOID(textLayoutProperty);
671
672 std::optional<Dimension> backupFontSize;
673 std::optional<Dimension> backupMaxFontSize;
674 std::optional<Dimension> backupMinFontSize;
675 if (textLayoutProperty->HasFontSize()) {
676 backupFontSize = textLayoutProperty->GetFontSizeValue(Dimension());
677 }
678 if (textLayoutProperty->HasAdaptMaxFontSize()) {
679 backupMaxFontSize = textLayoutProperty->GetAdaptMaxFontSizeValue(Dimension());
680 }
681 if (textLayoutProperty->HasAdaptMinFontSize()) {
682 backupMinFontSize = textLayoutProperty->GetAdaptMinFontSizeValue(Dimension());
683 }
684 textLayoutProperty->ResetFontSize();
685 textLayoutProperty->ResetAdaptMaxFontSize();
686 textLayoutProperty->ResetAdaptMinFontSize();
687 applyFunc(AceType::WeakClaim(AceType::RawPtr(textNode)));
688
689 if (!textLayoutProperty->HasFontSize() &&
690 !textLayoutProperty->HasAdaptMinFontSize() &&
691 !textLayoutProperty->HasAdaptMaxFontSize()) {
692 // restore
693 if (backupFontSize.has_value()) {
694 textLayoutProperty->UpdateFontSize(backupFontSize.value());
695 }
696 if (backupMaxFontSize.has_value()) {
697 textLayoutProperty->UpdateAdaptMaxFontSize(backupMaxFontSize.value());
698 }
699 if (backupMinFontSize.has_value()) {
700 textLayoutProperty->UpdateAdaptMinFontSize(backupMinFontSize.value());
701 }
702 } else {
703 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "modifier set %{public}s, %{public}s, %{public}s",
704 textLayoutProperty->HasFontSize() ? "FontSize" : "",
705 textLayoutProperty->HasAdaptMinFontSize() ? "AdaptMinFontSize" : "",
706 textLayoutProperty->HasAdaptMaxFontSize() ? "AdaptMaxFontSize" : "");
707 if (needCheckFontSizeIsSetted) {
708 isFontSizeSettedByDeveloper_ = true;
709 }
710 }
711
712 textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
713 textNode->MarkModifyDone();
714 }
715
ProcessTitleDragUpdate(float offset)716 void TitleBarPattern::ProcessTitleDragUpdate(float offset)
717 {
718 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
719 CHECK_NULL_VOID(titleBarNode);
720 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
721 CHECK_NULL_VOID(titleBarLayoutProperty);
722 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
723 IsHidden()) {
724 return;
725 }
726 SetTempTitleBarHeight(offset);
727 titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
728 SetTempTitleOffsetY();
729 SetTempSubTitleOffsetY();
730 titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
731
732 // title font size
733 auto mappedOffset = GetMappedOffset(offset);
734 fontSize_ = GetFontSize(mappedOffset);
735 UpdateTitleFontSize(fontSize_.value());
736
737 // subTitle Opacity
738 opacity_ = GetSubtitleOpacity();
739 UpdateSubTitleOpacity(opacity_.value());
740 }
741
GetSubtitleOpacity()742 float TitleBarPattern::GetSubtitleOpacity()
743 {
744 auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
745 opacityRatio_ = 1.0f / titleBarHeightDiff;
746 auto tempOpacity = static_cast<float>((GetTempTitleBarHeight() -
747 static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * opacityRatio_ + 0.0f);
748 return tempOpacity;
749 }
750
GetFontSize(float offset)751 Dimension TitleBarPattern::GetFontSize(float offset)
752 {
753 auto titleBarHeight = defaultTitleBarHeight_ + offset;
754 auto theme = NavigationGetTheme();
755 CHECK_NULL_RETURN(theme, Dimension(0.0f, DimensionUnit::FP));
756 Dimension titleL = theme->GetTitleFontSizeBig();
757 Dimension titleM = theme->GetTitleFontSize();
758 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
759 titleL = theme->GetMainTitleFontSizeL();
760 titleM = theme->GetMainTitleFontSizeM();
761 }
762 auto titleFontSizeDiff = titleL - titleM;
763 auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
764 if (!NearZero(titleBarHeightDiff)) {
765 fontSizeRatio_ = titleFontSizeDiff.Value() / titleBarHeightDiff;
766 }
767 auto tempFontSize = titleM.Value() +
768 (titleBarHeight - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * fontSizeRatio_;
769 if (GreatNotEqual(tempFontSize, titleL.Value())) {
770 tempFontSize = titleL.Value();
771 }
772 if (LessNotEqual(tempFontSize, titleM.Value())) {
773 tempFontSize = titleM.Value();
774 }
775 return Dimension(tempFontSize, DimensionUnit::FP);
776 }
777
GetMappedOffset(float offset)778 float TitleBarPattern::GetMappedOffset(float offset)
779 {
780 auto titleOffset = offset + defaultTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
781 auto heightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
782 float moveRatio = Curves::SHARP->MoveInternal(std::clamp(titleOffset / heightDiff, 0.0f, 1.0f));
783 auto mappedTitleOffset = moveRatio * heightDiff;
784 auto mappedOffset =
785 mappedTitleOffset - defaultTitleBarHeight_ + static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
786 return mappedOffset;
787 }
788
SpringAnimation(float startPos,float endPos)789 void TitleBarPattern::SpringAnimation(float startPos, float endPos)
790 {
791 auto host = GetHost();
792 CHECK_NULL_VOID(host);
793 SetOverDragOffset(overDragOffset_);
794 SetTempTitleBarHeightVp(maxTitleBarHeight_ + overDragOffset_ / 6.0f);
795 UpdateScaleByDragOverDragOffset(overDragOffset_);
796 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
797 auto pipeline = PipelineContext::GetCurrentContext();
798 if (pipeline) {
799 pipeline->FlushUITasks();
800 }
801
802 constexpr float velocity = 0.0f;
803 constexpr float mass = 1.0f; // The move animation spring curve mass is 1.0f
804 constexpr float stiffness = 228.0f; // The move animation spring curve stiffness is 228.0f
805 constexpr float damping = 30.0f; // The move animation spring curve damping is 30.0f
806 auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(velocity, mass, stiffness, damping);
807 AnimationOption option;
808 option.SetCurve(springCurve);
809
810 springAnimation_ = AnimationUtils::StartAnimation(
811 option,
812 [weakPattern = AceType::WeakClaim(this)]() {
813 auto pattern = weakPattern.Upgrade();
814 CHECK_NULL_VOID(pattern);
815 auto host = pattern->GetHost();
816 CHECK_NULL_VOID(host);
817 pattern->SetOverDragOffset(0.0f);
818 pattern->SetTempTitleBarHeightVp(pattern->GetMaxTitleBarHeight());
819 pattern->UpdateScaleByDragOverDragOffset(0.0f);
820 pattern->tempTitleOffsetY_ = 0.0f;
821 pattern->isFreeTitleUpdated_ = false;
822 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
823 auto pipeline = PipelineContext::GetCurrentContext();
824 if (pipeline) {
825 pipeline->FlushUITasks();
826 }
827 }, [weakPattern = AceType::WeakClaim(this)]() {
828 auto pattern = weakPattern.Upgrade();
829 CHECK_NULL_VOID(pattern);
830 pattern->CleanSpringAnimation();
831 });
832 }
833
ClearDragState()834 void TitleBarPattern::ClearDragState()
835 {
836 overDragOffset_ = 0.0f;
837 }
838
UpdateScaleByDragOverDragOffset(float overDragOffset)839 void TitleBarPattern::UpdateScaleByDragOverDragOffset(float overDragOffset)
840 {
841 if (Negative(overDragOffset)) {
842 return;
843 }
844 auto host = GetHost();
845 auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
846 CHECK_NULL_VOID(navBarNode);
847 if (navBarNode->GetPrevTitleIsCustomValue(true)) {
848 return;
849 }
850 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
851 CHECK_NULL_VOID(titleBarNode);
852 auto titleNode = titleBarNode->GetTitle();
853 CHECK_NULL_VOID(titleNode);
854 auto title = AceType::DynamicCast<FrameNode>(titleNode);
855 TransformScale(overDragOffset, title);
856 auto subtitleNode = titleBarNode->GetSubtitle();
857 if (subtitleNode) {
858 auto subtitle = AceType::DynamicCast<FrameNode>(subtitleNode);
859 TransformScale(overDragOffset, subtitle);
860 }
861
862 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
863 }
864
TransformScale(float overDragOffset,const RefPtr<FrameNode> & frameNode)865 void TitleBarPattern::TransformScale(float overDragOffset, const RefPtr<FrameNode>& frameNode)
866 {
867 CHECK_NULL_VOID(frameNode);
868 auto renderCtx = frameNode->GetRenderContext();
869 CHECK_NULL_VOID(renderCtx);
870 auto offset = std::clamp(overDragOffset, 0.0f, static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx()));
871 auto scaleRatio = offset / static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx());
872 VectorF scaleValue = VectorF(scaleRatio * 0.1f + 1.0f, scaleRatio * 0.1f + 1.0f);
873 renderCtx->UpdateTransformScale(scaleValue);
874 }
875
AnimateTo(float offset,bool isFullTitleMode)876 void TitleBarPattern::AnimateTo(float offset, bool isFullTitleMode)
877 {
878 AnimationOption option;
879 option.SetCurve(Curves::FAST_OUT_SLOW_IN);
880 option.SetDuration(DEFAULT_ANIMATION_DURATION);
881
882 animation_ = AnimationUtils::StartAnimation(
883 option,
884 [weakPattern = AceType::WeakClaim(this), offset, isFullTitleMode]() {
885 auto pattern = weakPattern.Upgrade();
886 CHECK_NULL_VOID(pattern);
887 auto host = pattern->GetHost();
888 CHECK_NULL_VOID(host);
889 pattern->ProcessTitleDragUpdate(offset);
890 if (isFullTitleMode) {
891 pattern->tempTitleOffsetY_ = 0.0f;
892 pattern->isFreeTitleUpdated_ = false;
893 }
894 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
895 auto pipeline = PipelineContext::GetCurrentContext();
896 if (pipeline) {
897 pipeline->FlushUITasks();
898 }
899 }, [weakPattern = AceType::WeakClaim(this)]() {
900 auto pattern = weakPattern.Upgrade();
901 CHECK_NULL_VOID(pattern);
902 pattern->CleanAnimation();
903 });
904 }
905
SetMaxTitleBarHeight()906 void TitleBarPattern::SetMaxTitleBarHeight()
907 {
908 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
909 CHECK_NULL_VOID(titleBarNode);
910 if (titleBarNode->GetSubtitle()) {
911 maxTitleBarHeight_ = static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
912 } else {
913 maxTitleBarHeight_ = static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
914 }
915 }
916
SetTempTitleBarHeight(float offsetY)917 void TitleBarPattern::SetTempTitleBarHeight(float offsetY)
918 {
919 auto tmepTitleBarHeight = defaultTitleBarHeight_ + offsetY;
920 if (tmepTitleBarHeight < static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) {
921 tmepTitleBarHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
922 }
923 if (tmepTitleBarHeight > maxTitleBarHeight_) {
924 tmepTitleBarHeight = maxTitleBarHeight_;
925 }
926 SetTempTitleBarHeightVp(tmepTitleBarHeight);
927 }
928
SetTempTitleOffsetY()929 void TitleBarPattern::SetTempTitleOffsetY()
930 {
931 tempTitleOffsetY_ = defaultTitleOffsetY_ + titleMoveDistance_;
932 if (tempTitleOffsetY_ < minTitleOffsetY_) {
933 tempTitleOffsetY_ = minTitleOffsetY_;
934 }
935 if (tempTitleOffsetY_ > maxTitleOffsetY_) {
936 tempTitleOffsetY_ = maxTitleOffsetY_;
937 }
938 }
939
SetTempSubTitleOffsetY()940 void TitleBarPattern::SetTempSubTitleOffsetY()
941 {
942 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
943 tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight() +
944 static_cast<float>(titleSpaceVertical_.ConvertToPx());
945 } else {
946 tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight();
947 }
948 if (tempTitleOffsetY_ < minTitleOffsetY_) {
949 tempSubTitleOffsetY_ = minTitleOffsetY_;
950 }
951 if (tempTitleOffsetY_ > maxTitleOffsetY_) {
952 tempSubTitleOffsetY_ = maxTitleOffsetY_;
953 }
954 }
955
SetDefaultTitleFontSize()956 void TitleBarPattern::SetDefaultTitleFontSize()
957 {
958 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
959 CHECK_NULL_VOID(titleBarNode);
960 CHECK_NULL_VOID(titleBarNode->GetTitle());
961 auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
962 CHECK_NULL_VOID(titleNode);
963 auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
964 CHECK_NULL_VOID(textLayoutProperty);
965 auto theme = NavigationGetTheme();
966 CHECK_NULL_VOID(theme);
967 defaultTitleFontSize_ = theme->GetTitleFontSize();
968 }
969
SetDefaultSubtitleOpacity()970 void TitleBarPattern::SetDefaultSubtitleOpacity()
971 {
972 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
973 CHECK_NULL_VOID(titleBarNode);
974 CHECK_NULL_VOID(titleBarNode->GetSubtitle());
975 auto subtitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
976 CHECK_NULL_VOID(subtitleNode);
977 auto context = subtitleNode->GetRenderContext();
978 CHECK_NULL_VOID(context);
979 if (defaultTitleBarHeight_ == maxTitleBarHeight_) {
980 defaultSubtitleOpacity_ = context->GetOpacityValue(1.0f);
981 } else {
982 defaultSubtitleOpacity_ = context->GetOpacityValue(0.0f);
983 }
984 }
985
GetTitleHeight()986 float TitleBarPattern::GetTitleHeight()
987 {
988 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
989 CHECK_NULL_RETURN(titleBarNode, 0.0f);
990 auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
991 CHECK_NULL_RETURN(titleNode, 0.0f);
992 auto geometryNode = titleNode->GetGeometryNode();
993 CHECK_NULL_RETURN(geometryNode, 0.0f);
994 return geometryNode->GetFrameSize().Height();
995 }
996
GetSubTitleOffsetY()997 float TitleBarPattern::GetSubTitleOffsetY()
998 {
999 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1000 CHECK_NULL_RETURN(titleBarNode, 0.0f);
1001 auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
1002 CHECK_NULL_RETURN(subTitleNode, 0.0f);
1003 auto geometryNode = subTitleNode->GetGeometryNode();
1004 CHECK_NULL_RETURN(geometryNode, 0.0f);
1005 return geometryNode->GetMarginFrameOffset().GetY();
1006 }
1007
UpdateTitleFontSize(const Dimension & tempTitleFontSize)1008 void TitleBarPattern::UpdateTitleFontSize(const Dimension& tempTitleFontSize)
1009 {
1010 if (isFontSizeSettedByDeveloper_) {
1011 return;
1012 }
1013 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1014 CHECK_NULL_VOID(titleBarNode);
1015 auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
1016 CHECK_NULL_VOID(titleNode);
1017 auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
1018 CHECK_NULL_VOID(textLayoutProperty);
1019 textLayoutProperty->UpdateFontSize(tempTitleFontSize);
1020 textLayoutProperty->UpdateAdaptMaxFontSize(tempTitleFontSize);
1021 titleNode->MarkModifyDone();
1022 }
1023
UpdateSubTitleOpacity(const double & value)1024 void TitleBarPattern::UpdateSubTitleOpacity(const double& value)
1025 {
1026 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1027 CHECK_NULL_VOID(titleBarNode);
1028 auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
1029 CHECK_NULL_VOID(subTitleNode);
1030 auto context = subTitleNode->GetRenderContext();
1031 CHECK_NULL_VOID(context);
1032 context->UpdateOpacity(value);
1033 }
1034
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1035 bool TitleBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1036 {
1037 if (config.skipMeasure && config.skipLayout) {
1038 return false;
1039 }
1040 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1041 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
1042 auto titleBarLayoutAlgorithm = DynamicCast<TitleBarLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
1043 CHECK_NULL_RETURN(titleBarLayoutAlgorithm, false);
1044 UpdateTitleModeChange();
1045
1046 initialTitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialTitleOffsetY();
1047 isInitialTitle_ = titleBarLayoutAlgorithm->IsInitialTitle();
1048 initialSubtitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialSubtitleOffsetY();
1049 isInitialSubtitle_ = titleBarLayoutAlgorithm->IsInitialSubtitle();
1050 minTitleHeight_ = titleBarLayoutAlgorithm->GetMinTitleHeight();
1051 return true;
1052 }
1053
UpdateTitleModeChange()1054 void TitleBarPattern::UpdateTitleModeChange()
1055 {
1056 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1057 CHECK_NULL_VOID(titleBarNode);
1058 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1059 CHECK_NULL_VOID(titleBarLayoutProperty);
1060 auto geometryNode = titleBarNode->GetGeometryNode();
1061 CHECK_NULL_VOID(geometryNode);
1062
1063 auto titleBarHeight = geometryNode->GetFrameSize().Height();
1064 if ((titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) &&
1065 !NearZero(maxTitleBarHeight_)) {
1066 if (titleBarHeight >= maxTitleBarHeight_) {
1067 titleMode_ = NavigationTitleMode::FULL;
1068 } else if (NearEqual(titleBarHeight, static_cast<float>(TITLEBAR_HEIGHT_MINI.ConvertToPx()))) {
1069 titleMode_ = NavigationTitleMode::MINI;
1070 }
1071 }
1072 }
1073
OnAttachToFrameNode()1074 void TitleBarPattern::OnAttachToFrameNode()
1075 {
1076 auto host = GetHost();
1077 CHECK_NULL_VOID(host);
1078 host->GetRenderContext()->SetClipToFrame(true);
1079
1080 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1081 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
1082 .edges = SAFE_AREA_EDGE_TOP };
1083 host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
1084 }
1085 auto pipelineContext = PipelineContext::GetCurrentContext();
1086 CHECK_NULL_VOID(pipelineContext);
1087
1088 auto halfFoldHoverCallbackId = pipelineContext->RegisterHalfFoldHoverChangedCallback(
1089 [weakHost = WeakPtr<FrameNode>(host)](bool isHalfFoldHover) {
1090 auto host = weakHost.Upgrade();
1091 CHECK_NULL_VOID(host);
1092 NavigationTitleUtil::FoldStatusChangedAnimation(host);
1093 });
1094 UpdateHalfFoldHoverChangedCallbackId(halfFoldHoverCallbackId);
1095 }
1096
InitFoldCreaseRegion()1097 void TitleBarPattern::InitFoldCreaseRegion()
1098 {
1099 auto container = Container::Current();
1100 CHECK_NULL_VOID(container);
1101 auto displayInfo = container->GetDisplayInfo();
1102 CHECK_NULL_VOID(displayInfo);
1103 currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
1104 }
1105
OnCoordScrollStart()1106 void TitleBarPattern::OnCoordScrollStart()
1107 {
1108 coordScrollOffset_ = 0.0f;
1109 coordScrollFinalOffset_ = 0.0f;
1110 isFreeTitleUpdated_ = true;
1111
1112 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1113 CHECK_NULL_VOID(titleBarNode);
1114 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1115 CHECK_NULL_VOID(titleBarLayoutProperty);
1116 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1117 return;
1118 }
1119 if (springAnimation_) {
1120 AnimationUtils::StopAnimation(springAnimation_);
1121 springAnimation_.reset();
1122 }
1123 if (animation_) {
1124 AnimationUtils::StopAnimation(animation_);
1125 animation_.reset();
1126 }
1127
1128 defaultTitleBarHeight_ = currentTitleBarHeight_;
1129 defaultTitleOffsetY_ = currentTitleOffsetY_;
1130 SetMaxTitleBarHeight();
1131 SetTempTitleBarHeight(0);
1132 minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2.0f;
1133 maxTitleOffsetY_ = initialTitleOffsetY_;
1134 moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
1135 (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
1136 titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
1137 }
1138
OnCoordScrollUpdate(float offset)1139 float TitleBarPattern::OnCoordScrollUpdate(float offset)
1140 {
1141 float lastOffset = coordScrollOffset_;
1142 coordScrollOffset_ += offset;
1143
1144 float offsetHandled = 0.0f;
1145 float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1146 float titleBarOffset = coordScrollOffset_;
1147 if (LessNotEqual(defaultTitleBarHeight_ + titleBarOffset, minHeight)) {
1148 // The target height is smaller than the minHeight, so the titleBarOffset is adjusted to modify the height to
1149 // the minHeight.
1150 titleBarOffset = minHeight - defaultTitleBarHeight_;
1151 overDragOffset_ = 0.0f;
1152 offsetHandled = CalculateHandledOffsetMinTitle(offset, lastOffset);
1153 } else if (GreatNotEqual(defaultTitleBarHeight_ + titleBarOffset, maxTitleBarHeight_)) {
1154 // The target height is greater than the maxTitleBarHeight_, so overDragOffset_ needs to be updated.
1155 overDragOffset_ = defaultTitleBarHeight_ + titleBarOffset - maxTitleBarHeight_;
1156 offsetHandled = CalculateHandledOffsetMaxTitle(offset, lastOffset);
1157 } else {
1158 // The target height is between the minHeight and the maxTitleBarHeight_.
1159 overDragOffset_ = 0.0f;
1160 offsetHandled = CalculateHandledOffsetBetweenMinAndMaxTitle(offset, lastOffset);
1161 }
1162 UpdateTitleBarByCoordScroll(titleBarOffset);
1163 coordScrollFinalOffset_ = titleBarOffset;
1164 auto barStyle = options_.brOptions.barStyle.value_or(BarStyle::STANDARD);
1165 if (barStyle == BarStyle::STACK) {
1166 offsetHandled = 0.0f;
1167 }
1168
1169 return offsetHandled;
1170 }
1171
OnCoordScrollEnd()1172 void TitleBarPattern::OnCoordScrollEnd()
1173 {
1174 if (NearZero(coordScrollOffset_)) {
1175 return;
1176 }
1177 float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1178 float middleHeight =
1179 (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) + maxTitleBarHeight_) / TITLE_RATIO;
1180 float finalHeight = defaultTitleBarHeight_ + coordScrollFinalOffset_;
1181 if (GreatNotEqual(finalHeight, minHeight) && LessOrEqual(finalHeight, middleHeight)) {
1182 // The finalHeight is between the minHeight and the middleHeight, so animate to min title.
1183 AnimateTo(static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - defaultTitleBarHeight_);
1184 return;
1185 }
1186 if (GreatNotEqual(finalHeight, middleHeight) && LessNotEqual(finalHeight, maxTitleBarHeight_)) {
1187 // The finalHeight is between the middleHeight and the maxTitleBarHeight_, so animate to max title.
1188 AnimateTo(maxTitleBarHeight_ - defaultTitleBarHeight_, true);
1189 return;
1190 }
1191 if (GreatNotEqual(finalHeight, maxTitleBarHeight_)) {
1192 // The finalHeight is bigger than the maxTitleBarHeight_, so animate to max title.
1193 SpringAnimation(finalHeight - maxTitleBarHeight_, 0);
1194 }
1195 }
1196
UpdateTitleBarByCoordScroll(float offset)1197 void TitleBarPattern::UpdateTitleBarByCoordScroll(float offset)
1198 {
1199 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1200 CHECK_NULL_VOID(titleBarNode);
1201 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1202 CHECK_NULL_VOID(titleBarLayoutProperty);
1203 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1204 return;
1205 }
1206 SetTitleStyleByCoordScrollOffset(offset);
1207 UpdateScaleByDragOverDragOffset(overDragOffset_);
1208 }
1209
SetTitleStyleByCoordScrollOffset(float offset)1210 void TitleBarPattern::SetTitleStyleByCoordScrollOffset(float offset)
1211 {
1212 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1213 CHECK_NULL_VOID(titleBarNode);
1214 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1215 CHECK_NULL_VOID(titleBarLayoutProperty);
1216 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1217 return;
1218 }
1219 if (Positive(overDragOffset_)) {
1220 SetTempTitleBarHeightVp(maxTitleBarHeight_ + overDragOffset_ / 6.0f);
1221 titleMoveDistance_ = (maxTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_ + overDragOffset_ / 6.0f;
1222 } else {
1223 SetTempTitleBarHeight(offset);
1224 titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
1225 }
1226
1227 SetTempTitleOffsetY();
1228 SetTempSubTitleOffsetY();
1229 titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1230
1231 // title font size
1232 auto mappedOffset = GetMappedOffset(offset);
1233 fontSize_ = GetFontSize(mappedOffset);
1234 UpdateTitleFontSize(fontSize_.value());
1235
1236 // subTitle Opacity
1237 opacity_ = GetSubtitleOpacity();
1238 UpdateSubTitleOpacity(opacity_.value());
1239 }
1240
OnColorConfigurationUpdate()1241 void TitleBarPattern::OnColorConfigurationUpdate()
1242 {
1243 auto host = GetHost();
1244 CHECK_NULL_VOID(host);
1245 UpdateBackgroundStyle(host);
1246 SetNeedResetMainTitleProperty(true);
1247 SetNeedResetSubTitleProperty(true);
1248
1249 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(host);
1250 CHECK_NULL_VOID(titleBarNode);
1251 auto backButton = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
1252 CHECK_NULL_VOID(backButton);
1253 if (backButton->GetTag() == "Navigator") {
1254 backButton = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
1255 CHECK_NULL_VOID(backButton);
1256 }
1257 auto theme = NavigationGetTheme();
1258 CHECK_NULL_VOID(theme);
1259 auto iconColor = theme->GetBackButtonIconColor();
1260 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1261 iconColor = theme->GetIconColor();
1262 auto backButtonColor = theme->GetCompBackgroundColor();
1263 auto renderContext = backButton->GetRenderContext();
1264 auto backButtonPattern = backButton->GetPattern<ButtonPattern>();
1265 backButtonPattern->setComponentButtonType(ComponentButtonType::NAVIGATION);
1266 backButtonPattern->SetBlendColor(theme->GetBackgroundPressedColor(), theme->GetBackgroundHoverColor());
1267 backButtonPattern->SetFocusBorderColor(theme->GetBackgroundFocusOutlineColor());
1268 backButtonPattern->SetFocusBorderWidth(theme->GetBackgroundFocusOutlineWeight());
1269 renderContext->UpdateBackgroundColor(backButtonColor);
1270 backButton->MarkModifyDone();
1271 }
1272 auto backButtonImgNode = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
1273 CHECK_NULL_VOID(backButtonImgNode);
1274 if (backButtonImgNode->GetTag() == V2::IMAGE_ETS_TAG) {
1275 auto backButtonImgRender = backButtonImgNode->GetPaintProperty<ImageRenderProperty>();
1276 CHECK_NULL_VOID(backButtonImgRender);
1277 backButtonImgRender->UpdateSvgFillColor(iconColor);
1278 }
1279 backButtonImgNode->MarkModifyDone();
1280 }
1281
CalculateHandledOffsetMinTitle(float offset,float lastCordScrollOffset)1282 float TitleBarPattern::CalculateHandledOffsetMinTitle(float offset, float lastCordScrollOffset)
1283 {
1284 float offsetHandled = 0.0f;
1285 float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1286 if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1287 // The starting height of this update is smaller than the minHeight, so the navigation component does
1288 // not handle the offset.
1289 offsetHandled = 0.0f;
1290 } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1291 // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
1292 // component only handles offsets from maxTitleBarHeight_ to minHeight.
1293 offsetHandled = minHeight - maxTitleBarHeight_;
1294 } else {
1295 // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1296 // navigation component only handles offsets from defaultTitleBarHeight_ to minHeight.
1297 offsetHandled = offset - (coordScrollOffset_ - (minHeight - defaultTitleBarHeight_));
1298 }
1299 return offsetHandled;
1300 }
1301
CalculateHandledOffsetMaxTitle(float offset,float lastCordScrollOffset)1302 float TitleBarPattern::CalculateHandledOffsetMaxTitle(float offset, float lastCordScrollOffset)
1303 {
1304 float offsetHandled = 0.0f;
1305 float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1306 if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1307 // The starting height of this update is greater than the maxTitleBarHeight_, so the navigation component
1308 // does not handle the offset.
1309 offsetHandled = 0.0f;
1310 } else if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1311 // The starting position height of this update is smaller than the minHeight, so the navigation component
1312 // only handles offsets from minHeight to maxTitleBarHeight_.
1313 offsetHandled = maxTitleBarHeight_ - minHeight;
1314 } else {
1315 // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1316 // navigation component only handles offsets from defaultTitleBarHeight_ to maxTitleBarHeight_.
1317 offsetHandled = offset - (coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_));
1318 }
1319 return offsetHandled;
1320 }
1321
CalculateHandledOffsetBetweenMinAndMaxTitle(float offset,float lastCordScrollOffset)1322 float TitleBarPattern::CalculateHandledOffsetBetweenMinAndMaxTitle(float offset, float lastCordScrollOffset)
1323 {
1324 float offsetHandled = 0.0f;
1325 float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1326 if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1327 // The starting height of this update is smaller than the minHeight, so the navigation component only
1328 // handles offsets from minHeight to target height.
1329 offsetHandled = defaultTitleBarHeight_ + coordScrollOffset_ - minHeight;
1330 } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1331 // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
1332 // component only handles offsets from maxTitleBarHeight_ to target height.
1333 offsetHandled = coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_);
1334 } else {
1335 // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1336 // navigation component handles all of the offset.
1337 offsetHandled = offset;
1338 }
1339 return offsetHandled;
1340 }
1341
SetTitlebarOptions(NavigationTitlebarOptions && opt)1342 void TitleBarPattern::SetTitlebarOptions(NavigationTitlebarOptions&& opt)
1343 {
1344 bool needUpdateBgOptions = options_.bgOptions != opt.bgOptions;
1345 if (options_.textOptions.mainTitleApplyFunc && !opt.textOptions.mainTitleApplyFunc) {
1346 shouldResetMainTitleProperty_ = true;
1347 }
1348 if (options_.textOptions.subTitleApplyFunc && !opt.textOptions.subTitleApplyFunc) {
1349 shouldResetSubTitleProperty_ = true;
1350 }
1351 options_ = std::move(opt);
1352 if (!needUpdateBgOptions) {
1353 return;
1354 }
1355
1356 auto host = GetHost();
1357 CHECK_NULL_VOID(host);
1358 UpdateBackgroundStyle(host);
1359 }
1360
UpdateBackgroundStyle(RefPtr<FrameNode> & host)1361 void TitleBarPattern::UpdateBackgroundStyle(RefPtr<FrameNode>& host)
1362 {
1363 auto renderContext = host->GetRenderContext();
1364 CHECK_NULL_VOID(renderContext);
1365 if (options_.bgOptions.color.has_value()) {
1366 renderContext->UpdateBackgroundColor(options_.bgOptions.color.value());
1367 } else {
1368 renderContext->ResetBackgroundColor();
1369 }
1370 if (options_.bgOptions.blurStyle.has_value()) {
1371 BlurStyleOption blur;
1372 blur.blurStyle = options_.bgOptions.blurStyle.value();
1373 renderContext->UpdateBackBlurStyle(blur);
1374 } else {
1375 renderContext->ResetBackBlurStyle();
1376 }
1377 }
1378
OnDetachFromFrameNode(FrameNode * frameNode)1379 void TitleBarPattern::OnDetachFromFrameNode(FrameNode* frameNode)
1380 {
1381 CHECK_NULL_VOID(frameNode);
1382 auto pipeline = PipelineContext::GetCurrentContext();
1383 CHECK_NULL_VOID(pipeline);
1384
1385 if (HasHalfFoldHoverChangedCallbackId()) {
1386 pipeline->UnRegisterHalfFoldHoverChangedCallback(halfFoldHoverChangedCallbackId_.value());
1387 }
1388 }
1389
DumpInfo()1390 void TitleBarPattern::DumpInfo()
1391 {
1392 auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1393 CHECK_NULL_VOID(hostNode);
1394 auto mainTitle = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
1395 if (mainTitle) {
1396 auto property = mainTitle->GetLayoutProperty<TextLayoutProperty>();
1397 if (property) {
1398 DumpTitleProperty(property, true);
1399 }
1400 }
1401
1402 auto subTitle = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
1403 if (subTitle) {
1404 auto property = subTitle->GetLayoutProperty<TextLayoutProperty>();
1405 if (property) {
1406 DumpTitleProperty(property, false);
1407 }
1408 }
1409 }
1410
GetTitleBarHeightLessThanMaxBarHeight() const1411 float TitleBarPattern::GetTitleBarHeightLessThanMaxBarHeight() const
1412 {
1413 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1414 CHECK_NULL_RETURN(titleBarNode, 0.f);
1415 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1416 CHECK_NULL_RETURN(titleBarLayoutProperty, 0.f);
1417 auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
1418 if (titleMode != NavigationTitleMode::FREE) {
1419 return 0.f;
1420 }
1421 auto barStyle = options_.brOptions.barStyle.value_or(BarStyle::STANDARD);
1422 if (barStyle != BarStyle::STACK) {
1423 return 0.f;
1424 }
1425 return maxTitleBarHeight_ - currentTitleBarHeight_;
1426 }
1427
HandleLongPress(const RefPtr<FrameNode> & backButtonNode)1428 void TitleBarPattern::HandleLongPress(const RefPtr<FrameNode>& backButtonNode)
1429 {
1430 auto accessibilityProperty = backButtonNode->GetAccessibilityProperty<AccessibilityProperty>();
1431 CHECK_NULL_VOID(accessibilityProperty);
1432 auto message = accessibilityProperty->GetAccessibilityText();
1433 if (dialogNode_ != nullptr) {
1434 HandleLongPressActionEnd();
1435 }
1436
1437 auto backButtonIconNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetFirstChild());
1438 CHECK_NULL_VOID(backButtonIconNode);
1439 if (backButtonIconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
1440 dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(message, backButtonIconNode);
1441 return;
1442 }
1443 auto imageProperty = backButtonIconNode->GetLayoutProperty<ImageLayoutProperty>();
1444 CHECK_NULL_VOID(imageProperty);
1445 ImageSourceInfo imageSourceInfo = imageProperty->GetImageSourceInfoValue();
1446 dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo);
1447 }
1448
HandleLongPressActionEnd()1449 void TitleBarPattern::HandleLongPressActionEnd()
1450 {
1451 CHECK_NULL_VOID(dialogNode_);
1452 auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1453 CHECK_NULL_VOID(hostNode);
1454 auto pipeline = hostNode->GetContext();
1455 CHECK_NULL_VOID(pipeline);
1456 auto overlayManager = pipeline->GetOverlayManager();
1457 CHECK_NULL_VOID(overlayManager);
1458 overlayManager->CloseDialog(dialogNode_);
1459 dialogNode_ = nullptr;
1460 }
1461
InitBackButtonLongPressEvent(const RefPtr<FrameNode> & backButtonNode)1462 void TitleBarPattern::InitBackButtonLongPressEvent(const RefPtr<FrameNode>& backButtonNode)
1463 {
1464 auto gestureHub = backButtonNode->GetOrCreateGestureEventHub();
1465 CHECK_NULL_VOID(gestureHub);
1466
1467 auto longPressCallback = [weak = WeakClaim(this), weakNode = WeakClaim(RawPtr(backButtonNode))]
1468 (GestureEvent& info) {
1469 auto pattern = weak.Upgrade();
1470 CHECK_NULL_VOID(pattern);
1471 auto backButtonNode = weakNode.Upgrade();
1472 CHECK_NULL_VOID(backButtonNode);
1473 pattern->HandleLongPress(backButtonNode);
1474 };
1475 longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
1476 gestureHub->SetLongPressEvent(longPressEvent_);
1477
1478 auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
1479 CHECK_NULL_VOID(longPressRecognizer);
1480
1481 auto longPressEndCallback = [weak = WeakClaim(this)](GestureEvent& info) {
1482 auto pattern = weak.Upgrade();
1483 CHECK_NULL_VOID(pattern);
1484 pattern->HandleLongPressActionEnd();
1485 };
1486 longPressRecognizer->SetOnActionEnd(longPressEndCallback);
1487 }
1488
OnFontScaleConfigurationUpdate()1489 void TitleBarPattern::OnFontScaleConfigurationUpdate()
1490 {
1491 auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1492 CHECK_NULL_VOID(hostNode);
1493 auto pipeline = hostNode->GetContext();
1494 CHECK_NULL_VOID(pipeline);
1495 auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
1496 CHECK_NULL_VOID(backButtonNode);
1497 if (LessNotEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
1498 auto gestureHub = backButtonNode->GetOrCreateGestureEventHub();
1499 CHECK_NULL_VOID(gestureHub);
1500 gestureHub->SetLongPressEvent(nullptr);
1501 auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
1502 CHECK_NULL_VOID(longPressRecognizer);
1503 longPressRecognizer->SetOnActionEnd(nullptr);
1504 return;
1505 }
1506 InitBackButtonLongPressEvent(backButtonNode);
1507 }
1508 } // namespace OHOS::Ace::NG
1509