• 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 "core/animation/spring_curve.h"
19 #include "core/common/container.h"
20 #include "core/components_ng/pattern/image/image_layout_property.h"
21 #include "core/components_ng/pattern/image/image_render_property.h"
22 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
23 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
24 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
25 #include "core/components_ng/pattern/navigation/title_bar_node.h"
26 #include "core/components_ng/pattern/text/text_layout_property.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28 
29 namespace OHOS::Ace::NG {
30 
31 namespace {
32 constexpr int32_t DEFAULT_ANIMATION_DURATION = 200;
33 constexpr int32_t TITLE_RATIO = 2;
34 
HandlePlatformVersionAboveTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)35 void HandlePlatformVersionAboveTen(
36     const RefPtr<FrameNode>& backButtonNode, const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
37 {
38     // API >= 10
39     auto backButtonImageNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetChildren().front());
40     CHECK_NULL_VOID(backButtonImageNode);
41     RefPtr<ImageLayoutProperty> backButtonImageLayoutProperty =
42         backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
43     CHECK_NULL_VOID(backButtonImageLayoutProperty);
44 
45     bool noPixelMap = titleBarLayoutProperty->GetNoPixMapValue();
46     if (noPixelMap && titleBarLayoutProperty->HasImageSource()) {
47         backButtonImageLayoutProperty->UpdateImageSourceInfo(titleBarLayoutProperty->GetImageSourceValue());
48         backButtonImageNode->MarkModifyDone();
49         return;
50     }
51 
52     if (!noPixelMap &&  titleBarLayoutProperty->HasPixelMap()) {
53         auto pixelMap = titleBarLayoutProperty->GetPixelMapValue();
54         backButtonImageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
55         backButtonImageNode->MarkModifyDone();
56     }
57 }
58 
HandlePlatformVersionBelowTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)59 void HandlePlatformVersionBelowTen(
60     const RefPtr<FrameNode>& backButtonNode, const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
61 {
62     // API < 10
63     RefPtr<ImageLayoutProperty> backButtonImageLayoutProperty =
64         backButtonNode->GetLayoutProperty<ImageLayoutProperty>();
65     CHECK_NULL_VOID(backButtonImageLayoutProperty);
66     if (titleBarLayoutProperty->HasImageSource()) {
67         backButtonImageLayoutProperty->UpdateImageSourceInfo(titleBarLayoutProperty->GetImageSourceValue());
68         backButtonNode->MarkModifyDone();
69     }
70 }
71 
HandleDefaultIconForNavDestination(const RefPtr<TitleBarNode> & hostNode,const RefPtr<FrameNode> & backButtonImageNode)72 void HandleDefaultIconForNavDestination(
73     const RefPtr<TitleBarNode>& hostNode, const RefPtr<FrameNode>& backButtonImageNode)
74 {
75     auto navDestinationNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
76     CHECK_NULL_VOID(navDestinationNode);
77     auto theme = NavigationGetTheme();
78     CHECK_NULL_VOID(theme);
79     auto navDestinationEventHub = navDestinationNode->GetEventHub<EventHub>();
80     CHECK_NULL_VOID(navDestinationEventHub);
81     auto paintProperty = backButtonImageNode->GetPaintProperty<ImageRenderProperty>();
82     CHECK_NULL_VOID(paintProperty);
83     // If use defalut icon, need to set fill-color
84     if (!navDestinationEventHub->IsEnabled()) {
85         paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor().BlendOpacity(theme->GetAlphaDisabled()));
86     } else {
87         paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor());
88     }
89     backButtonImageNode->MarkModifyDone();
90 }
91 
MountBackButton(const RefPtr<TitleBarNode> & hostNode)92 void MountBackButton(const RefPtr<TitleBarNode>& hostNode)
93 {
94     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
95     CHECK_NULL_VOID(titleBarLayoutProperty);
96     auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
97     CHECK_NULL_VOID(backButtonNode);
98     auto backButtonImageNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetChildren().front());
99     CHECK_NULL_VOID(backButtonImageNode);
100     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
101     if (parentType == TitleBarParentType::NAVBAR) {
102         auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
103         CHECK_NULL_VOID(backButtonImageLayoutProperty);
104 
105         if (titleBarLayoutProperty->HasNoPixMap()) {
106             bool noPixelMap = titleBarLayoutProperty->GetNoPixMapValue();
107             if (noPixelMap && titleBarLayoutProperty->HasImageSource()) {
108                 backButtonImageLayoutProperty->UpdateImageSourceInfo(titleBarLayoutProperty->GetImageSourceValue());
109             }
110             if (!noPixelMap && titleBarLayoutProperty->HasPixelMap()) {
111                 auto pixelMap = titleBarLayoutProperty->GetPixelMapValue();
112                 backButtonImageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
113                 backButtonImageNode->MarkModifyDone();
114             }
115         }
116 
117         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
118         CHECK_NULL_VOID(navBarNode);
119         auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
120         CHECK_NULL_VOID(navBarLayoutProperty);
121         auto hideBackButton = navBarLayoutProperty->GetHideBackButtonValue(false);
122         auto backButtonLayoutProperty = AceType::DynamicCast<FrameNode>(backButtonNode)->GetLayoutProperty();
123         CHECK_NULL_VOID(backButtonLayoutProperty);
124         backButtonLayoutProperty->UpdateVisibility(hideBackButton ? VisibleType::GONE : VisibleType::VISIBLE);
125         backButtonNode->SetJSViewActive(hideBackButton ? false : true);
126         backButtonImageNode->MarkModifyDone();
127         return;
128     }
129 
130     if (!titleBarLayoutProperty->HasNoPixMap()) {
131         if (parentType == TitleBarParentType::NAV_DESTINATION) {
132             HandleDefaultIconForNavDestination(hostNode, backButtonImageNode);
133         }
134         backButtonNode->MarkModifyDone();
135         return;
136     }
137     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
138         HandlePlatformVersionBelowTen(backButtonNode, titleBarLayoutProperty);
139     } else {
140         HandlePlatformVersionAboveTen(backButtonNode, titleBarLayoutProperty);
141     }
142 }
143 
MountSubTitle(const RefPtr<TitleBarNode> & hostNode)144 void MountSubTitle(const RefPtr<TitleBarNode>& hostNode)
145 {
146     CHECK_NULL_VOID(hostNode);
147     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
148     CHECK_NULL_VOID(titleBarLayoutProperty);
149     auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
150     CHECK_NULL_VOID(subtitleNode);
151     auto titleLayoutProperty = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
152     CHECK_NULL_VOID(titleLayoutProperty);
153 
154     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
155         auto theme = NavigationGetTheme();
156         CHECK_NULL_VOID(theme);
157         titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_SUBTITLE_FONT_SIZE);
158         titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetSubTitleFontSize());
159         titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
160     }
161 
162     subtitleNode->MarkModifyDone();
163 }
164 
165 } // namespace
166 
InitTitleParam()167 void TitleBarPattern::InitTitleParam()
168 {
169     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
170     CHECK_NULL_VOID(titleBarNode);
171     if (titleBarNode->GetSubtitle()) {
172         tempTitleBarHeight_ = static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
173     } else {
174         tempTitleBarHeight_ = static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
175     }
176     overDragOffset_ = 0.0f;
177     tempTitleOffsetY_ = 0.0f;
178     fontSize_.reset();
179     opacity_.reset();
180     isFreeTitleUpdated_ = false;
181 }
182 
IsHidden()183 bool TitleBarPattern::IsHidden()
184 {
185     auto host = GetHost();
186     auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
187     CHECK_NULL_RETURN(navBarNode, false);
188     auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
189     CHECK_NULL_RETURN(navBarLayoutProperty, false);
190     return navBarLayoutProperty->GetHideTitleBar().value_or(false);
191 }
192 
MountTitle(const RefPtr<TitleBarNode> & hostNode)193 void TitleBarPattern::MountTitle(const RefPtr<TitleBarNode>& hostNode)
194 {
195     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
196     CHECK_NULL_VOID(titleBarLayoutProperty);
197     auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
198     CHECK_NULL_VOID(titleNode);
199     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetParent());
200     CHECK_NULL_VOID(navBarNode);
201     // if title node is custom node markModifyDone and return
202     if (navBarNode->GetPrevTitleIsCustomValue(false)) {
203         titleNode->MarkModifyDone();
204         return;
205     }
206 
207     auto titleLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
208     CHECK_NULL_VOID(titleLayoutProperty);
209 
210     auto theme = NavigationGetTheme();
211     CHECK_NULL_VOID(theme);
212     auto currentFontSize = titleLayoutProperty->GetFontSizeValue(Dimension(0));
213     auto currentMaxLine = titleLayoutProperty->GetMaxLinesValue(0);
214     auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
215     if (titleMode == NavigationTitleMode::MINI) {
216         if (titleBarLayoutProperty->HasHideBackButton() && titleBarLayoutProperty->GetHideBackButtonValue()) {
217             titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSize());
218             titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSize());
219         } else {
220             titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeMin());
221             titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSizeMin());
222         }
223         UpdateSubTitleOpacity(1.0);
224     } else if (titleMode == NavigationTitleMode::FULL) {
225         titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
226         titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSizeBig());
227         UpdateSubTitleOpacity(1.0);
228     } else {
229         if (fontSize_.has_value()) {
230             titleLayoutProperty->UpdateFontSize(Dimension(fontSize_.value(), DimensionUnit::PX));
231             titleLayoutProperty->UpdateAdaptMaxFontSize(Dimension(fontSize_.value(), DimensionUnit::PX));
232         } else {
233             titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
234             titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSizeBig());
235         }
236         if (opacity_.has_value()) {
237             UpdateSubTitleOpacity(opacity_.value());
238         } else {
239             UpdateSubTitleOpacity(1.0);
240         }
241     }
242 
243     titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_TITLE_FONT_SIZE);
244     titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
245     auto maxLines = hostNode->GetSubtitle() ? 1 : TITLEBAR_MAX_LINES;
246     titleLayoutProperty->UpdateMaxLines(maxLines);
247     if (currentFontSize != titleLayoutProperty->GetFontSizeValue(Dimension(0)) ||
248         currentMaxLine != titleLayoutProperty->GetMaxLinesValue(0)) {
249         titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
250     }
251     titleNode->MarkModifyDone();
252 }
253 
OnModifyDone()254 void TitleBarPattern::OnModifyDone()
255 {
256     Pattern::OnModifyDone();
257     if (isInitialTitle_) {
258         InitTitleParam();
259     }
260     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
261     CHECK_NULL_VOID(hostNode);
262     MountBackButton(hostNode);
263     MountTitle(hostNode);
264     MountSubTitle(hostNode);
265 }
266 
ProcessTitleDragStart(float offset)267 void TitleBarPattern::ProcessTitleDragStart(float offset)
268 {
269     if (Positive(overDragOffset_)) {
270         return;
271     }
272     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
273     CHECK_NULL_VOID(titleBarNode);
274     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
275     CHECK_NULL_VOID(titleBarLayoutProperty);
276     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
277         IsHidden()) {
278         return;
279     }
280     if (springController_ && !springController_->IsStopped()) {
281         // clear stop listener before stop
282         springController_->ClearStopListeners();
283         springController_->Stop();
284     }
285     if (animator_ && !animator_->IsStopped()) {
286         animator_->Stop();
287     }
288 
289     defaultTitleBarHeight_ = currentTitleBarHeight_;
290     SetMaxTitleBarHeight();
291     SetTempTitleBarHeight(offset);
292     minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2.0f;
293     maxTitleOffsetY_ = initialTitleOffsetY_;
294     moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
295                  (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
296     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
297     defaultTitleOffsetY_ = currentTitleOffsetY_;
298     SetTempTitleOffsetY();
299     defaultSubtitleOffsetY_ = GetSubTitleOffsetY();
300     SetTempSubTitleOffsetY();
301     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
302 
303     // title font size
304     SetDefaultTitleFontSize();
305     auto mappedOffset = GetMappedOffset(offset);
306     auto tempFontSize = GetFontSize(mappedOffset);
307     UpdateTitleFontSize(Dimension(tempFontSize, DimensionUnit::PX));
308 
309     // subTitle Opacity
310     SetDefaultSubtitleOpacity();
311     auto tempOpacity = GetSubtitleOpacity();
312     UpdateSubTitleOpacity(tempOpacity);
313 
314     isFreeTitleUpdated_ = true;
315 }
316 
ProcessTitleDragUpdate(float offset)317 void TitleBarPattern::ProcessTitleDragUpdate(float offset)
318 {
319     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
320     CHECK_NULL_VOID(titleBarNode);
321     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
322     CHECK_NULL_VOID(titleBarLayoutProperty);
323     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
324         IsHidden()) {
325         return;
326     }
327     SetTempTitleBarHeight(offset);
328     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
329     SetTempTitleOffsetY();
330     SetTempSubTitleOffsetY();
331     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
332 
333     // title font size
334     auto mappedOffset = GetMappedOffset(offset);
335     fontSize_ = GetFontSize(mappedOffset);
336     UpdateTitleFontSize(Dimension(fontSize_.value(), DimensionUnit::PX));
337 
338     // subTitle Opacity
339     opacity_ = GetSubtitleOpacity();
340     UpdateSubTitleOpacity(opacity_.value());
341 }
342 
ProcessTitleDragEnd()343 void TitleBarPattern::ProcessTitleDragEnd()
344 {
345     if (Positive(overDragOffset_)) {
346         return;
347     }
348     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
349     CHECK_NULL_VOID(titleBarNode);
350     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
351     CHECK_NULL_VOID(titleBarLayoutProperty);
352     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
353         IsHidden()) {
354         return;
355     }
356 
357     if (Positive(overDragOffset_)) {
358         SpringAnimation(overDragOffset_, 0);
359     }
360     if (CanOverDrag_ || isTitleScaleChange_) {
361         auto titleMiddleValue =
362             (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) + maxTitleBarHeight_) / TITLE_RATIO;
363         if (LessNotEqual(tempTitleBarHeight_, titleMiddleValue) || NearEqual(tempTitleBarHeight_, titleMiddleValue)) {
364             AnimateTo(static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - defaultTitleBarHeight_);
365             return;
366         } else if (GreatNotEqual(tempTitleBarHeight_, titleMiddleValue)) {
367             AnimateTo(maxTitleBarHeight_ - defaultTitleBarHeight_);
368             return;
369         }
370     }
371 }
372 
GetSubtitleOpacity()373 float TitleBarPattern::GetSubtitleOpacity()
374 {
375     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
376     opacityRatio_ = 1.0f / titleBarHeightDiff;
377     auto tempOpacity = static_cast<float>(
378         (tempTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * opacityRatio_ + 0.0f);
379     return tempOpacity;
380 }
381 
GetFontSize(float offset)382 float TitleBarPattern::GetFontSize(float offset)
383 {
384     auto titleBarHeight = defaultTitleBarHeight_ + offset;
385     auto theme = NavigationGetTheme();
386     CHECK_NULL_RETURN(theme, 0.0f);
387     auto titleFontSizeDiff = theme->GetTitleFontSizeBig() - theme->GetTitleFontSize();
388     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
389     fontSizeRatio_ = titleFontSizeDiff.ConvertToPx() / titleBarHeightDiff;
390     auto tempFontSize = static_cast<float>(
391         (titleBarHeight - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * fontSizeRatio_ +
392         theme->GetTitleFontSize().ConvertToPx());
393     if (GreatNotEqual(tempFontSize, theme->GetTitleFontSizeBig().ConvertToPx())) {
394         tempFontSize = theme->GetTitleFontSizeBig().ConvertToPx();
395     }
396     if (LessNotEqual(tempFontSize, theme->GetTitleFontSize().ConvertToPx())) {
397         tempFontSize = theme->GetTitleFontSize().ConvertToPx();
398     }
399     return tempFontSize;
400 }
401 
GetMappedOffset(float offset)402 float TitleBarPattern::GetMappedOffset(float offset)
403 {
404     auto titleOffset = offset + defaultTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
405     auto heightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
406     float moveRatio = Curves::SHARP->MoveInternal(std::clamp(titleOffset / heightDiff, 0.0f, 1.0f));
407     auto mappedTitleOffset = moveRatio * heightDiff;
408     auto mappedOffset =
409         mappedTitleOffset - defaultTitleBarHeight_ + static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
410     return mappedOffset;
411 }
412 
SpringAnimation(float startPos,float endPos)413 void TitleBarPattern::SpringAnimation(float startPos, float endPos)
414 {
415     float mass = 1.0f;        // The move animation spring curve mass is 1.0f
416     float stiffness = 228.0f; // The move animation spring curve stiffness is 228.0f
417     float damping = 30.0f;    // The move animation spring curve damping is 30.0f
418     const RefPtr<SpringProperty> DEFAULT_OVER_SPRING_PROPERTY =
419         AceType::MakeRefPtr<SpringProperty>(mass, stiffness, damping);
420     if (!springMotion_) {
421         springMotion_ = AceType::MakeRefPtr<SpringMotion>(overDragOffset_, 0, 0, DEFAULT_OVER_SPRING_PROPERTY);
422     } else {
423         springMotion_->Reset(overDragOffset_, 0, 0, DEFAULT_OVER_SPRING_PROPERTY);
424         springMotion_->ClearListeners();
425     }
426     springMotion_->AddListener([weak = AceType::WeakClaim(this)](float value) {
427         auto titlebar = weak.Upgrade();
428         CHECK_NULL_VOID(titlebar);
429         titlebar->SetOverDragOffset(value);
430         titlebar->tempTitleBarHeight_ = titlebar->maxTitleBarHeight_ + value / 6.0f;
431         titlebar->UpdateScaleByDragOverDragOffset(value);
432         auto host = titlebar->GetHost();
433         CHECK_NULL_VOID(host);
434         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
435     });
436 
437     if (!springController_) {
438         springController_ = AceType::MakeRefPtr<Animator>(PipelineBase::GetCurrentContext());
439     }
440     springController_->ClearStopListeners();
441     springController_->PlayMotion(springMotion_);
442     springController_->AddStopListener([weak = AceType::WeakClaim(this)]() {
443         auto titlebar = weak.Upgrade();
444         CHECK_NULL_VOID(titlebar);
445         titlebar->ClearDragState();
446         auto host = titlebar->GetHost();
447         CHECK_NULL_VOID(host);
448         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
449     });
450 }
451 
ClearDragState()452 void TitleBarPattern::ClearDragState()
453 {
454     overDragOffset_ = 0.0f;
455 }
456 
UpdateScaleByDragOverDragOffset(float overDragOffset)457 void TitleBarPattern::UpdateScaleByDragOverDragOffset(float overDragOffset)
458 {
459     if (Negative(overDragOffset)) {
460         return;
461     }
462     auto host = GetHost();
463     auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
464     CHECK_NULL_VOID(navBarNode);
465     if (navBarNode->GetPrevTitleIsCustomValue(true)) {
466         return;
467     }
468     auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
469     CHECK_NULL_VOID(navBarLayoutProperty);
470     if (navBarLayoutProperty->GetHideTitleBar().value_or(false)) {
471         return;
472     }
473 
474     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
475     CHECK_NULL_VOID(titleBarNode);
476     auto titleNode = titleBarNode->GetTitle();
477     CHECK_NULL_VOID(titleNode);
478     auto title = AceType::DynamicCast<FrameNode>(titleNode);
479     TransformScale(overDragOffset, title);
480     auto subtitleNode = titleBarNode->GetSubtitle();
481     if (subtitleNode) {
482         auto subtitle = AceType::DynamicCast<FrameNode>(subtitleNode);
483         TransformScale(overDragOffset, subtitle);
484     }
485 
486     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
487 }
488 
TransformScale(float overDragOffset,const RefPtr<FrameNode> & frameNode)489 void TitleBarPattern::TransformScale(float overDragOffset, const RefPtr<FrameNode>& frameNode)
490 {
491     CHECK_NULL_VOID(frameNode);
492     auto renderCtx = frameNode->GetRenderContext();
493     CHECK_NULL_VOID(renderCtx);
494     auto offset = std::clamp(overDragOffset, 0.0f, static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx()));
495     auto scaleRatio = offset / static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx());
496     VectorF scaleValue = VectorF(scaleRatio * 0.1f + 1.0f, scaleRatio * 0.1f + 1.0f);
497     renderCtx->UpdateTransformScale(scaleValue);
498 }
499 
AnimateTo(float offset)500 void TitleBarPattern::AnimateTo(float offset)
501 {
502     if (!animator_) {
503         animator_ = CREATE_ANIMATOR(PipelineBase::GetCurrentContext());
504     }
505     auto animation = AceType::MakeRefPtr<CurveAnimation<float>>(GetCurrentOffset(), offset, Curves::FAST_OUT_SLOW_IN);
506     animation->AddListener([weakScroll = AceType::WeakClaim(this)](float value) {
507         auto titlebar = weakScroll.Upgrade();
508         CHECK_NULL_VOID(titlebar);
509         titlebar->ProcessTitleDragUpdate(value);
510         auto host = titlebar->GetHost();
511         CHECK_NULL_VOID(host);
512         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
513         auto pipeline = PipelineContext::GetCurrentContext();
514         if (pipeline) {
515             pipeline->FlushUITasks();
516         }
517     });
518     animator_->ClearInterpolators();
519     animator_->AddInterpolator(animation);
520     animator_->SetDuration(DEFAULT_ANIMATION_DURATION);
521     animator_->Play();
522 }
523 
SetMaxTitleBarHeight()524 void TitleBarPattern::SetMaxTitleBarHeight()
525 {
526     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
527     CHECK_NULL_VOID(titleBarNode);
528     if (titleBarNode->GetSubtitle()) {
529         maxTitleBarHeight_ = static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
530     } else {
531         maxTitleBarHeight_ = static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
532     }
533 }
534 
SetTempTitleBarHeight(float offsetY)535 void TitleBarPattern::SetTempTitleBarHeight(float offsetY)
536 {
537     tempTitleBarHeight_ = defaultTitleBarHeight_ + offsetY;
538     if (tempTitleBarHeight_ < static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) {
539         tempTitleBarHeight_ = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
540     }
541     if (tempTitleBarHeight_ > maxTitleBarHeight_) {
542         tempTitleBarHeight_ = maxTitleBarHeight_;
543     }
544 }
545 
SetTempTitleOffsetY()546 void TitleBarPattern::SetTempTitleOffsetY()
547 {
548     tempTitleOffsetY_ = defaultTitleOffsetY_ + titleMoveDistance_;
549     if (tempTitleOffsetY_ < minTitleOffsetY_) {
550         tempTitleOffsetY_ = minTitleOffsetY_;
551     }
552     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
553         tempTitleOffsetY_ = maxTitleOffsetY_;
554     }
555 }
556 
SetTempSubTitleOffsetY()557 void TitleBarPattern::SetTempSubTitleOffsetY()
558 {
559     tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight();
560     if (tempTitleOffsetY_ < minTitleOffsetY_) {
561         tempSubTitleOffsetY_ = minTitleOffsetY_;
562     }
563     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
564         tempSubTitleOffsetY_ = maxTitleOffsetY_;
565     }
566 }
567 
SetDefaultTitleFontSize()568 void TitleBarPattern::SetDefaultTitleFontSize()
569 {
570     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
571     CHECK_NULL_VOID(titleBarNode);
572     CHECK_NULL_VOID(titleBarNode->GetTitle());
573     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
574     CHECK_NULL_VOID(titleNode);
575     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
576     CHECK_NULL_VOID(textLayoutProperty);
577     auto theme = NavigationGetTheme();
578     CHECK_NULL_VOID(theme);
579     defaultTitleFontSize_ = theme->GetTitleFontSize();
580 }
581 
SetDefaultSubtitleOpacity()582 void TitleBarPattern::SetDefaultSubtitleOpacity()
583 {
584     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
585     CHECK_NULL_VOID(titleBarNode);
586     CHECK_NULL_VOID(titleBarNode->GetSubtitle());
587     auto subtitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
588     CHECK_NULL_VOID(subtitleNode);
589     auto context = subtitleNode->GetRenderContext();
590     CHECK_NULL_VOID(context);
591     if (defaultTitleBarHeight_ == maxTitleBarHeight_) {
592         defaultSubtitleOpacity_ = context->GetOpacityValue(1.0f);
593     } else {
594         defaultSubtitleOpacity_ = context->GetOpacityValue(0.0f);
595     }
596 }
597 
GetTitleHeight()598 float TitleBarPattern::GetTitleHeight()
599 {
600     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
601     CHECK_NULL_RETURN(titleBarNode, 0.0f);
602     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
603     CHECK_NULL_RETURN(titleNode, 0.0f);
604     auto geometryNode = titleNode->GetGeometryNode();
605     CHECK_NULL_RETURN(geometryNode, 0.0f);
606     return geometryNode->GetFrameSize().Height();
607 }
608 
GetSubTitleOffsetY()609 float TitleBarPattern::GetSubTitleOffsetY()
610 {
611     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
612     CHECK_NULL_RETURN(titleBarNode, 0.0f);
613     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
614     CHECK_NULL_RETURN(subTitleNode, 0.0f);
615     auto geometryNode = subTitleNode->GetGeometryNode();
616     CHECK_NULL_RETURN(geometryNode, 0.0f);
617     return geometryNode->GetMarginFrameOffset().GetY();
618 }
619 
UpdateTitleFontSize(const Dimension & tempTitleFontSize)620 void TitleBarPattern::UpdateTitleFontSize(const Dimension& tempTitleFontSize)
621 {
622     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
623     CHECK_NULL_VOID(titleBarNode);
624     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
625     CHECK_NULL_VOID(titleNode);
626     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
627     CHECK_NULL_VOID(textLayoutProperty);
628     textLayoutProperty->UpdateFontSize(tempTitleFontSize);
629     textLayoutProperty->UpdateAdaptMaxFontSize(tempTitleFontSize);
630     titleNode->MarkModifyDone();
631 }
632 
UpdateSubTitleOpacity(const double & value)633 void TitleBarPattern::UpdateSubTitleOpacity(const double& value)
634 {
635     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
636     CHECK_NULL_VOID(titleBarNode);
637     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
638     CHECK_NULL_VOID(subTitleNode);
639     auto context = subTitleNode->GetRenderContext();
640     CHECK_NULL_VOID(context);
641     context->UpdateOpacity(value);
642 }
643 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)644 bool TitleBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
645 {
646     if (config.skipMeasure && config.skipLayout) {
647         return false;
648     }
649     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
650     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
651     auto titleBarLayoutAlgorithm = DynamicCast<TitleBarLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
652     CHECK_NULL_RETURN(titleBarLayoutAlgorithm, false);
653     UpdateTitleModeChange();
654 
655     initialTitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialTitleOffsetY();
656     isInitialTitle_ = titleBarLayoutAlgorithm->IsInitialTitle();
657     initialSubtitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialSubtitleOffsetY();
658     isInitialSubtitle_ = titleBarLayoutAlgorithm->IsInitialSubtitle();
659     minTitleHeight_ = titleBarLayoutAlgorithm->GetMinTitleHeight();
660     return true;
661 }
662 
UpdateTitleModeChange()663 void TitleBarPattern::UpdateTitleModeChange()
664 {
665     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
666     CHECK_NULL_VOID(titleBarNode);
667     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
668     CHECK_NULL_VOID(titleBarLayoutProperty);
669     auto geometryNode = titleBarNode->GetGeometryNode();
670     CHECK_NULL_VOID(geometryNode);
671 
672     auto titleBarHeight = geometryNode->GetFrameSize().Height();
673     if ((titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) &&
674         !NearZero(maxTitleBarHeight_)) {
675         if (titleBarHeight >= maxTitleBarHeight_) {
676             titleMode_ = NavigationTitleMode::FULL;
677         } else if (NearEqual(titleBarHeight, static_cast<float>(TITLEBAR_HEIGHT_MINI.ConvertToPx()))) {
678             titleMode_ = NavigationTitleMode::MINI;
679         }
680     }
681 }
682 
OnAttachToFrameNode()683 void TitleBarPattern::OnAttachToFrameNode()
684 {
685     auto host = GetHost();
686     CHECK_NULL_VOID(host);
687     host->GetRenderContext()->SetClipToFrame(true);
688 
689     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
690         SafeAreaExpandOpts opts = {.type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_TOP};
691         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
692     }
693 }
694 
OnCoordScrollStart()695 void TitleBarPattern::OnCoordScrollStart()
696 {
697     coordScrollOffset_ = 0.0f;
698     coordScrollFinalOffset_ = 0.0f;
699     isFreeTitleUpdated_ = true;
700 
701     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
702     CHECK_NULL_VOID(titleBarNode);
703     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
704     CHECK_NULL_VOID(titleBarLayoutProperty);
705     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
706         return;
707     }
708     if (springController_ && !springController_->IsStopped()) {
709         // clear stop listener before stop
710         springController_->ClearStopListeners();
711         springController_->Stop();
712     }
713     if (animator_ && !animator_->IsStopped()) {
714         animator_->Stop();
715     }
716 
717     defaultTitleBarHeight_ = currentTitleBarHeight_;
718     defaultTitleOffsetY_ = currentTitleOffsetY_;
719     SetMaxTitleBarHeight();
720     SetTempTitleBarHeight(0);
721     minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2.0f;
722     maxTitleOffsetY_ = initialTitleOffsetY_;
723     moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
724                  (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
725     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
726 }
727 
OnCoordScrollUpdate(float offset)728 float TitleBarPattern::OnCoordScrollUpdate(float offset)
729 {
730     float lastOffset = coordScrollOffset_;
731     coordScrollOffset_ += offset;
732 
733     float offsetHandled = 0.0f;
734     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
735     float titleBarOffset = coordScrollOffset_;
736     if (LessNotEqual(defaultTitleBarHeight_ + titleBarOffset, minHeight)) {
737         // The target height is smaller than the minHeight, so the titleBarOffset is adjusted to modify the height to
738         // the minHeight.
739         titleBarOffset = minHeight - defaultTitleBarHeight_;
740         overDragOffset_ = 0.0f;
741         offsetHandled = CalculateHandledOffsetMinTitle(offset, lastOffset);
742     } else if (GreatNotEqual(defaultTitleBarHeight_ + titleBarOffset, maxTitleBarHeight_)) {
743         // The target height is greater than the maxTitleBarHeight_, so overDragOffset_ needs to be updated.
744         overDragOffset_ = defaultTitleBarHeight_ + titleBarOffset - maxTitleBarHeight_;
745         offsetHandled = CalculateHandledOffsetMaxTitle(offset, lastOffset);
746     } else {
747         // The target height is between the minHeight and the maxTitleBarHeight_.
748         overDragOffset_ = 0.0f;
749         offsetHandled = CalculateHandledOffsetBetweenMinAndMaxTitle(offset, lastOffset);
750     }
751     UpdateTitleBarByCoordScroll(titleBarOffset);
752     coordScrollFinalOffset_ = titleBarOffset;
753 
754     return offsetHandled;
755 }
756 
OnCoordScrollEnd()757 void TitleBarPattern::OnCoordScrollEnd()
758 {
759     if (NearZero(coordScrollOffset_)) {
760         return;
761     }
762     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
763     float middleHeight =
764         (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) + maxTitleBarHeight_) / TITLE_RATIO;
765     float finalHeight = defaultTitleBarHeight_ + coordScrollFinalOffset_;
766     if (GreatNotEqual(finalHeight, minHeight) && LessOrEqual(finalHeight, middleHeight)) {
767         // The finalHeight is between the minHeight and the middleHeight, so animate to min title.
768         AnimateTo(static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - defaultTitleBarHeight_);
769     } else if (GreatNotEqual(finalHeight, middleHeight) && LessNotEqual(finalHeight, maxTitleBarHeight_)) {
770         // The finalHeight is between the middleHeight and the maxTitleBarHeight_, so animate to max title.
771         AnimateTo(maxTitleBarHeight_ - defaultTitleBarHeight_);
772     } else if (GreatNotEqual(finalHeight, maxTitleBarHeight_)) {
773         // The finalHeight is bigger than the maxTitleBarHeight_, so animate to max title.
774         SpringAnimation(finalHeight - maxTitleBarHeight_, 0);
775     }
776 }
777 
UpdateTitleBarByCoordScroll(float offset)778 void TitleBarPattern::UpdateTitleBarByCoordScroll(float offset)
779 {
780     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
781     CHECK_NULL_VOID(titleBarNode);
782     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
783     CHECK_NULL_VOID(titleBarLayoutProperty);
784     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
785         return;
786     }
787     SetTitleStyleByCoordScrollOffset(offset);
788     UpdateScaleByDragOverDragOffset(overDragOffset_);
789 }
790 
SetTitleStyleByCoordScrollOffset(float offset)791 void TitleBarPattern::SetTitleStyleByCoordScrollOffset(float offset)
792 {
793     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
794     CHECK_NULL_VOID(titleBarNode);
795     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
796     CHECK_NULL_VOID(titleBarLayoutProperty);
797     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
798         return;
799     }
800     if (Positive(overDragOffset_)) {
801         tempTitleBarHeight_ = maxTitleBarHeight_ + overDragOffset_ / 6.0f;
802         titleMoveDistance_ = (maxTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_ + overDragOffset_ / 6.0f;
803     } else {
804         SetTempTitleBarHeight(offset);
805         titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
806     }
807 
808     SetTempTitleOffsetY();
809     SetTempSubTitleOffsetY();
810     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
811 
812     // title font size
813     auto mappedOffset = GetMappedOffset(offset);
814     fontSize_ = GetFontSize(mappedOffset);
815     UpdateTitleFontSize(Dimension(fontSize_.value(), DimensionUnit::PX));
816 
817     // subTitle Opacity
818     opacity_ = GetSubtitleOpacity();
819     UpdateSubTitleOpacity(opacity_.value());
820 }
821 
OnColorConfigurationUpdate()822 void TitleBarPattern::OnColorConfigurationUpdate()
823 {
824     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
825     CHECK_NULL_VOID(titleBarNode);
826     auto backButton = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
827     CHECK_NULL_VOID(backButton);
828     if (backButton->GetTag() == "Navigator") {
829         backButton = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
830         CHECK_NULL_VOID(backButton);
831     }
832     auto backButtonImgNode = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
833     CHECK_NULL_VOID(backButtonImgNode);
834     auto backButtonImgRender = backButtonImgNode->GetPaintProperty<ImageRenderProperty>();
835     CHECK_NULL_VOID(backButtonImgRender);
836     auto theme = NavigationGetTheme();
837     CHECK_NULL_VOID(theme);
838     backButtonImgRender->UpdateSvgFillColor(theme->GetBackButtonIconColor());
839     backButtonImgNode->MarkModifyDone();
840 }
841 
CalculateHandledOffsetMinTitle(float offset,float lastCordScrollOffset)842 float TitleBarPattern::CalculateHandledOffsetMinTitle(float offset, float lastCordScrollOffset)
843 {
844     float offsetHandled = 0.0f;
845     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
846     if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
847         // The starting height of this update is smaller than the minHeight, so the navigation component does
848         // not handle the offset.
849         offsetHandled = 0.0f;
850     } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
851         // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
852         // component only handles offsets from maxTitleBarHeight_ to minHeight.
853         offsetHandled = minHeight - maxTitleBarHeight_;
854     } else {
855         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
856         // navigation component only handles offsets from defaultTitleBarHeight_ to minHeight.
857         offsetHandled = offset - (coordScrollOffset_ - (minHeight - defaultTitleBarHeight_));
858     }
859     return offsetHandled;
860 }
861 
CalculateHandledOffsetMaxTitle(float offset,float lastCordScrollOffset)862 float TitleBarPattern::CalculateHandledOffsetMaxTitle(float offset, float lastCordScrollOffset)
863 {
864     float offsetHandled = 0.0f;
865     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
866     if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
867         // The starting height of this update is greater than the maxTitleBarHeight_, so the navigation component
868         // does not handle the offset.
869         offsetHandled = 0.0f;
870     } else if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
871         // The starting position height of this update is smaller than the minHeight, so the navigation component
872         // only handles offsets from minHeight to maxTitleBarHeight_.
873         offsetHandled = maxTitleBarHeight_ - minHeight;
874     } else {
875         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
876         // navigation component only handles offsets from defaultTitleBarHeight_ to maxTitleBarHeight_.
877         offsetHandled = offset - (coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_));
878     }
879     return offsetHandled;
880 }
881 
CalculateHandledOffsetBetweenMinAndMaxTitle(float offset,float lastCordScrollOffset)882 float TitleBarPattern::CalculateHandledOffsetBetweenMinAndMaxTitle(float offset, float lastCordScrollOffset)
883 {
884     float offsetHandled = 0.0f;
885     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
886     if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
887         // The starting height of this update is smaller than the minHeight, so the navigation component only
888         // handles offsets from minHeight to target height.
889         offsetHandled = defaultTitleBarHeight_ + coordScrollOffset_ - minHeight;
890     } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
891         // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
892         // component only handles offsets from maxTitleBarHeight_ to target height.
893         offsetHandled = coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_);
894     } else {
895         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
896         // navigation component handles all of the offset.
897         offsetHandled = offset;
898     }
899     return offsetHandled;
900 }
901 
SetTitlebarOptions(NavigationTitlebarOptions && opt)902 void TitleBarPattern::SetTitlebarOptions(NavigationTitlebarOptions&& opt)
903 {
904     if (opt == options_) {
905         return;
906     }
907 
908     options_ = std::move(opt);
909     auto host = GetHost();
910     CHECK_NULL_VOID(host);
911     auto renderContext = host->GetRenderContext();
912     CHECK_NULL_VOID(renderContext);
913     if (options_.bgOptions.color.has_value()) {
914         renderContext->UpdateBackgroundColor(options_.bgOptions.color.value());
915     } else {
916         renderContext->ResetBackgroundColor();
917     }
918     if (options_.bgOptions.blurStyle.has_value()) {
919         BlurStyleOption blur;
920         blur.blurStyle = options_.bgOptions.blurStyle.value();
921         renderContext->UpdateBackBlurStyle(blur);
922     } else {
923         renderContext->ResetBackBlurStyle();
924     }
925 }
926 } // namespace OHOS::Ace::NG
927