• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/navigation/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