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