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