• 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/components_ng/pattern/image/image_layout_property.h"
20 #include "core/components_ng/pattern/image/image_render_property.h"
21 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
22 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
23 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
24 #include "core/components_ng/pattern/navigation/title_bar_node.h"
25 #include "core/components_ng/pattern/text/text_layout_property.h"
26 #include "core/components_v2/inspector/inspector_constants.h"
27 
28 namespace OHOS::Ace::NG {
29 
30 namespace {
31 constexpr int32_t DEFAULT_ANIMATION_DURATION = 200;
32 constexpr int32_t TITLE_RATIO = 2;
33 
MountBackButton(const RefPtr<TitleBarNode> & hostNode)34 void MountBackButton(const RefPtr<TitleBarNode>& hostNode)
35 {
36     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
37     CHECK_NULL_VOID(titleBarLayoutProperty);
38     auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
39     CHECK_NULL_VOID(backButtonNode);
40     if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) == TitleBarParentType::NAVBAR) {
41         auto buttonNode = backButtonNode->GetChildren().front();
42         CHECK_NULL_VOID(buttonNode);
43         auto backButtonImageNode = AceType::DynamicCast<FrameNode>(buttonNode->GetChildren().front());
44         CHECK_NULL_VOID(backButtonImageNode);
45         auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
46         CHECK_NULL_VOID(backButtonImageLayoutProperty);
47         if (titleBarLayoutProperty->HasNoPixMap() && titleBarLayoutProperty->HasImageSource()) {
48             backButtonImageLayoutProperty->UpdateImageSourceInfo(titleBarLayoutProperty->GetImageSourceValue());
49         }
50         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
51         CHECK_NULL_VOID(navBarNode);
52         auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
53         CHECK_NULL_VOID(navBarLayoutProperty);
54         auto hideBackButton = navBarLayoutProperty->GetHideBackButtonValue(false);
55         backButtonImageLayoutProperty->UpdateVisibility(hideBackButton ? VisibleType::GONE : VisibleType::VISIBLE);
56         backButtonImageNode->MarkModifyDone();
57         return;
58     }
59     if (!titleBarLayoutProperty->HasNoPixMap()) {
60         backButtonNode->MarkModifyDone();
61         return;
62     }
63     RefPtr<ImageLayoutProperty> backButtonImageLayoutProperty;
64     if (PipelineContext::GetCurrentContext() && PipelineContext::GetCurrentContext()
65             ->GetMinPlatformVersion() < static_cast<int32_t>(PlatformVersion::VERSION_TEN)) {
66         backButtonImageLayoutProperty = backButtonNode->GetLayoutProperty<ImageLayoutProperty>();
67     } else {
68         auto buttonNode = backButtonNode->GetChildren().front();
69         CHECK_NULL_VOID(buttonNode);
70         auto backButtonImageNode = AceType::DynamicCast<FrameNode>(buttonNode->GetChildren().front());
71         CHECK_NULL_VOID(backButtonImageNode);
72         backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
73     }
74     CHECK_NULL_VOID(backButtonImageLayoutProperty);
75     if (titleBarLayoutProperty->HasImageSource()) {
76         backButtonImageLayoutProperty->UpdateImageSourceInfo(titleBarLayoutProperty->GetImageSourceValue());
77         backButtonNode->MarkModifyDone();
78         return;
79     }
80 
81     if (titleBarLayoutProperty->HasPixelMap()) {
82         // TODO: use pixelMap
83         backButtonNode->MarkModifyDone();
84         return;
85     }
86 }
87 
MountTitle(const RefPtr<TitleBarNode> & hostNode)88 void MountTitle(const RefPtr<TitleBarNode>& hostNode)
89 {
90     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
91     CHECK_NULL_VOID(titleBarLayoutProperty);
92     auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
93     CHECK_NULL_VOID(titleNode);
94     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetParent());
95     CHECK_NULL_VOID(navBarNode);
96     // if title node is custom node markModifyDone and return
97     if (navBarNode->GetPrevTitleIsCustomValue(false)) {
98         titleNode->MarkModifyDone();
99         return;
100     }
101 
102     auto titleLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
103     CHECK_NULL_VOID(titleLayoutProperty);
104 
105     auto theme = NavigationGetTheme();
106     CHECK_NULL_VOID(theme);
107     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
108         if (titleBarLayoutProperty->HasHideBackButton() && titleBarLayoutProperty->GetHideBackButtonValue()) {
109             titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSize());
110             titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSize());
111         } else {
112             titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeMin());
113             titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSizeMin());
114         }
115         titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_TITLE_FONT_SIZE);
116         titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
117     } else {
118         titleLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
119         titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetTitleFontSizeBig());
120     }
121 
122     if (hostNode->GetSubtitle()) {
123         titleLayoutProperty->UpdateMaxLines(1);
124     } else {
125         titleLayoutProperty->UpdateMaxLines(TITLEBAR_MAX_LINES);
126     }
127 
128     titleNode->MarkModifyDone();
129 }
130 
MountSubTitle(const RefPtr<TitleBarNode> & hostNode)131 void MountSubTitle(const RefPtr<TitleBarNode>& hostNode)
132 {
133     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
134     CHECK_NULL_VOID(titleBarLayoutProperty);
135     auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
136     CHECK_NULL_VOID(subtitleNode);
137     auto titleLayoutProperty = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
138     CHECK_NULL_VOID(titleLayoutProperty);
139 
140     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
141         auto theme = NavigationGetTheme();
142         CHECK_NULL_VOID(theme);
143         titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_SUBTITLE_FONT_SIZE);
144         titleLayoutProperty->UpdateAdaptMaxFontSize(theme->GetSubTitleFontSize());
145         titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
146     }
147 
148     subtitleNode->MarkModifyDone();
149 }
150 
151 } // namespace
152 
OnModifyDone()153 void TitleBarPattern::OnModifyDone()
154 {
155     Pattern::OnModifyDone();
156     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
157     CHECK_NULL_VOID(hostNode);
158     MountBackButton(hostNode);
159     MountTitle(hostNode);
160     MountSubTitle(hostNode);
161 }
162 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)163 void TitleBarPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
164 {
165     CHECK_NULL_VOID_NOLOG(!panEvent_);
166 
167     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
168         LOGI("Pan event start");
169         auto pattern = weak.Upgrade();
170         CHECK_NULL_VOID_NOLOG(pattern);
171         if (info.GetInputEventType() == InputEventType::AXIS) {
172             return;
173         }
174         pattern->HandleDragStart(info);
175     };
176 
177     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
178         auto pattern = weak.Upgrade();
179         CHECK_NULL_VOID_NOLOG(pattern);
180         if (info.GetInputEventType() == InputEventType::AXIS) {
181             return;
182         }
183         pattern->HandleDragUpdate(info);
184     };
185 
186     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
187         LOGI("Pan event end mainVelocity: %{public}lf", info.GetMainVelocity());
188         auto pattern = weak.Upgrade();
189         CHECK_NULL_VOID_NOLOG(pattern);
190         if (info.GetInputEventType() == InputEventType::AXIS) {
191             return;
192         }
193         pattern->HandleDragEnd(info.GetMainVelocity());
194     };
195 
196     auto actionCancelTask = [weak = WeakClaim(this)]() {
197         LOGI("Pan event cancel");
198         auto pattern = weak.Upgrade();
199         CHECK_NULL_VOID_NOLOG(pattern);
200         pattern->HandleDragEnd(0.0);
201     };
202 
203     if (panEvent_) {
204         gestureHub->RemovePanEvent(panEvent_);
205     }
206 
207     panEvent_ = MakeRefPtr<PanEvent>(
208         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
209     PanDirection panDirection = { .type = PanDirection::VERTICAL };
210     gestureHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
211 }
212 
HandleDragStart(const GestureEvent & info)213 void TitleBarPattern::HandleDragStart(const GestureEvent& info)
214 {
215     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
216     CHECK_NULL_VOID(titleBarNode);
217     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
218     CHECK_NULL_VOID(titleBarLayoutProperty);
219     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
220         return;
221     }
222     defaultTitleBarHeight_ = titleBarNode->GetGeometryNode()->GetFrameSize().Height();
223     SetMaxTitleBarHeight();
224     SetTempTitleBarHeight(static_cast<float>(info.GetOffsetY()));
225     minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2;
226     maxTitleOffsetY_ = initialTitleOffsetY_;
227     moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
228                  (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
229     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
230     defaultTitleOffsetY_ = GetTitleOffsetY();
231     SetTempTitleOffsetY();
232     defaultSubtitleOffsetY_ = GetSubTitleOffsetY();
233     SetTempSubTitleOffsetY();
234     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
235 
236     // title font size
237     SetDefaultTitleFontSize();
238     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
239     auto titleFontSizeDiff = MAX_TITLE_FONT_SIZE - MIN_TITLE_FONT_SIZE;
240     fontSizeRatio_ = titleFontSizeDiff.Value() / titleBarHeightDiff;
241     auto tempFontSize = static_cast<float>(
242         (tempTitleBarHeight_ - defaultTitleBarHeight_) * fontSizeRatio_ + defaultTitleFontSize_.Value());
243     UpdateTitleFontSize(Dimension(tempFontSize, DimensionUnit::VP));
244 
245     // subTitle Opacity
246     SetDefaultSubtitleOpacity();
247     opacityRatio_ = 1.0f / titleBarHeightDiff;
248     auto tempOpacity =
249         static_cast<float>((tempTitleBarHeight_ - defaultTitleBarHeight_) * opacityRatio_ + defaultSubtitleOpacity_);
250     UpdateSubTitleOpacity(tempOpacity);
251 }
252 
HandleDragUpdate(const GestureEvent & info)253 void TitleBarPattern::HandleDragUpdate(const GestureEvent& info)
254 {
255     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
256     CHECK_NULL_VOID(titleBarNode);
257     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
258     CHECK_NULL_VOID(titleBarLayoutProperty);
259     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
260         return;
261     }
262     SetTempTitleBarHeight(static_cast<float>(info.GetOffsetY()));
263     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
264     SetTempTitleOffsetY();
265     SetTempSubTitleOffsetY();
266     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
267 
268     // title font size
269     auto tempFontSize = static_cast<float>(
270         (tempTitleBarHeight_ - defaultTitleBarHeight_) * fontSizeRatio_ + defaultTitleFontSize_.Value());
271     UpdateTitleFontSize(Dimension(tempFontSize, DimensionUnit::VP));
272 
273     // subTitle Opacity
274     auto tempOpacity =
275         static_cast<float>((tempTitleBarHeight_ - defaultTitleBarHeight_) * opacityRatio_ + defaultSubtitleOpacity_);
276     UpdateSubTitleOpacity(tempOpacity);
277 }
278 
HandleDragEnd(double dragVelocity)279 void TitleBarPattern::HandleDragEnd(double dragVelocity)
280 {
281     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
282     CHECK_NULL_VOID(titleBarNode);
283     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
284     CHECK_NULL_VOID(titleBarLayoutProperty);
285     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
286         return;
287     }
288 }
289 
ProcessTittleDragStart(float offset)290 void TitleBarPattern::ProcessTittleDragStart(float offset)
291 {
292     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
293     CHECK_NULL_VOID(titleBarNode);
294     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
295     CHECK_NULL_VOID(titleBarLayoutProperty);
296     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
297         return;
298     }
299     if (springController_ && !springController_->IsStopped()) {
300         // clear stop listener before stop
301         springController_->ClearStopListeners();
302         springController_->Stop();
303     }
304     if (animator_ && !animator_->IsStopped()) {
305         animator_->Stop();
306     }
307 
308     defaultTitleBarHeight_ = titleBarNode->GetGeometryNode()->GetFrameSize().Height();
309     SetMaxTitleBarHeight();
310     SetTempTitleBarHeight(offset);
311     minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2.0f;
312     maxTitleOffsetY_ = initialTitleOffsetY_;
313     moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
314                  (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
315     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
316     defaultTitleOffsetY_ = GetTitleOffsetY();
317     SetTempTitleOffsetY();
318     defaultSubtitleOffsetY_ = GetSubTitleOffsetY();
319     SetTempSubTitleOffsetY();
320     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
321 
322     // title font size
323     SetDefaultTitleFontSize();
324     auto mappedOffset = GetMappedOffset(offset);
325     auto tempFontSize = GetFontSize(mappedOffset);
326     UpdateTitleFontSize(Dimension(tempFontSize, DimensionUnit::VP));
327 
328     // subTitle Opacity
329     SetDefaultSubtitleOpacity();
330     auto tempOpacity = GetSubtitleOpacity();
331     UpdateSubTitleOpacity(tempOpacity);
332 }
333 
ProcessTittleDragUpdate(float offset)334 void TitleBarPattern::ProcessTittleDragUpdate(float offset)
335 {
336     if (NearZero(offset)) {
337         return;
338     }
339     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
340     CHECK_NULL_VOID(titleBarNode);
341     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
342     CHECK_NULL_VOID(titleBarLayoutProperty);
343     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
344         return;
345     }
346     SetTitleStyleByOffset(offset);
347     if (CanOverDrag_) {
348         overDragOffset_ = offset + defaultTitleBarHeight_ - maxTitleBarHeight_;
349     } else {
350         overDragOffset_ = 0.0f;
351     }
352 
353     if (Positive(overDragOffset_)) {
354         UpdateScaleByDragOverDragOffset(overDragOffset_);
355     } else {
356         overDragOffset_ = 0.0f;
357     }
358 }
359 
SetTitleStyleByOffset(float offset)360 void TitleBarPattern::SetTitleStyleByOffset(float offset)
361 {
362     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
363     SetTempTitleBarHeight(offset);
364     titleMoveDistance_ = (tempTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_;
365     SetTempTitleOffsetY();
366     SetTempSubTitleOffsetY();
367     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
368 
369     // title font size
370     auto mappedOffset = GetMappedOffset(offset);
371     auto tempFontSize = GetFontSize(mappedOffset);
372     UpdateTitleFontSize(Dimension(tempFontSize, DimensionUnit::VP));
373 
374     // subTitle Opacity
375     auto tempOpacity = GetSubtitleOpacity();
376     UpdateSubTitleOpacity(tempOpacity);
377 }
378 
ProcessTittleDragEnd()379 void TitleBarPattern::ProcessTittleDragEnd()
380 {
381     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
382     CHECK_NULL_VOID(titleBarNode);
383     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
384     CHECK_NULL_VOID(titleBarLayoutProperty);
385     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
386         return;
387     }
388 
389     if (Positive(overDragOffset_)) {
390         SpringAnimation(overDragOffset_, 0);
391         return;
392     }
393 
394     auto titleMiddleValue =
395         (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) + maxTitleBarHeight_) / TITLE_RATIO;
396     if (LessNotEqual(tempTitleBarHeight_, titleMiddleValue) || NearEqual(tempTitleBarHeight_, titleMiddleValue)) {
397         AnimateTo(static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - defaultTitleBarHeight_);
398     } else if (GreatNotEqual(tempTitleBarHeight_, titleMiddleValue)) {
399         AnimateTo(maxTitleBarHeight_ - defaultTitleBarHeight_);
400     }
401 }
402 
GetSubtitleOpacity()403 float TitleBarPattern::GetSubtitleOpacity()
404 {
405     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
406     opacityRatio_ = 1.0f / titleBarHeightDiff;
407     auto tempOpacity = static_cast<float>(
408         (tempTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * opacityRatio_ + 0.0f);
409     return tempOpacity;
410 }
411 
GetFontSize(float offset)412 float TitleBarPattern::GetFontSize(float offset)
413 {
414     auto titleBarHeight = defaultTitleBarHeight_ + offset;
415     if (LessNotEqual(titleBarHeight, static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()))) {
416         titleBarHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
417     }
418     if (GreatNotEqual(titleBarHeight, maxTitleBarHeight_)) {
419         titleBarHeight = maxTitleBarHeight_;
420     }
421     auto titleFontSizeDiff = MAX_TITLE_FONT_SIZE - MIN_TITLE_FONT_SIZE;
422     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
423     fontSizeRatio_ = titleFontSizeDiff.Value() / titleBarHeightDiff;
424     auto tempFontSize = static_cast<float>(
425         (titleBarHeight - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * fontSizeRatio_ +
426         MIN_TITLE_FONT_SIZE.Value());
427     return tempFontSize;
428 }
429 
GetMappedOffset(float offset)430 float TitleBarPattern::GetMappedOffset(float offset)
431 {
432     auto titleOffset = offset + defaultTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
433     auto heightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
434     float moveRatio = Curves::SHARP->MoveInternal(std::clamp(titleOffset / heightDiff, 0.0f, 1.0f));
435     auto mappedTitleOffset = moveRatio * heightDiff;
436     auto mappedOffset =
437         mappedTitleOffset - defaultTitleBarHeight_ + static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
438     return mappedOffset;
439 }
440 
SpringAnimation(float startPos,float endPos)441 void TitleBarPattern::SpringAnimation(float startPos, float endPos)
442 {
443     float mass = 1.0f;        // The move animation spring curve mass is 1.0f
444     float stiffness = 228.0f; // The move animation spring curve stiffness is 228.0f
445     float damping = 30.0f;    // The move animation spring curve damping is 30.0f
446     const RefPtr<SpringProperty> DEFAULT_OVER_SPRING_PROPERTY =
447         AceType::MakeRefPtr<SpringProperty>(mass, stiffness, damping);
448     if (!springMotion_) {
449         springMotion_ = AceType::MakeRefPtr<SpringMotion>(overDragOffset_, 0, 0, DEFAULT_OVER_SPRING_PROPERTY);
450     } else {
451         springMotion_->Reset(overDragOffset_, 0, 0, DEFAULT_OVER_SPRING_PROPERTY);
452         springMotion_->ClearListeners();
453     }
454     springMotion_->AddListener([weak = AceType::WeakClaim(this)](float value) {
455         auto titlebar = weak.Upgrade();
456         CHECK_NULL_VOID(titlebar);
457         titlebar->SetOverDragOffset(value);
458         titlebar->UpdateScaleByDragOverDragOffset(value);
459         auto host = titlebar->GetHost();
460         CHECK_NULL_VOID(host);
461         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
462     });
463 
464     if (!springController_) {
465         springController_ = AceType::MakeRefPtr<Animator>(PipelineBase::GetCurrentContext());
466     }
467     springController_->ClearStopListeners();
468     springController_->PlayMotion(springMotion_);
469     springController_->AddStopListener([weak = AceType::WeakClaim(this)]() {
470         auto titlebar = weak.Upgrade();
471         CHECK_NULL_VOID(titlebar);
472         titlebar->ClearDragState();
473         auto host = titlebar->GetHost();
474         CHECK_NULL_VOID(host);
475         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
476     });
477 }
478 
ClearDragState()479 void TitleBarPattern::ClearDragState()
480 {
481     overDragOffset_ = 0.0f;
482 }
483 
UpdateScaleByDragOverDragOffset(float overDragOffset)484 void TitleBarPattern::UpdateScaleByDragOverDragOffset(float overDragOffset)
485 {
486     if (Negative(overDragOffset)) {
487         return;
488     }
489     auto host = GetHost();
490     auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
491     CHECK_NULL_VOID(navBarNode);
492     if (navBarNode->GetPrevTitleIsCustomValue(true)) {
493         return;
494     }
495     auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
496     CHECK_NULL_VOID(navBarLayoutProperty);
497     if (navBarLayoutProperty->GetHideTitleBar().value_or(false)) {
498         return;
499     }
500 
501     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
502     CHECK_NULL_VOID(titleBarNode);
503     auto titleNode = titleBarNode->GetTitle();
504     CHECK_NULL_VOID(titleNode);
505     auto title = AceType::DynamicCast<FrameNode>(titleNode);
506     TransformScale(overDragOffset, title);
507     auto subtitleNode = titleBarNode->GetSubtitle();
508     if (subtitleNode) {
509         auto subtitle = AceType::DynamicCast<FrameNode>(subtitleNode);
510         TransformScale(overDragOffset, subtitle);
511     }
512 
513     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
514 }
515 
TransformScale(float overDragOffset,const RefPtr<FrameNode> & frameNode)516 void TitleBarPattern::TransformScale(float overDragOffset, const RefPtr<FrameNode>& frameNode)
517 {
518     CHECK_NULL_VOID(frameNode);
519     auto renderCtx = frameNode->GetRenderContext();
520     CHECK_NULL_VOID(renderCtx);
521     auto offset = std::clamp(overDragOffset, 0.0f, static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx()));
522     auto scaleRatio = offset / static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx());
523     VectorF scaleValue = VectorF(scaleRatio * 0.1f + 1.0f, scaleRatio * 0.1f + 1.0f);
524     renderCtx->UpdateTransformScale(scaleValue);
525 }
526 
AnimateTo(float offset)527 void TitleBarPattern::AnimateTo(float offset)
528 {
529     if (!animator_) {
530         animator_ = CREATE_ANIMATOR(PipelineBase::GetCurrentContext());
531     }
532     auto animation = AceType::MakeRefPtr<CurveAnimation<float>>(GetCurrentOffset(), offset, Curves::FAST_OUT_SLOW_IN);
533     animation->AddListener([weakScroll = AceType::WeakClaim(this)](float value) {
534         auto titlebar = weakScroll.Upgrade();
535         CHECK_NULL_VOID_NOLOG(titlebar);
536         titlebar->SetTitleStyleByOffset(value);
537         auto host = titlebar->GetHost();
538         CHECK_NULL_VOID(host);
539         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
540         auto pipeline = PipelineContext::GetCurrentContext();
541         if (pipeline) {
542             pipeline->FlushUITasks();
543         }
544     });
545     animator_->ClearInterpolators();
546     animator_->AddInterpolator(animation);
547     animator_->SetDuration(DEFAULT_ANIMATION_DURATION);
548     animator_->Play();
549 }
550 
SetMaxTitleBarHeight()551 void TitleBarPattern::SetMaxTitleBarHeight()
552 {
553     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
554     CHECK_NULL_VOID(titleBarNode);
555     if (titleBarNode->GetSubtitle()) {
556         maxTitleBarHeight_ = static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
557     } else {
558         maxTitleBarHeight_ = static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
559     }
560 }
561 
SetTempTitleBarHeight(float offsetY)562 void TitleBarPattern::SetTempTitleBarHeight(float offsetY)
563 {
564     tempTitleBarHeight_ = defaultTitleBarHeight_ + offsetY;
565     if (tempTitleBarHeight_ < static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) {
566         tempTitleBarHeight_ = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
567     }
568     if (tempTitleBarHeight_ > maxTitleBarHeight_) {
569         tempTitleBarHeight_ = maxTitleBarHeight_;
570     }
571 }
572 
SetTempTitleOffsetY()573 void TitleBarPattern::SetTempTitleOffsetY()
574 {
575     tempTitleOffsetY_ = defaultTitleOffsetY_ + titleMoveDistance_;
576     if (tempTitleOffsetY_ < minTitleOffsetY_) {
577         tempTitleOffsetY_ = minTitleOffsetY_;
578     }
579     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
580         tempTitleOffsetY_ = maxTitleOffsetY_;
581     }
582 }
583 
SetTempSubTitleOffsetY()584 void TitleBarPattern::SetTempSubTitleOffsetY()
585 {
586     tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight();
587     if (tempTitleOffsetY_ < minTitleOffsetY_) {
588         tempSubTitleOffsetY_ = minTitleOffsetY_;
589     }
590     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
591         tempSubTitleOffsetY_ = maxTitleOffsetY_;
592     }
593 }
594 
SetDefaultTitleFontSize()595 void TitleBarPattern::SetDefaultTitleFontSize()
596 {
597     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
598     CHECK_NULL_VOID(titleBarNode);
599     CHECK_NULL_VOID_NOLOG(titleBarNode->GetTitle());
600     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
601     CHECK_NULL_VOID(titleNode);
602     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
603     CHECK_NULL_VOID(textLayoutProperty);
604     if (defaultTitleBarHeight_ == maxTitleBarHeight_) {
605         defaultTitleFontSize_ = textLayoutProperty->GetFontSizeValue(MAX_TITLE_FONT_SIZE);
606     } else {
607         defaultTitleFontSize_ = textLayoutProperty->GetFontSizeValue(MIN_TITLE_FONT_SIZE);
608     }
609 }
610 
SetDefaultSubtitleOpacity()611 void TitleBarPattern::SetDefaultSubtitleOpacity()
612 {
613     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
614     CHECK_NULL_VOID(titleBarNode);
615     CHECK_NULL_VOID(titleBarNode->GetSubtitle());
616     auto subtitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
617     CHECK_NULL_VOID(subtitleNode);
618     auto context = subtitleNode->GetRenderContext();
619     CHECK_NULL_VOID(context);
620     if (defaultTitleBarHeight_ == maxTitleBarHeight_) {
621         defaultSubtitleOpacity_ = context->GetOpacityValue(1.0f);
622     } else {
623         defaultSubtitleOpacity_ = context->GetOpacityValue(0.0f);
624     }
625 }
626 
GetTitleHeight()627 float TitleBarPattern::GetTitleHeight()
628 {
629     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
630     CHECK_NULL_RETURN(titleBarNode, 0.0f);
631     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
632     CHECK_NULL_RETURN(titleNode, 0.0f);
633     auto geometryNode = titleNode->GetGeometryNode();
634     CHECK_NULL_RETURN(geometryNode, 0.0f);
635     return geometryNode->GetFrameSize().Height();
636 }
637 
GetTitleOffsetY()638 float TitleBarPattern::GetTitleOffsetY()
639 {
640     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
641     CHECK_NULL_RETURN(titleBarNode, 0.0f);
642     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
643     CHECK_NULL_RETURN(titleNode, 0.0f);
644     auto geometryNode = titleNode->GetGeometryNode();
645     CHECK_NULL_RETURN(geometryNode, 0.0f);
646     return geometryNode->GetMarginFrameOffset().GetY();
647 }
648 
GetSubTitleHeight()649 float TitleBarPattern::GetSubTitleHeight()
650 {
651     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
652     CHECK_NULL_RETURN(titleBarNode, 0.0f);
653     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
654     CHECK_NULL_RETURN(subTitleNode, 0.0f);
655     auto geometryNode = subTitleNode->GetGeometryNode();
656     CHECK_NULL_RETURN(geometryNode, 0.0f);
657     return geometryNode->GetFrameSize().Height();
658 }
659 
GetSubTitleOffsetY()660 float TitleBarPattern::GetSubTitleOffsetY()
661 {
662     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
663     CHECK_NULL_RETURN(titleBarNode, 0.0f);
664     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
665     CHECK_NULL_RETURN(subTitleNode, 0.0f);
666     auto geometryNode = subTitleNode->GetGeometryNode();
667     CHECK_NULL_RETURN(geometryNode, 0.0f);
668     return geometryNode->GetMarginFrameOffset().GetY();
669 }
670 
UpdateTitleFontSize(const Dimension & tempTitleFontSize)671 void TitleBarPattern::UpdateTitleFontSize(const Dimension& tempTitleFontSize)
672 {
673     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
674     CHECK_NULL_VOID(titleBarNode);
675     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
676     CHECK_NULL_VOID(titleNode);
677     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
678     CHECK_NULL_VOID(textLayoutProperty);
679     textLayoutProperty->UpdateFontSize(tempTitleFontSize);
680     titleNode->MarkModifyDone();
681 }
682 
UpdateSubTitleOpacity(const double & value)683 void TitleBarPattern::UpdateSubTitleOpacity(const double& value)
684 {
685     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
686     CHECK_NULL_VOID(titleBarNode);
687     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
688     CHECK_NULL_VOID(subTitleNode);
689     auto context = subTitleNode->GetRenderContext();
690     CHECK_NULL_VOID(context);
691     context->UpdateOpacity(value);
692 }
693 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)694 bool TitleBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
695 {
696     if (config.skipMeasure && config.skipLayout) {
697         return false;
698     }
699     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
700     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
701     auto titleBarLayoutAlgorithm = DynamicCast<TitleBarLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
702     CHECK_NULL_RETURN(titleBarLayoutAlgorithm, false);
703     UpdateTitleModeChange();
704 
705     initialTitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialTitleOffsetY();
706     isInitialTitle_ = titleBarLayoutAlgorithm->IsInitialTitle();
707     initialSubtitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialSubtitleOffsetY();
708     isInitialSubtitle_ = titleBarLayoutAlgorithm->IsInitialSubtitle();
709     minTitleHeight_ = titleBarLayoutAlgorithm->GetMinTitleHeight();
710     return true;
711 }
712 
UpdateTitleModeChange()713 void TitleBarPattern::UpdateTitleModeChange()
714 {
715     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
716     CHECK_NULL_VOID(titleBarNode);
717     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
718     CHECK_NULL_VOID(titleBarLayoutProperty);
719     auto geometryNode = titleBarNode->GetGeometryNode();
720     CHECK_NULL_VOID(geometryNode);
721 
722     auto titleBarHeight = geometryNode->GetFrameSize().Height();
723     if ((titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) &&
724         !NearZero(maxTitleBarHeight_)) {
725         if (titleBarHeight >= maxTitleBarHeight_) {
726             titleMode_ = NavigationTitleMode::FULL;
727         } else if (NearEqual(titleBarHeight, static_cast<float>(TITLEBAR_HEIGHT_MINI.ConvertToPx()))) {
728             titleMode_ = NavigationTitleMode::MINI;
729         }
730     }
731 }
732 
OnAttachToFrameNode()733 void TitleBarPattern::OnAttachToFrameNode()
734 {
735     auto host = GetHost();
736     CHECK_NULL_VOID(host);
737     host->GetRenderContext()->SetClipToFrame(true);
738 }
739 
OnColorConfigurationUpdate()740 void TitleBarPattern::OnColorConfigurationUpdate()
741 {
742     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
743     CHECK_NULL_VOID(titleBarNode);
744     auto backButton = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
745     CHECK_NULL_VOID(backButton);
746     if (backButton->GetTag() == "Navigator") {
747         backButton = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
748         CHECK_NULL_VOID(backButton);
749     }
750     auto backButtonImgNode = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
751     CHECK_NULL_VOID(backButtonImgNode);
752     auto backButtonImgRender = backButtonImgNode->GetPaintProperty<ImageRenderProperty>();
753     CHECK_NULL_VOID(backButtonImgRender);
754     auto theme = NavigationGetTheme();
755     CHECK_NULL_VOID(theme);
756     backButtonImgRender->UpdateSvgFillColor(theme->GetBackButtonIconColor());
757     backButtonImgNode->MarkModifyDone();
758 }
759 } // namespace OHOS::Ace::NG
760