• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/overlay/sheet_presentation_pattern.h"
17 
18 #include "sheet_presentation_property.h"
19 
20 #include "base/geometry/dimension.h"
21 #include "base/log/dump_log.h"
22 #include "base/memory/referenced.h"
23 #include "base/utils/utils.h"
24 #include "base/window/foldable_window.h"
25 #include "core/animation/animation_pub.h"
26 #include "core/animation/curve.h"
27 #include "core/common/container.h"
28 #include "core/components/drag_bar/drag_bar_theme.h"
29 #include "core/components_ng/base/frame_node.h"
30 #include "core/components_ng/event/event_hub.h"
31 #include "core/components_ng/event/gesture_event_hub.h"
32 #include "core/components_ng/event/touch_event.h"
33 #include "core/components_ng/pattern/image/image_pattern.h"
34 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
35 #include "core/components_ng/pattern/overlay/overlay_manager.h"
36 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
37 #include "core/components_ng/pattern/overlay/sheet_manager.h"
38 #include "core/components_ng/pattern/overlay/sheet_style.h"
39 #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h"
40 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
41 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
42 #include "core/components_ng/pattern/stage/page_pattern.h"
43 #include "core/components_ng/pattern/text/text_layout_property.h"
44 #include "core/components_ng/pattern/text_field/text_field_manager.h"
45 #ifdef WINDOW_SCENE_SUPPORTED
46 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
47 #endif
48 #include "core/components_ng/property/property.h"
49 #include "core/components_v2/inspector/inspector_constants.h"
50 #include "core/event/touch_event.h"
51 #include "core/pipeline_ng/pipeline_context.h"
52 
53 namespace OHOS::Ace::NG {
54 namespace {
55 constexpr float SHEET_VISIABLE_ALPHA = 1.0f;
56 constexpr float SHEET_INVISIABLE_ALPHA = 0.0f;
57 constexpr int32_t SHEET_ENTRY_ANIMATION_DURATION = 250;
58 constexpr int32_t SHEET_EXIT_ANIMATION_DURATION = 100;
59 constexpr float SHEET_INVISIABLE_OFFSET = 8.0;
60 constexpr int32_t SHEET_HALF_HEIGHT = 2;
61 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
62 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_X = 1.5_vp;
63 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_Y = 7.32_vp;
64 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_X = 1.5_vp;
65 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_Y = 7.32_vp;
66 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
67 constexpr Dimension ARROW_RADIUS = 2.0_vp;
68 } // namespace
OnModifyDone()69 void SheetPresentationPattern::OnModifyDone()
70 {
71     auto host = GetHost();
72     CHECK_NULL_VOID(host);
73     auto renderContext = host->GetRenderContext();
74     if (renderContext) {
75         auto pipeline = host->GetContext();
76         CHECK_NULL_VOID(pipeline);
77         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
78         CHECK_NULL_VOID(sheetTheme);
79         auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
80         CHECK_NULL_VOID(layoutProperty);
81         auto sheetStyle = layoutProperty->GetSheetStyleValue();
82         BlurStyle blurStyle = static_cast<BlurStyle>(sheetTheme->GetSheetBackgroundBlurStyle());
83         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)
84             && blurStyle != BlurStyle::NO_MATERIAL) {
85             BlurStyleOption options;
86             options.blurStyle = blurStyle;
87             renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
88             renderContext->UpdateBackBlurStyle(sheetStyle.backgroundBlurStyle.value_or(options));
89         } else {
90             renderContext->UpdateBackgroundColor(
91                 sheetStyle.backgroundColor.value_or(sheetTheme->GetSheetBackgoundColor()));
92         }
93     }
94     InitPanEvent();
95     InitPageHeight();
96     InitScrollProps();
97     InitFoldCreaseRegion();
98 }
99 
100 // check device is phone, fold status, and device in landscape
IsPhoneInLandScape()101 bool SheetPresentationPattern::IsPhoneInLandScape()
102 {
103     auto host = GetHost();
104     CHECK_NULL_RETURN(host, false);
105     auto pipelineContext = host->GetContext();
106     CHECK_NULL_RETURN(pipelineContext, false);
107     auto containerId = Container::CurrentId();
108     auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
109     CHECK_NULL_RETURN(foldWindow, false);
110     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
111     CHECK_NULL_RETURN(sheetTheme, false);
112     auto sheetThemeType = sheetTheme->GetSheetType();
113     if (sheetThemeType == "auto" && !foldWindow->IsFoldExpand() &&
114         SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
115         return true;
116     }
117     return false;
118 }
119 
GetSheetTopSafeArea()120 float SheetPresentationPattern::GetSheetTopSafeArea()
121 {
122     auto host = GetHost();
123     CHECK_NULL_RETURN(host, 0.0f);
124     auto pipelineContext = host->GetContext();
125     CHECK_NULL_RETURN(pipelineContext, 0.0f);
126     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
127     auto sheetTopSafeArea = safeAreaInsets.top_.Length();
128     auto windowManager = pipelineContext->GetWindowManager();
129     auto sheetType = GetSheetType();
130     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
131     double deviceHeight = static_cast<double>(SystemProperties::GetDeviceHeight());
132 
133     // full screen subwindow sheet is also WINDOW_MODE_FLOATING, can not enter
134     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING &&
135         !NearEqual(windowGlobalRect.Height(), deviceHeight)) {
136         sheetTopSafeArea = SHEET_BLANK_FLOATING_STATUS_BAR.ConvertToPx();
137     } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE &&
138                AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
139         sheetTopSafeArea = 0.0f;
140     }
141     return sheetTopSafeArea;
142 }
143 
InitPageHeight()144 void SheetPresentationPattern::InitPageHeight()
145 {
146     auto pipelineContext = PipelineContext::GetCurrentContext();
147     CHECK_NULL_VOID(pipelineContext);
148     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
149     auto currentTopSafeArea = sheetTopSafeArea_;
150     TAG_LOGD(AceLogTag::ACE_SHEET, "statusBarHeight of sheet by GetSafeAreaWithoutProcess : %{public}u",
151         safeAreaInsets.top_.Length());
152     sheetTopSafeArea_ =
153         GetSheetType() != SheetType::SHEET_BOTTOMLANDSPACE ? safeAreaInsets.top_.Length() : .0f;
154     auto showInPage =
155         GetLayoutProperty<SheetPresentationProperty>()->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
156     auto overlay = GetOverlayManager();
157     if (overlay && overlay->IsRootExpansive() && showInPage) {
158         sheetTopSafeArea_ = .0f;
159     }
160 
161     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
162     CHECK_NULL_VOID(layoutProperty);
163     auto sheetStyle = layoutProperty->GetSheetStyleValue();
164     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
165         IsPhoneInLandScape()) {
166         sheetTopSafeArea_ = 0.0f;
167     }
168     auto windowManager = pipelineContext->GetWindowManager();
169     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
170     double deviceHeight = static_cast<double>(SystemProperties::GetDeviceHeight());
171     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING &&
172         !NearEqual(windowGlobalRect.Height(), deviceHeight)) {
173         sheetTopSafeArea_ = SHEET_BLANK_FLOATING_STATUS_BAR.ConvertToPx();
174     }
175     TAG_LOGD(AceLogTag::ACE_SHEET, "sheetTopSafeArea of sheet is : %{public}f", sheetTopSafeArea_);
176     if (!NearEqual(currentTopSafeArea, sheetTopSafeArea_)) {
177         topSafeAreaChanged_ = true;
178     }
179     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
180     CHECK_NULL_VOID(sheetTheme);
181     sheetThemeType_ = sheetTheme->GetSheetType();
182     InitSheetMode();
183 }
184 
InitScrollProps()185 void SheetPresentationPattern::InitScrollProps()
186 {
187     auto host = GetHost();
188     CHECK_NULL_VOID(host);
189     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
190     CHECK_NULL_VOID(scrollNode);
191     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
192     CHECK_NULL_VOID(scrollPattern);
193 
194     // When sheet content height is larger than sheet height,
195     // the sheet height should set scroll always enabled.
196     scrollPattern->SetAlwaysEnabled(scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && IsScrollable());
197 }
198 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)199 bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap(
200     const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
201 {
202     if (config.skipMeasure && config.skipLayout) {
203         return false;
204     }
205     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
206     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
207     auto sheetLayoutAlgorithm =
208         DynamicCast<SheetPresentationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
209     CHECK_NULL_RETURN(sheetLayoutAlgorithm, false);
210     InitPageHeight();
211     if (sheetLayoutAlgorithm->GetSheetMaxHeight() > 0) {
212         pageHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight();
213         sheetMaxHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight() - sheetTopSafeArea_;
214         sheetMaxWidth_ = sheetLayoutAlgorithm->GetSheetMaxWidth();
215         centerHeight_ = sheetLayoutAlgorithm->GetCenterHeight();
216         if (!NearEqual(sheetOffsetX_, sheetLayoutAlgorithm->GetSheetOffsetX()) ||
217             !NearEqual(sheetOffsetY_, sheetLayoutAlgorithm->GetSheetOffsetY())) {
218             sheetOffsetX_ = sheetLayoutAlgorithm->GetSheetOffsetX();
219             sheetOffsetY_ = sheetLayoutAlgorithm->GetSheetOffsetY();
220             arrowOffset_ = OffsetF(sheetLayoutAlgorithm->GetArrowOffsetX(), .0f);
221             windowChanged_ = true;
222         }
223     }
224     InitialLayoutProps();
225     UpdateFontScaleStatus();
226     UpdateDragBarStatus();
227     UpdateCloseIconStatus();
228     UpdateTitlePadding();
229     UpdateSheetTitle();
230     ClipSheetNode();
231     CheckBuilderChange();
232     if (GetSheetType() != SheetType::SHEET_POPUP) {
233         if (windowRotate_) {
234             // When rotating the screen,
235             // first switch the sheet to the position corresponding to the proportion before rotation
236             TranslateTo(pageHeight_ - height_);
237             windowRotate_ = false;
238         } else {
239             // After rotation, if need to avoid the keyboard, trigger the avoidance behavior
240             AvoidSafeArea();
241         }
242     }
243     if (GetSheetType() == SheetType::SHEET_POPUP) {
244         MarkSheetPageNeedRender();
245     }
246     return true;
247 }
248 
CheckBuilderChange()249 void SheetPresentationPattern::CheckBuilderChange()
250 {
251     auto host = GetHost();
252     CHECK_NULL_VOID(host);
253     auto builderNode = GetFirstFrameNodeOfBuilder();
254     CHECK_NULL_VOID(builderNode);
255     auto eventHub = builderNode->GetEventHub<EventHub>();
256     CHECK_NULL_VOID(eventHub);
257     OnAreaChangedFunc onBuilderAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
258                                                      const OffsetF& /* oldOrigin */, const RectF& /* rect */,
259                                                      const OffsetF& /* origin */) {
260         auto sheetNode = sheetNodeWk.Upgrade();
261         CHECK_NULL_VOID(sheetNode);
262         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
263         CHECK_NULL_VOID(sheetPattern);
264         auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
265         CHECK_NULL_VOID(layoutProperty);
266         auto sheetStyle = layoutProperty->GetSheetStyleValue();
267         if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
268             sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
269         }
270     };
271     eventHub->AddInnerOnAreaChangedCallback(builderNode->GetId(), std::move(onBuilderAreaChangedFunc));
272 }
273 
AvoidAiBar()274 void SheetPresentationPattern::AvoidAiBar()
275 {
276     CHECK_NULL_VOID(Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN));
277     if (!IsTypeNeedAvoidAiBar()) {
278         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet need not avoid AiBar.");
279         return;
280     }
281     auto host = GetHost();
282     CHECK_NULL_VOID(host);
283     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
284     CHECK_NULL_VOID(scrollNode);
285     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
286     CHECK_NULL_VOID(scrollPattern);
287     if (NonPositive(scrollPattern->GetScrollableDistance()) || isScrolling_) {
288         return;
289     }
290     auto pipeline = PipelineContext::GetCurrentContext();
291     CHECK_NULL_VOID(pipeline);
292     auto inset = pipeline->GetSafeArea();
293     auto layoutProperty = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
294     layoutProperty->UpdateScrollContentEndOffset(inset.bottom_.Length());
295     TAG_LOGD(AceLogTag::ACE_SHEET, "AvoidAiBar function execution completed");
296     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
297 }
298 
IsScrollable() const299 bool SheetPresentationPattern::IsScrollable() const
300 {
301     auto host = GetHost();
302     CHECK_NULL_RETURN(host, false);
303     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
304     CHECK_NULL_RETURN(scrollNode, false);
305     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
306     CHECK_NULL_RETURN(scrollPattern, false);
307     return Positive(scrollPattern->GetScrollableDistance());
308 }
309 
OnAttachToFrameNode()310 void SheetPresentationPattern::OnAttachToFrameNode()
311 {
312     auto host = GetHost();
313     CHECK_NULL_VOID(host);
314     auto pipelineContext = host->GetContext();
315     CHECK_NULL_VOID(pipelineContext);
316     scale_ = pipelineContext->GetFontScale();
317     InitFoldState();
318     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
319     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
320     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
321     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
322     CHECK_NULL_VOID(targetNode);
323     pipelineContext->AddOnAreaChangeNode(targetNode->GetId());
324     OnAreaChangedFunc onAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
325                                               const OffsetF& /* oldOrigin */, const RectF& /* rect */,
326                                               const OffsetF& /* origin */) {
327         auto sheetNode = sheetNodeWk.Upgrade();
328         CHECK_NULL_VOID(sheetNode);
329         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
330         CHECK_NULL_VOID(sheetPattern);
331         if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
332             sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
333         }
334     };
335     auto eventHub = targetNode->GetEventHub<EventHub>();
336     CHECK_NULL_VOID(eventHub);
337     eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc));
338 
339     auto gesture = host->GetOrCreateGestureEventHub();
340     CHECK_NULL_VOID(gesture);
341     auto touchTask = [](TouchEventInfo& info) {
342         info.SetStopPropagation(true);
343         TAG_LOGD(AceLogTag::ACE_SHEET, "The sheet hits the touch event.");
344     };
345     gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
346     RegisterHoverModeChangeCallback();
347 }
348 
OnDetachFromFrameNode(FrameNode * sheetNode)349 void SheetPresentationPattern::OnDetachFromFrameNode(FrameNode* sheetNode)
350 {
351     CHECK_NULL_VOID(sheetNode);
352     auto pipeline = sheetNode->GetContext();
353     CHECK_NULL_VOID(pipeline);
354     pipeline->RemoveWindowSizeChangeCallback(sheetNode->GetId());
355     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
356     CHECK_NULL_VOID(targetNode);
357     auto eventHub = targetNode->GetEventHub<EventHub>();
358     CHECK_NULL_VOID(eventHub);
359     eventHub->RemoveInnerOnAreaChangedCallback(sheetNode->GetId());
360     if (HasHoverModeChangedCallbackId()) {
361         pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
362     }
363 }
364 
RegisterHoverModeChangeCallback()365 void SheetPresentationPattern::RegisterHoverModeChangeCallback()
366 {
367     auto host = GetHost();
368     CHECK_NULL_VOID(host);
369     auto context = host->GetContext();
370     CHECK_NULL_VOID(context);
371     auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
372         auto pattern = weak.Upgrade();
373         CHECK_NULL_VOID(pattern);
374         auto host = pattern->GetHost();
375         CHECK_NULL_VOID(host);
376         auto context = host->GetContext();
377         CHECK_NULL_VOID(context);
378         AnimationOption optionPosition;
379         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
380         optionPosition.SetCurve(motion);
381         context->FlushUITasks();
382         context->Animate(
383             optionPosition, motion,
384             [host, context]() {
385                 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
386                 context->FlushUITasks();
387             },
388             [weak]() {
389                 auto pattern = weak.Upgrade();
390                 CHECK_NULL_VOID(pattern);
391                 pattern->FireHoverModeChangeCallback();
392             });
393     };
394     auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
395     UpdateHoverModeChangedCallbackId(hoverModeCallId);
396 }
397 
SetSheetBorderWidth(bool isPartialUpdate)398 void SheetPresentationPattern::SetSheetBorderWidth(bool isPartialUpdate)
399 {
400     auto host = GetHost();
401     CHECK_NULL_VOID(host);
402     auto pipeline = host->GetContext();
403     CHECK_NULL_VOID(pipeline);
404     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
405     CHECK_NULL_VOID(sheetTheme);
406     auto sheetType = GetSheetType();
407     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
408     CHECK_NULL_VOID(layoutProperty);
409     auto sheetStyle = layoutProperty->GetSheetStyleValue();
410     auto renderContext = host->GetRenderContext();
411     CHECK_NULL_VOID(renderContext);
412     renderContext->SetClipToBounds(true);
413     if (sheetStyle.borderWidth.has_value()) {
414         auto sheetRadius = sheetTheme->GetSheetRadius();
415         auto borderWidth = sheetStyle.borderWidth.value();
416         BorderRadiusProperty borderRadius;
417         if ((sheetType == SheetType::SHEET_CENTER) || (sheetType == SheetType::SHEET_POPUP)) {
418             borderRadius.SetRadius(sheetRadius);
419         } else {
420             borderRadius = BorderRadiusProperty(sheetRadius, sheetRadius, 0.0_vp, 0.0_vp);
421             borderWidth.bottomDimen = 0.0_vp;
422         }
423         renderContext->UpdateBorderRadius(borderRadius);
424         layoutProperty->UpdateBorderWidth(borderWidth);
425         renderContext->UpdateBorderWidth(borderWidth);
426     } else if (renderContext->GetBorderWidth().has_value() && !isPartialUpdate) {
427         BorderWidthProperty borderWidth;
428         borderWidth.SetBorderWidth(0.0_vp);
429         layoutProperty->UpdateBorderWidth(borderWidth);
430         renderContext->UpdateBorderWidth(borderWidth);
431     }
432 
433     SetSheetOuterBorderWidth(sheetTheme, sheetStyle);
434 }
435 
436 // initial drag gesture event
InitPanEvent()437 void SheetPresentationPattern::InitPanEvent()
438 {
439     auto host = GetHost();
440     CHECK_NULL_VOID(host);
441 
442     auto hub = host->GetEventHub<EventHub>();
443     CHECK_NULL_VOID(hub);
444     auto gestureHub = hub->GetOrCreateGestureEventHub();
445     CHECK_NULL_VOID(gestureHub);
446     if (panEvent_) {
447         return;
448     }
449 
450     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& event) {
451         auto pattern = weak.Upgrade();
452         if (pattern) {
453             pattern->HandleDragStart();
454         }
455     };
456 
457     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
458         auto pattern = weak.Upgrade();
459         if (pattern) {
460             pattern->HandleDragUpdate(info);
461         }
462     };
463 
464     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
465         auto pattern = weak.Upgrade();
466         if (pattern) {
467             pattern->HandleDragEnd(info.GetMainVelocity());
468         }
469     };
470     auto actionCancelTask = [weak = WeakClaim(this)]() {
471         auto pattern = weak.Upgrade();
472         if (pattern) {
473             pattern->HandleDragEnd({});
474         }
475     };
476     PanDirection panDirection;
477     panDirection.type = PanDirection::VERTICAL;
478     panEvent_ = MakeRefPtr<PanEvent>(
479         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
480     gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
481 }
482 
HandleDragStart()483 void SheetPresentationPattern::HandleDragStart()
484 {
485     InitScrollProps();
486     SetIsDragging(true);
487     if (animation_ && isAnimationProcess_) {
488         AnimationUtils::StopAnimation(animation_);
489         isAnimationBreak_ = true;
490     }
491     currentOffset_ = 0.0f;
492     isDirectionUp_ = true;
493 }
494 
HandleDragUpdate(const GestureEvent & info)495 void SheetPresentationPattern::HandleDragUpdate(const GestureEvent& info)
496 {
497     auto sheetType = GetSheetType();
498     if (sheetType == SheetType::SHEET_POPUP) {
499         return;
500     }
501     auto mainDelta = static_cast<float>(info.GetMainDelta());
502     auto host = GetHost();
503     CHECK_NULL_VOID(host);
504     auto tempOffset = currentOffset_;
505     auto detentSize = sheetDetentHeight_.size();
506     if (detentSize <= 0) {
507         return;
508     }
509     auto height = GetSheetHeightBeforeDragUpdate();
510     auto maxDetentSize = GetMaxSheetHeightBeforeDragUpdate();
511     if (GreatNotEqual((height - currentOffset_), maxDetentSize)) {
512         if (LessNotEqual(mainDelta, 0) && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
513             auto friction = CalculateFriction((height - currentOffset_) / sheetMaxHeight_);
514             mainDelta = mainDelta * friction;
515         }
516     }
517     currentOffset_ = currentOffset_ + mainDelta;
518     if (NearEqual(currentOffset_, tempOffset)) {
519         return;
520     }
521     auto pageHeight = GetPageHeightWithoutOffset();
522     auto offset = pageHeight - height + currentOffset_;
523     if (LessOrEqual(offset, (pageHeight - sheetMaxHeight_))) {
524         offset = pageHeight - sheetMaxHeight_;
525         currentOffset_ = height - sheetMaxHeight_;
526     }
527     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && currentOffset_ < 0;
528     if (isNeedChangeScrollHeight) {
529         ChangeScrollHeight(height - currentOffset_);
530     }
531     ProcessColumnRect(height - currentOffset_);
532     auto renderContext = host->GetRenderContext();
533     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
534     if (IsSheetBottomStyle()) {
535         OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
536     }
537 }
538 
HandleDragEnd(float dragVelocity)539 void SheetPresentationPattern::HandleDragEnd(float dragVelocity)
540 {
541     isNeedProcessHeight_ = true;
542     SetIsDragging(false);
543     auto sheetDetentsSize = sheetDetentHeight_.size();
544     if ((sheetDetentsSize == 0) || (GetSheetType() == SheetType::SHEET_POPUP)) {
545         return;
546     }
547     float upHeight = 0.0f;
548     float downHeight = 0.0f;
549     auto height = GetSheetHeightBeforeDragUpdate();
550     auto currentSheetHeight =
551         GreatNotEqual((height - currentOffset_), sheetMaxHeight_) ? sheetMaxHeight_ : (height - currentOffset_);
552     start_ = currentSheetHeight;
553     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet HandleDragEnd, current height is: %{public}f", currentSheetHeight);
554 
555     // record the drag position
556     uint32_t detentsLowerPos = 0;
557     uint32_t detentsUpperPos = 0;
558     ComputeDetentsPos(currentSheetHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
559 
560     // when drag velocity is under the threshold and the sheet height is not in the middle of lower and upper bound.
561     if ((LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) &&
562         (!NearEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight)))) {
563         // check whether the lower or upper index is closer to the current height of the sheet page
564         if (GreatNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
565             if (NearZero(downHeight)) {
566                 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
567             } else {
568                 detentsIndex_ = detentsLowerPos;
569                 ChangeSheetHeight(downHeight);
570                 ChangeSheetPage(height);
571                 SheetTransition(true, std::abs(dragVelocity));
572             }
573         } else if (LessNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
574             detentsIndex_ = detentsUpperPos;
575             ChangeSheetHeight(upHeight);
576             ChangeSheetPage(height);
577             SheetTransition(true, std::abs(dragVelocity));
578         }
579     } else {
580         // when drag velocity is over the threshold
581         if (GreatOrEqual(dragVelocity, 0.0f)) {
582             if (NearZero(downHeight)) {
583                 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
584             } else {
585                 detentsIndex_ = detentsLowerPos;
586                 ChangeSheetHeight(downHeight);
587                 ChangeSheetPage(height);
588                 SheetTransition(true, std::abs(dragVelocity));
589             }
590         } else {
591             detentsIndex_ = detentsUpperPos;
592             ChangeSheetHeight(upHeight);
593             ChangeSheetPage(height);
594             SheetTransition(true, std::abs(dragVelocity));
595         }
596     }
597 
598     // match the sorted detents index to the unsorted one
599     auto detentHeight = sheetDetentHeight_[detentsIndex_];
600     auto pos = std::find(unSortedSheetDentents_.begin(), unSortedSheetDentents_.end(), detentHeight);
601     if (pos != std::end(unSortedSheetDentents_)) {
602         auto idx = static_cast<uint32_t>(std::distance(unSortedSheetDentents_.begin(), pos));
603         detentsFinalIndex_ = idx;
604     }
605 }
606 
ComputeDetentsPos(float currentSheetHeight,float & upHeight,float & downHeight,uint32_t & detentsLowerPos,uint32_t & detentsUpperPos)607 void SheetPresentationPattern::ComputeDetentsPos(
608     float currentSheetHeight, float& upHeight, float& downHeight, uint32_t& detentsLowerPos, uint32_t& detentsUpperPos)
609 {
610     // when drag the sheet page, find the lower and upper index range
611     auto lowerIter = std::lower_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
612     auto upperIter = std::upper_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
613     auto sheetDetentsSize = sheetDetentHeight_.size();
614     if (sheetDetentsSize <= 0) {
615         TAG_LOGI(AceLogTag::ACE_SHEET, "SheetDetentsSize is less than or equal to 0");
616         return;
617     }
618     if (lowerIter == sheetDetentHeight_.end() || upperIter == sheetDetentHeight_.end()) {
619         // when drag over the highest sheet page
620         upHeight = sheetDetentHeight_[sheetDetentsSize - 1];
621         downHeight = sheetDetentHeight_[sheetDetentsSize - 1];
622         detentsLowerPos = sheetDetentsSize - 1;
623         detentsUpperPos = sheetDetentsSize - 1;
624     } else {
625         auto lowerPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), lowerIter));
626         auto upperPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), upperIter));
627         if (lowerPosition == 0) {
628             upHeight = sheetDetentHeight_[lowerPosition];
629             downHeight = 0;
630         } else {
631             // the first largest height greater than the currentsheet height
632             upHeight = sheetDetentHeight_[upperPosition];
633 
634             // the largest height lower than the currentsheet height
635             downHeight = sheetDetentHeight_[lowerPosition - 1];
636             detentsLowerPos = lowerPosition - 1;
637             detentsUpperPos = upperPosition;
638         }
639     }
640 }
641 
ChangeSheetPage(float height)642 void SheetPresentationPattern::ChangeSheetPage(float height)
643 {
644     if (IsAvoidingKeyboard() && keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL) {
645         return;
646     }
647     ChangeScrollHeight(height);
648     ProcessColumnRect(height);
649 }
650 
OnCoordScrollStart()651 void SheetPresentationPattern::OnCoordScrollStart()
652 {
653     if (animation_ && isAnimationProcess_) {
654         AnimationUtils::StopAnimation(animation_);
655         isAnimationBreak_ = true;
656     }
657     currentOffset_ = 0.0f;
658 }
659 
OnCoordScrollUpdate(float scrollOffset)660 bool SheetPresentationPattern::OnCoordScrollUpdate(float scrollOffset)
661 {
662     if (!GetShowState() || !IsScrollable()) {
663         return false;
664     }
665 
666     auto sheetType = GetSheetType();
667     auto sheetDetentsSize = sheetDetentHeight_.size();
668     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
669         return false;
670     }
671     auto height = GetSheetHeightBeforeDragUpdate();
672     if ((NearZero(currentOffset_)) && (LessNotEqual(scrollOffset, 0.0f)) &&
673         (GreatOrEqual(height, GetMaxSheetHeightBeforeDragUpdate()))) {
674         return false;
675     }
676     auto host = GetHost();
677     CHECK_NULL_RETURN(host, false);
678     currentOffset_ = currentOffset_ + scrollOffset;
679     auto pageHeight = GetPageHeightWithoutOffset();
680     auto offset = pageHeight - height + currentOffset_;
681     if (LessOrEqual(offset, pageHeight - sheetMaxHeight_)) {
682         offset = pageHeight - sheetMaxHeight_;
683         currentOffset_ = height - sheetMaxHeight_;
684     }
685     ProcessColumnRect(height - currentOffset_);
686     auto renderContext = host->GetRenderContext();
687     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
688     return true;
689 }
690 
OnCoordScrollEnd(float dragVelocity)691 void SheetPresentationPattern::OnCoordScrollEnd(float dragVelocity)
692 {
693     HandleDragEnd(dragVelocity);
694 }
695 
InitialLayoutProps()696 void SheetPresentationPattern::InitialLayoutProps()
697 {
698     CheckSheetHeightChange();
699     InitSheetDetents();
700 }
701 
InitialSingleGearHeight(NG::SheetStyle & sheetStyle)702 float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetStyle)
703 {
704     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
705     float sheetHeight = largeHeight;
706     auto sheetNode = GetHost();
707     CHECK_NULL_RETURN(sheetNode, sheetHeight);
708     if (sheetStyle.sheetHeight.sheetMode.has_value()) {
709         if (sheetStyle.sheetHeight.sheetMode == SheetMode::MEDIUM) {
710             sheetHeight = pageHeight_ * MEDIUM_SIZE;
711             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
712                 sheetHeight = pageHeight_ * MEDIUM_SIZE_PRE;
713             }
714         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::LARGE) {
715             sheetHeight = largeHeight;
716         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
717             sheetHeight = GetFitContentHeight();
718             if (sheetHeight > largeHeight) {
719                 sheetHeight = largeHeight;
720             }
721             HandleFitContontChange(sheetHeight);
722         }
723     } else {
724         float height = 0.0f;
725         if (sheetStyle.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
726             height = sheetStyle.sheetHeight.height->ConvertToPxWithSize(sheetMaxHeight_);
727         } else {
728             height = sheetStyle.sheetHeight.height->ConvertToPx();
729         }
730         if (GreatNotEqual(height, largeHeight)) {
731             sheetHeight = largeHeight;
732         } else if (LessNotEqual(height, 0)) {
733             sheetHeight = largeHeight;
734         } else {
735             sheetHeight = height;
736         }
737     }
738     return sheetHeight;
739 }
740 
AvoidSafeArea(bool forceAvoid)741 void SheetPresentationPattern::AvoidSafeArea(bool forceAvoid)
742 {
743     auto sheetType = GetSheetType();
744     if (sheetType == SheetType::SHEET_POPUP || IsCurSheetNeedHalfFoldHover()) {
745         return;
746     }
747     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
748         AvoidKeyboardBySheetMode(forceAvoid);
749         return;
750     }
751     auto host = GetHost();
752     CHECK_NULL_VOID(host);
753     auto pipelineContext = PipelineContext::GetCurrentContext();
754     CHECK_NULL_VOID(pipelineContext);
755     auto manager = pipelineContext->GetSafeAreaManager();
756     if (!forceAvoid && keyboardHeight_ == manager->GetKeyboardInset().Length()) {
757         return;
758     }
759     keyboardHeight_ = manager->GetKeyboardInset().Length();
760     CHECK_NULL_VOID(host->GetFocusHub());
761     auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
762     sheetHeightUp_ = heightUp;
763     if (isDismissProcess_) {
764         TAG_LOGD(AceLogTag::ACE_SHEET,
765             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
766         return;
767     }
768     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet height increase %{public}f.", heightUp);
769     auto offset = pageHeight_ - height_ - heightUp;
770     auto renderContext = host->GetRenderContext();
771     if (isScrolling_) {
772         // if scrolling and keyboard will down, scroll needs to reset.
773         if (NearZero(heightUp)) {
774             ScrollTo(.0f);
775             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
776         } else {
777             sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
778             // Otherwise, sheet is necessary to raise and trigger scroll scrolling
779             // sheet is raised to the top first
780             renderContext->UpdateTransformTranslate(
781                 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
782             // Then adjust the remaining height(heightUp = h - maxH) difference by scrolling
783             ScrollTo(heightUp);
784         }
785     } else {
786         // offset: translate endpoint, calculated from top
787         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
788     }
789     if (IsSheetBottomStyle()) {
790         OnHeightDidChange(height_ + sheetHeightUp_);
791     }
792 }
793 
GetSheetHeightChange()794 float SheetPresentationPattern::GetSheetHeightChange()
795 {
796     // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode
797     // TextFieldManagerNG::GetHeight: the cursor Height + 24vp
798     auto pipelineContext = PipelineContext::GetCurrentContext();
799     CHECK_NULL_RETURN(pipelineContext, .0f);
800     auto manager = pipelineContext->GetSafeAreaManager();
801     auto keyboardInsert = manager->GetKeyboardInset();
802     if (keyboardInsert.Length() == 0) {
803         return 0.f;
804     }
805     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
806     // inputH : Distance from input component's Caret to bottom of screen
807     // = caret's offset + caret's height + 24vp
808     if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() &&
809         !pipelineContext->UsingCaretAvoidMode()) {
810         TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time");
811         return .0f;
812     }
813     float inputH = 0.f;
814     if (pipelineContext->UsingCaretAvoidMode()) {
815         // when user scroll after avoiding keyboard, we need to update scroll offset before avoid keyboard twice.
816         GetCurrentScrollHeight();
817         // when avoiding keyboard twice, recover input height before avoiding is needed.
818         inputH = textFieldManager ? pipelineContext->GetRootHeight() -
819             textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight() - sheetHeightUp_ -
820             scrollHeight_ : 0.f;
821     } else {
822         inputH = textFieldManager ? (pipelineContext->GetRootHeight() - textFieldManager->GetClickPosition().GetY() -
823                                     textFieldManager->GetHeight()) : 0.f;
824     }
825     // keyboardH : keyboard height + height of the bottom navigation bar
826     auto keyboardH = keyboardInsert.Length() + manager->GetSystemSafeArea().bottom_.Length();
827     // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
828     auto inputMinH = keyboardH;
829     // the LARGE sheet is 15vp from the status bar, and SHEET_CENTER's Node height not equal to screen height.
830     auto largeHeight = pipelineContext->GetRootHeight() - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea_;
831     // maxH : height that the sheet can reach the stage = the LARGE sheet - Current sheet height
832     auto maxH = largeHeight - height_;
833     if (inputH >= inputMinH) {
834         // sheet needs not up
835         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet needs not up");
836         return .0f;
837     }
838     // The expected height of the sheet to be lifted
839     auto h = inputMinH - inputH;
840     if (h <= maxH) {
841         RecoverScrollOrResizeAvoidStatus();
842         // sheet is lifted up with h
843         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is lifted up with h = %{public}f", h);
844         return h;
845     }
846     // h > maxH, sheet goes up to the LARGE, then adjust the remaining height(h - maxH) difference by scrolling
847     if (IsResizeWhenAvoidKeyboard()) {
848         // remaing height need to update to (keyboardH - bottomDistance) when in resize mode after translate
849         inputH = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
850         h = inputMinH - inputH;
851     }
852     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is LARGE, and there is [%{public}f] height left to be processed.", h - maxH);
853     isScrolling_ = true;
854     return h - maxH;
855 }
856 
CreatePropertyCallback()857 void SheetPresentationPattern::CreatePropertyCallback()
858 {
859     if (property_) {
860         return;
861     }
862     auto propertyCallback = [weak = AceType::WeakClaim(this)](float position) {
863         auto ref = weak.Upgrade();
864         CHECK_NULL_VOID(ref);
865         ref->OnHeightDidChange(static_cast<int>(position));
866     };
867     property_ = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(0.0, std::move(propertyCallback));
868 }
869 
ModifyFireSheetTransition(float dragVelocity)870 void SheetPresentationPattern::ModifyFireSheetTransition(float dragVelocity)
871 {
872     TAG_LOGD(AceLogTag::ACE_SHEET, "ModifyFireSheetTransition function enter");
873     auto host = GetHost();
874     CHECK_NULL_VOID(host);
875     auto renderContext = host->GetRenderContext();
876     CHECK_NULL_VOID(renderContext);
877     AnimationOption option;
878     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
879         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
880     option.SetCurve(curve);
881     option.SetFillMode(FillMode::FORWARDS);
882     auto offset = UpdateSheetTransitionOffset();
883     CreatePropertyCallback();
884     CHECK_NULL_VOID(property_);
885     renderContext->AttachNodeAnimatableProperty(property_);
886     property_->SetPropertyUnit(PropertyUnit::PIXEL_POSITION);
887 
888     auto finishCallback = [weak = AceType::WeakClaim(this)]() {
889         auto ref = weak.Upgrade();
890         CHECK_NULL_VOID(ref);
891         if (!ref->GetAnimationBreak()) {
892             ref->SetAnimationProcess(false);
893             ref->ChangeSheetPage(ref->height_);
894         } else {
895             ref->isAnimationBreak_ = false;
896         }
897         ref->AvoidAiBar();
898         ref->isNeedProcessHeight_ = false;
899         ref->FireOnDetentsDidChange(ref->height_);
900         ref->preDidHeight_ = ref->height_;
901         ref->isSpringBack_ = false;
902     };
903 
904     isAnimationProcess_ = true;
905 
906     property_->Set(start_);
907     animation_ = AnimationUtils::StartAnimation(
908         option,
909         [weak = AceType::WeakClaim(this), renderContext, offset]() {
910             auto ref = weak.Upgrade();
911             CHECK_NULL_VOID(ref);
912             if (renderContext) {
913                 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
914                 ref->property_->Set(ref->height_ + ref->sheetHeightUp_);
915                 bool isNeedChangeScrollHeight =
916                     ref->scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && ref->isDirectionUp_;
917                 if (isNeedChangeScrollHeight) {
918                     ref->ChangeScrollHeight(ref->height_);
919                 }
920             }
921         },
922         finishCallback);
923 }
924 
925 /**
926  * @brief Get the max height before drag or nestedScroll.
927  * the height is relative to the bottom of screen.
928  */
GetMaxSheetHeightBeforeDragUpdate()929 float SheetPresentationPattern::GetMaxSheetHeightBeforeDragUpdate()
930 {
931     if (IsCurSheetNeedHalfFoldHover()) {
932         return GetPageHeightWithoutOffset() - sheetOffsetY_;
933     }
934     auto sheetDetentsSize = sheetDetentHeight_.size();
935     if (sheetDetentsSize <= 0) {
936         TAG_LOGW(AceLogTag::ACE_SHEET, "sheetDetentsSize is nonPositive");
937         return 0.0f;
938     }
939     // The value can be returned in other scenarios as follows:
940     // 1. bottom sheet tyle : maxHeight is maxDetent.
941     // 2. center and other sheet tyle, except for popup tyle :
942     // maxHeight is the height of the top left corner of sheet from the bottom of screen
943     // 3. scene in setting offsetY : add offsetY to the following value
944     return sheetDetentHeight_[sheetDetentsSize - 1];
945 }
946 
947 /**
948  * @brief Get the height before drag or nestedScroll.
949  * the height is relative to the bottom of screen.
950  */
GetSheetHeightBeforeDragUpdate()951 float SheetPresentationPattern::GetSheetHeightBeforeDragUpdate()
952 {
953     if (IsCurSheetNeedHalfFoldHover()) {
954         return GetPageHeightWithoutOffset() - sheetOffsetY_;
955     }
956     // height_ : from the bottom of screen, after the sheet entry action has ended.
957     // sheetHeightUp_ : increased height to avoid soft keyboard.
958     // -bottomOffsetY_ : increased height by setting offsetY. bottomOffsetY_ is a negative number.
959     return height_ + sheetHeightUp_ - bottomOffsetY_;
960 }
961 
UpdateSheetTransitionOffset()962 float SheetPresentationPattern::UpdateSheetTransitionOffset()
963 {
964     // dentets greater than 1 and no rebound
965     if (!WillSpringBack() && sheetDetentHeight_.size() > 1) {
966         // When avoiding keyboards
967         // don't consider the height difference introduced by avoidance after switching detents
968         sheetHeightUp_ = 0.0f;
969     }
970     // apply to springBack scene
971     // return the offset before drag
972     auto offset = GetPageHeightWithoutOffset() - GetSheetHeightBeforeDragUpdate();
973     return offset;
974 }
975 
SheetTransition(bool isTransitionIn,float dragVelocity)976 void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity)
977 {
978     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDirectionUp_;
979     if ((HasOnHeightDidChange() && IsSheetBottomStyle() && isTransitionIn && isNeedProcessHeight_)
980         || isNeedChangeScrollHeight) {
981         ModifyFireSheetTransition(dragVelocity);
982         return;
983     }
984     auto host = GetHost();
985     CHECK_NULL_VOID(host);
986     AnimationOption option;
987     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
988         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
989     option.SetCurve(curve);
990     option.SetFillMode(FillMode::FORWARDS);
991     auto offset = UpdateSheetTransitionOffset();
992     if (!isTransitionIn) {
993         const auto& overlayManager = GetOverlayManager();
994         CHECK_NULL_VOID(overlayManager);
995         auto maskNode = overlayManager->GetSheetMask(host);
996         if (maskNode) {
997             overlayManager->PlaySheetMaskTransition(maskNode, false);
998         }
999     }
1000     option.SetOnFinishEvent([weak = AceType::WeakClaim(this), isTransitionIn]() {
1001         auto pattern = weak.Upgrade();
1002         CHECK_NULL_VOID(pattern);
1003         if (isTransitionIn) {
1004             if (!pattern->GetAnimationBreak()) {
1005                 pattern->SetAnimationProcess(false);
1006                 pattern->ChangeSheetPage(pattern->height_);
1007             } else {
1008                 pattern->isAnimationBreak_ = false;
1009             }
1010             pattern->AvoidAiBar();
1011             pattern->FireOnDetentsDidChange(pattern->height_);
1012             pattern->isSpringBack_ = false;
1013         } else {
1014             pattern->SetAnimationProcess(false);
1015             const auto& overlayManager = pattern->GetOverlayManager();
1016             CHECK_NULL_VOID(overlayManager);
1017             auto host = pattern->GetHost();
1018             CHECK_NULL_VOID(host);
1019             overlayManager->FireAutoSave(host);
1020             overlayManager->DestroySheet(host, pattern->GetSheetKey());
1021             pattern->FireCallback("false");
1022         }
1023     });
1024     StartSheetTransitionAnimation(option, isTransitionIn, offset);
1025 }
1026 
SheetInteractiveDismiss(BindSheetDismissReason dismissReason,float dragVelocity)1027 void SheetPresentationPattern::SheetInteractiveDismiss(BindSheetDismissReason dismissReason, float dragVelocity)
1028 {
1029     isDirectionUp_ = false;
1030     if (HasShouldDismiss() || HasOnWillDismiss()) {
1031         const auto& overlayManager = GetOverlayManager();
1032         CHECK_NULL_VOID(overlayManager);
1033         overlayManager->SetDismissTarget(DismissTarget(sheetKey_));
1034         auto host = GetHost();
1035         CHECK_NULL_VOID(host);
1036         SheetManager::GetInstance().SetDismissSheet(host->GetId());
1037         if (dismissReason == BindSheetDismissReason::SLIDE_DOWN) {
1038             ProcessColumnRect(height_);
1039             isSpringBack_ = true;
1040             if (HasSheetSpringBack()) {
1041                 CallSheetSpringBack();
1042             } else {
1043                 isDismissProcess_ = false;
1044                 SheetTransition(true);
1045             }
1046         }
1047         CallShouldDismiss();
1048         CallOnWillDismiss(static_cast<int32_t>(dismissReason));
1049     } else {
1050         DismissTransition(false, dragVelocity);
1051     }
1052 }
1053 
DismissTransition(bool isTransitionIn,float dragVelocity)1054 void SheetPresentationPattern::DismissTransition(bool isTransitionIn, float dragVelocity)
1055 {
1056     isDismissProcess_ = true;
1057     const auto& overlayManager = GetOverlayManager();
1058     CHECK_NULL_VOID(overlayManager);
1059     overlayManager->ModalPageLostFocus(GetHost());
1060     if (!isTransitionIn) {
1061         OnWillDisappear();
1062     }
1063     auto sheetType = GetSheetType();
1064     if (sheetType == SheetType::SHEET_POPUP) {
1065         BubbleStyleSheetTransition(isTransitionIn);
1066     } else {
1067         SheetTransition(isTransitionIn, dragVelocity);
1068     }
1069 }
1070 
ChangeScrollHeight(float height)1071 void SheetPresentationPattern::ChangeScrollHeight(float height)
1072 {
1073     auto host = GetHost();
1074     CHECK_NULL_VOID(host);
1075     auto geometryNode = host->GetGeometryNode();
1076     CHECK_NULL_VOID(geometryNode);
1077     auto operationNode = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
1078     CHECK_NULL_VOID(operationNode);
1079     auto perationGeometryNode = operationNode->GetGeometryNode();
1080     CHECK_NULL_VOID(perationGeometryNode);
1081     auto operationHeight = perationGeometryNode->GetFrameSize().Height();
1082     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
1083     CHECK_NULL_VOID(scrollNode);
1084     auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
1085     CHECK_NULL_VOID(scrollProps);
1086     auto scrollHeight = height - operationHeight - resizeDecreasedHeight_;
1087     auto sheetType = GetSheetType();
1088     if ((sheetType == SheetType::SHEET_POPUP) || (sheetType == SheetType::SHEET_CENTER)) {
1089         auto sheetHeight = geometryNode->GetFrameSize().Height();
1090         scrollHeight = sheetHeight - operationHeight - resizeDecreasedHeight_;
1091     }
1092     scrollProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(scrollHeight)));
1093     scrollNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1094 }
1095 
UpdateDragBarStatus()1096 void SheetPresentationPattern::UpdateDragBarStatus()
1097 {
1098     auto host = GetHost();
1099     CHECK_NULL_VOID(host);
1100     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1101     CHECK_NULL_VOID(layoutProperty);
1102     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1103     auto showDragIndicator = sheetStyle.showDragBar.value_or(true);
1104 
1105     auto titleColumn = DynamicCast<FrameNode>(host->GetFirstChild());
1106     CHECK_NULL_VOID(titleColumn);
1107     auto sheetDragBar = DynamicCast<FrameNode>(titleColumn->GetFirstChild());
1108     CHECK_NULL_VOID(sheetDragBar);
1109     auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
1110     CHECK_NULL_VOID(dragBarLayoutProperty);
1111     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1112         dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1113         sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1114         return;
1115     }
1116     if (IsSheetBottomStyle() && (sheetDetentHeight_.size() > 1)) {
1117         if (sheetStyle.isTitleBuilder.has_value()) {
1118             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1119         } else {
1120             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1121         }
1122     } else {
1123         if (sheetStyle.isTitleBuilder.has_value()) {
1124             dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1125         } else {
1126             dragBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
1127         }
1128     }
1129     sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1130 }
1131 
GetCloseIconPosX(const SizeF & sheetSize,const RefPtr<SheetTheme> & sheetTheme)1132 float SheetPresentationPattern::GetCloseIconPosX(const SizeF& sheetSize, const RefPtr<SheetTheme>& sheetTheme)
1133 {
1134     auto closeIconX = sheetSize.Width() - static_cast<float>(SHEET_CLOSE_ICON_WIDTH.ConvertToPx()) -
1135                       static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1136     if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
1137         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1138         closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1139     }
1140     return closeIconX;
1141 }
1142 
IsShowCloseIcon()1143 bool SheetPresentationPattern::IsShowCloseIcon()
1144 {
1145     auto host = GetHost();
1146     CHECK_NULL_RETURN(host, false);
1147     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1148     CHECK_NULL_RETURN(layoutProperty, false);
1149     return layoutProperty->GetSheetStyleValue().showCloseIcon.value_or(true);
1150 }
1151 
GetTitleNode() const1152 RefPtr<FrameNode> SheetPresentationPattern::GetTitleNode() const
1153 {
1154     auto host = GetHost();
1155     CHECK_NULL_RETURN(host, nullptr);
1156     auto operationNode = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
1157     CHECK_NULL_RETURN(operationNode, nullptr);
1158     return DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1159 }
1160 
UpdateTitlePadding()1161 void SheetPresentationPattern::UpdateTitlePadding()
1162 {
1163     auto host = GetHost();
1164     CHECK_NULL_VOID(host);
1165     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1166     CHECK_NULL_VOID(layoutProperty);
1167     if (!layoutProperty->GetSheetStyleValue().isTitleBuilder.has_value()) {
1168         return;
1169     }
1170 
1171     auto titleNode = GetTitleNode();
1172     CHECK_NULL_VOID(titleNode);
1173     auto titleLayoutProperty = DynamicCast<LinearLayoutProperty>(titleNode->GetLayoutProperty());
1174     CHECK_NULL_VOID(titleLayoutProperty);
1175     auto pipeline = host->GetContext();
1176     CHECK_NULL_VOID(pipeline);
1177     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1178     CHECK_NULL_VOID(sheetTheme);
1179     auto showCloseIcon = true;
1180     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN)) {
1181         showCloseIcon = IsShowCloseIcon();
1182     }
1183     PaddingProperty padding;
1184 
1185     // The title bar area is reserved for the close button area size by default.
1186     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1187         auto sheetCloseIconTitleSpace = sheetTheme->IsOuterBorderEnable() ? 0.0_vp : SHEET_CLOSE_ICON_TITLE_SPACE_NEW;
1188         padding.end = CalcLength(showCloseIcon ? sheetCloseIconTitleSpace + SHEET_CLOSE_ICON_WIDTH : 0.0_vp);
1189     } else {
1190         padding.right = CalcLength(SHEET_CLOSE_ICON_TITLE_SPACE + SHEET_CLOSE_ICON_WIDTH);
1191     }
1192     titleLayoutProperty->UpdatePadding(padding);
1193     auto titleColumnPattern = titleNode->GetPattern<LinearLayoutPattern>();
1194     CHECK_NULL_VOID(titleColumnPattern);
1195     titleColumnPattern->CheckLocalized();
1196     titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1197 }
1198 
UpdateCloseIconStatus()1199 void SheetPresentationPattern::UpdateCloseIconStatus()
1200 {
1201     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1202         TAG_LOGI(AceLogTag::ACE_SHEET, "PlatformVersion less or equal to version 10");
1203         return;
1204     }
1205     auto host = GetHost();
1206     CHECK_NULL_VOID(host);
1207     auto pipeline = PipelineContext::GetCurrentContext();
1208     CHECK_NULL_VOID(pipeline);
1209     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1210     CHECK_NULL_VOID(sheetTheme);
1211     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1212     CHECK_NULL_VOID(layoutProperty);
1213     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1214     auto showCloseIcon = IsShowCloseIcon();
1215     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
1216     CHECK_NULL_VOID(sheetCloseIcon);
1217     auto geometryNode = host->GetGeometryNode();
1218     CHECK_NULL_VOID(geometryNode);
1219     auto size = geometryNode->GetFrameSize();
1220     auto closeIconX = GetCloseIconPosX(size, sheetTheme);
1221     auto closeIconY = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1222     OffsetT<Dimension> positionOffset;
1223     positionOffset.SetX(Dimension(closeIconX));
1224     auto sheetType = GetSheetType();
1225     if (sheetType == SheetType::SHEET_POPUP) {
1226         positionOffset.SetY(Dimension(closeIconY) + SHEET_ARROW_HEIGHT);
1227     } else {
1228         positionOffset.SetY(Dimension(closeIconY));
1229     }
1230     auto renderContext = sheetCloseIcon->GetRenderContext();
1231     CHECK_NULL_VOID(renderContext);
1232     TAG_LOGD(AceLogTag::ACE_SHEET, "sheet closeIcon positionOffset info, x is: %{public}s, y is: %{public}s",
1233         positionOffset.GetX().ToString().c_str(), positionOffset.GetY().ToString().c_str());
1234     renderContext->UpdatePosition(positionOffset);
1235     auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
1236     CHECK_NULL_VOID(iconLayoutProperty);
1237     iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1238     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1239 }
1240 
UpdateSheetTitle()1241 void SheetPresentationPattern::UpdateSheetTitle()
1242 {
1243     auto host = GetHost();
1244     CHECK_NULL_VOID(host);
1245     auto pipeline = PipelineContext::GetCurrentContext();
1246     CHECK_NULL_VOID(pipeline);
1247     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1248     CHECK_NULL_VOID(layoutProperty);
1249     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1250     if (sheetStyle.sheetTitle.has_value()) {
1251         auto titleId = GetTitleId();
1252         auto titleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(titleId));
1253         CHECK_NULL_VOID(titleNode);
1254         auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
1255         CHECK_NULL_VOID(titleProp);
1256         titleProp->UpdateContent(sheetStyle.sheetTitle.value());
1257         if (pipeline->GetFontScale() != scale_) {
1258             titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1259         }
1260         titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1261         if (sheetStyle.sheetSubtitle.has_value()) {
1262             auto subtitleId = GetSubtitleId();
1263             auto subtitleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(subtitleId));
1264             CHECK_NULL_VOID(subtitleNode);
1265             auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
1266             CHECK_NULL_VOID(subtitleProp);
1267             subtitleProp->UpdateContent(sheetStyle.sheetSubtitle.value());
1268             subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1269         }
1270     }
1271 }
1272 
UpdateFontScaleStatus()1273 void SheetPresentationPattern::UpdateFontScaleStatus()
1274 {
1275     auto host = GetHost();
1276     CHECK_NULL_VOID(host);
1277     auto pipeline = PipelineContext::GetCurrentContext();
1278     CHECK_NULL_VOID(pipeline);
1279     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1280     CHECK_NULL_VOID(layoutProperty);
1281     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1282     if (pipeline->GetFontScale() != scale_) {
1283         auto operationNode = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
1284         CHECK_NULL_VOID(operationNode);
1285         auto titleColumnNode = DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1286         CHECK_NULL_VOID(titleColumnNode);
1287         auto layoutProps = operationNode->GetLayoutProperty<LinearLayoutProperty>();
1288         CHECK_NULL_VOID(layoutProps);
1289         auto titleLayoutProps = titleColumnNode->GetLayoutProperty<LinearLayoutProperty>();
1290         CHECK_NULL_VOID(titleLayoutProps);
1291         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1292         CHECK_NULL_VOID(sheetTheme);
1293         bool isSheetHasNoTitle = !sheetStyle.isTitleBuilder.has_value();
1294         bool isFontScaledInSystemTitle = sheetStyle.isTitleBuilder.has_value() && !sheetStyle.isTitleBuilder.value() &&
1295                                          GreatNotEqual(pipeline->GetFontScale(), sheetTheme->GetSheetNormalScale());
1296         if (isSheetHasNoTitle || isFontScaledInSystemTitle) {
1297             layoutProps->ClearUserDefinedIdealSize(false, true);
1298             titleLayoutProps->ClearUserDefinedIdealSize(false, true);
1299         } else if (sheetStyle.isTitleBuilder.has_value()) {
1300             layoutProps->UpdateUserDefinedIdealSize(
1301                 CalcSize(std::nullopt, CalcLength(SHEET_OPERATION_AREA_HEIGHT - SHEET_TITLE_AERA_MARGIN)));
1302             titleLayoutProps->UpdateUserDefinedIdealSize(
1303                 CalcSize(std::nullopt, CalcLength(SHEET_OPERATION_AREA_HEIGHT)));
1304             if (sheetStyle.sheetSubtitle.has_value()) {
1305                 layoutProps->UpdateUserDefinedIdealSize(
1306                     CalcSize(std::nullopt, CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - SHEET_TITLE_AERA_MARGIN)));
1307                 titleLayoutProps->UpdateUserDefinedIdealSize(
1308                     CalcSize(std::nullopt,
1309                         CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - SHEET_DOUBLE_TITLE_BOTTON_MARGIN)));
1310             }
1311         }
1312         UpdateSheetTitle();
1313         scale_ = pipeline->GetFontScale();
1314         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1315     }
1316 }
1317 
OnColorConfigurationUpdate()1318 void SheetPresentationPattern::OnColorConfigurationUpdate()
1319 {
1320     auto host = GetHost();
1321     CHECK_NULL_VOID(host);
1322     auto pipeline = PipelineContext::GetCurrentContext();
1323     CHECK_NULL_VOID(pipeline);
1324     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1325     CHECK_NULL_VOID(sheetTheme);
1326     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
1327     CHECK_NULL_VOID(sheetCloseIcon);
1328     auto renderContext = sheetCloseIcon->GetRenderContext();
1329     CHECK_NULL_VOID(renderContext);
1330     renderContext->UpdateBackgroundColor(sheetTheme->GetCloseIconColor());
1331     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1332     auto iconNode = DynamicCast<FrameNode>(sheetCloseIcon->GetChildAtIndex(0));
1333     CHECK_NULL_VOID(iconNode);
1334 
1335     // when api >= 12, use symbol format image, else use image format.
1336     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
1337         SystemProperties::IsNeedSymbol()) {
1338         auto symbolLayoutProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
1339         CHECK_NULL_VOID(symbolLayoutProperty);
1340         symbolLayoutProperty->UpdateSymbolColorList({sheetTheme->GetCloseIconSymbolColor()});
1341     } else {
1342         auto imagePaintProperty = iconNode->GetPaintProperty<ImageRenderProperty>();
1343         CHECK_NULL_VOID(imagePaintProperty);
1344         imagePaintProperty->UpdateSvgFillColor(sheetTheme->GetCloseIconImageColor());
1345     }
1346     iconNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1347 }
1348 
GetWrapperHeight()1349 float SheetPresentationPattern::GetWrapperHeight()
1350 {
1351     auto host = GetHost();
1352     CHECK_NULL_RETURN(host, 0.0f);
1353     auto sheetWrapper = host->GetParent();
1354     CHECK_NULL_RETURN(sheetWrapper, 0.0f);
1355     auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
1356     CHECK_NULL_RETURN(sheetWrapperNode, 0.0f);
1357     auto sheetWrapperGeometryNode = sheetWrapperNode->GetGeometryNode();
1358     CHECK_NULL_RETURN(sheetWrapperGeometryNode, 0.0f);
1359     return sheetWrapperGeometryNode->GetFrameSize().Height();
1360 }
1361 
SheetHeightNeedChanged()1362 bool SheetPresentationPattern::SheetHeightNeedChanged()
1363 {
1364     auto host = GetHost();
1365     CHECK_NULL_RETURN(host, false);
1366     auto sheetGeometryNode = host->GetGeometryNode();
1367     CHECK_NULL_RETURN(sheetGeometryNode, false);
1368     if (!NearEqual(sheetGeometryNode->GetFrameSize().Height(), sheetHeight_) ||
1369         !NearEqual(GetWrapperHeight(), wrapperHeight_)) {
1370         return true;
1371     }
1372     return false;
1373 }
1374 
UpdateMaskBackgroundColor()1375 void SheetPresentationPattern::UpdateMaskBackgroundColor()
1376 {
1377     auto host = GetHost();
1378     CHECK_NULL_VOID(host);
1379     auto pipeline = host->GetContext();
1380     CHECK_NULL_VOID(pipeline);
1381     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1382     CHECK_NULL_VOID(sheetTheme);
1383     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1384     CHECK_NULL_VOID(layoutProperty);
1385     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1386     sheetMaskColor_ = sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor());
1387     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1388         if (sheetStyle.maskColor.has_value()) {
1389             sheetMaskColor_ = sheetStyle.maskColor.value();
1390         } else {
1391             sheetMaskColor_ = Color::TRANSPARENT;
1392         }
1393     } else {
1394         if ((!sheetStyle.interactive.has_value() && GetSheetType() == SheetType::SHEET_POPUP) ||
1395             sheetStyle.interactive.value_or(false)) {
1396             sheetMaskColor_ = Color::TRANSPARENT;
1397         }
1398     }
1399 }
1400 
UpdateMaskBackgroundColorRender()1401 void SheetPresentationPattern::UpdateMaskBackgroundColorRender()
1402 {
1403     auto host = GetHost();
1404     CHECK_NULL_VOID(host);
1405     UpdateMaskBackgroundColor();
1406     auto maskNode = DynamicCast<FrameNode>(host->GetParent());
1407     CHECK_NULL_VOID(maskNode);
1408     auto maskRenderContext = maskNode->GetRenderContext();
1409     CHECK_NULL_VOID(maskRenderContext);
1410     maskRenderContext->UpdateBackgroundColor(sheetMaskColor_);
1411 }
1412 
FireCommonCallback()1413 void SheetPresentationPattern::FireCommonCallback()
1414 {
1415     auto host = GetHost();
1416     CHECK_NULL_VOID(host);
1417     FireOnTypeDidChange();
1418     FireOnWidthDidChange(host);
1419     FireOnHeightDidChange();
1420 }
1421 
CheckSheetHeightChange()1422 void SheetPresentationPattern::CheckSheetHeightChange()
1423 {
1424     auto host = GetHost();
1425     CHECK_NULL_VOID(host);
1426     auto sheetGeometryNode = host->GetGeometryNode();
1427     CHECK_NULL_VOID(sheetGeometryNode);
1428     if (isFirstInit_) {
1429         sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1430         wrapperHeight_ = GetWrapperHeight();
1431         sheetType_ = GetSheetType();
1432         isFirstInit_ = false;
1433     } else {
1434         if (sheetType_ != GetSheetType()) {
1435             if (sheetType_ == SheetType::SHEET_POPUP) {
1436                 MarkSheetPageNeedRender();
1437             }
1438             SetSheetBorderWidth();
1439         }
1440         if (SheetHeightNeedChanged() || (sheetType_ != GetSheetType()) || windowChanged_ || topSafeAreaChanged_) {
1441             sheetType_ = GetSheetType();
1442             sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1443             wrapperHeight_ = GetWrapperHeight();
1444             const auto& overlayManager = GetOverlayManager();
1445             CHECK_NULL_VOID(overlayManager);
1446             auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1447             CHECK_NULL_VOID(layoutProperty);
1448             auto sheetStyle = layoutProperty->GetSheetStyleValue();
1449             overlayManager->ComputeSheetOffset(sheetStyle, host);
1450             if (sheetType_ == SheetType::SHEET_POPUP) {
1451                 auto renderContext = GetRenderContext();
1452                 CHECK_NULL_VOID(renderContext);
1453                 renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_), 0.0f });
1454                 renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
1455                 FireCommonCallback();
1456             } else {
1457                 overlayManager->PlaySheetTransition(host, true, false);
1458             }
1459             auto maskNode = overlayManager->GetSheetMask(host);
1460             if (maskNode) {
1461                 UpdateMaskBackgroundColorRender();
1462             }
1463             windowChanged_ = false;
1464             topSafeAreaChanged_ = false;
1465         }
1466     }
1467     GetBuilderInitHeight();
1468 }
1469 
IsCustomDetentsChanged(SheetStyle sheetStyle)1470 void SheetPresentationPattern::IsCustomDetentsChanged(SheetStyle sheetStyle)
1471 {
1472     unsigned int preDetentsSize = preDetents_.size();
1473     unsigned int userSetDetentsSize = sheetStyle.detents.size();
1474     // if preview detents size is not equal to the new one, set detents index to zero
1475     if (preDetentsSize != userSetDetentsSize) {
1476         detentsFinalIndex_ = 0;
1477         return;
1478     }
1479 
1480     // check whether the new coming one's content is equal to the last time input
1481     unsigned int length = std::min(preDetentsSize, userSetDetentsSize);
1482     for (unsigned int index = 0; index < length; index++) {
1483         if (sheetStyle.detents[index] != preDetents_[index]) {
1484             // if detents has been changed, set detents index to zero
1485             detentsFinalIndex_ = 0;
1486             break;
1487         }
1488     }
1489 }
1490 
InitSheetDetents()1491 void SheetPresentationPattern::InitSheetDetents()
1492 {
1493     // record input detents
1494     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1495     CHECK_NULL_VOID(layoutProperty);
1496     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1497     IsCustomDetentsChanged(sheetStyle);
1498     preDetents_.clear();
1499     sheetDetentHeight_.clear();
1500     unSortedSheetDentents_.clear();
1501     float height = 0.0f;
1502     auto sheetNode = GetHost();
1503     CHECK_NULL_VOID(sheetNode);
1504     auto geometryNode = sheetNode->GetGeometryNode();
1505     CHECK_NULL_VOID(geometryNode);
1506     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1507     auto sheetType = GetSheetType();
1508     auto sheetFrameHeight = geometryNode->GetFrameSize().Height();
1509     auto mediumSize = MEDIUM_SIZE;
1510     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1511         mediumSize = MEDIUM_SIZE_PRE;
1512     }
1513     switch (sheetType) {
1514         case SheetType::SHEET_BOTTOMLANDSPACE:
1515             if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1516                 height = sheetFrameHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1517                 sheetDetentHeight_.emplace_back(height);
1518                 break;
1519             }
1520         case SheetType::SHEET_BOTTOM:
1521             [[fallthrough]];
1522         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
1523             if (sheetStyle.detents.size() <= 0) {
1524                 height = InitialSingleGearHeight(sheetStyle);
1525                 sheetDetentHeight_.emplace_back(height);
1526                 break;
1527             }
1528             for (auto iter : sheetStyle.detents) {
1529                 preDetents_.emplace_back(iter);
1530                 if (iter.sheetMode.has_value()) {
1531                     if (iter.sheetMode == SheetMode::MEDIUM) {
1532                         height = pageHeight_ * mediumSize;
1533                     } else if (iter.sheetMode == SheetMode::LARGE) {
1534                         height = largeHeight;
1535                     } else if (iter.sheetMode == SheetMode::AUTO) {
1536                         height = GetFitContentHeight();
1537                         height = GreatNotEqual(height, largeHeight) ? largeHeight : height;
1538                         HandleFitContontChange(height);
1539                     }
1540                 } else {
1541                     if (iter.height->Unit() == DimensionUnit::PERCENT) {
1542                         height = iter.height->ConvertToPxWithSize(sheetMaxHeight_);
1543                     } else {
1544                         height = iter.height->ConvertToPx();
1545                     }
1546                     if (GreatNotEqual(height, largeHeight)) {
1547                         height = largeHeight;
1548                     } else if (LessNotEqual(height, 0)) {
1549                         height = largeHeight;
1550                     }
1551                 }
1552                 sheetDetentHeight_.emplace_back(height);
1553                 unSortedSheetDentents_.emplace_back(height);
1554             }
1555             std::sort(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), std::less<float>());
1556             sheetDetentHeight_.erase(
1557                 std::unique(sheetDetentHeight_.begin(), sheetDetentHeight_.end()), sheetDetentHeight_.end());
1558             break;
1559         case SheetType::SHEET_CENTER:
1560             height = (centerHeight_ + pageHeight_) / SHEET_HALF_HEIGHT;
1561             sheetDetentHeight_.emplace_back(height);
1562             break;
1563         default:
1564             break;
1565     }
1566 }
1567 
HandleFitContontChange(float height)1568 void SheetPresentationPattern::HandleFitContontChange(float height)
1569 {
1570     if ((NearEqual(height_, sheetFitContentHeight_)) && (!NearEqual(height, sheetFitContentHeight_))) {
1571         ChangeSheetHeight(height);
1572         ChangeSheetPage(height_);
1573         SheetTransition(true);
1574     }
1575     sheetFitContentHeight_ = height;
1576 }
1577 
GetSheetType()1578 SheetType SheetPresentationPattern::GetSheetType()
1579 {
1580     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1581         return SHEET_BOTTOM;
1582     }
1583     SheetType sheetType = SheetType::SHEET_BOTTOM;
1584     auto pipelineContext = PipelineContext::GetCurrentContext();
1585     CHECK_NULL_RETURN(pipelineContext, sheetType);
1586     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1587     CHECK_NULL_RETURN(layoutProperty, sheetType);
1588     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1589     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
1590     TAG_LOGD(AceLogTag::ACE_SHEET, "GetSheetType displayWindowRect info is : %{public}s",
1591         windowGlobalRect.ToString().c_str());
1592     // only bottom when width is less than 600vp
1593     if ((windowGlobalRect.Width() < SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) ||
1594         (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM)) {
1595         return SheetType::SHEET_BOTTOM;
1596     }
1597     if (sheetThemeType_ == "auto") {
1598         GetSheetTypeWithAuto(sheetType);
1599     } else if (sheetThemeType_ == "popup") {
1600         GetSheetTypeWithPopup(sheetType);
1601     }
1602     return sheetType;
1603 }
1604 
InitSheetMode()1605 void SheetPresentationPattern::InitSheetMode()
1606 {
1607     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1608     CHECK_NULL_VOID(layoutProperty);
1609     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1610     scrollSizeMode_ = sheetStyle.scrollSizeMode.value_or(ScrollSizeMode::FOLLOW_DETENT);
1611     keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL);
1612 }
1613 
GetSheetTypeWithAuto(SheetType & sheetType)1614 void SheetPresentationPattern::GetSheetTypeWithAuto(SheetType& sheetType)
1615 {
1616     auto rootHeight = PipelineContext::GetCurrentRootHeight();
1617     auto rootWidth = PipelineContext::GetCurrentRootWidth();
1618     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1619     CHECK_NULL_VOID(layoutProperty);
1620     auto pipeline = PipelineContext::GetCurrentContext();
1621     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1622     CHECK_NULL_VOID(sheetTheme);
1623     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1624 #ifdef PREVIEW
1625     auto container = Container::Current();
1626     CHECK_NULL_VOID(container);
1627     if (container->IsFoldable() && container->GetCurrentFoldStatus() == FoldStatus::EXPAND) {
1628 #else
1629     // when big fold expand
1630     if (IsFoldExpand() && !sheetTheme->IsOnlyBottom()) {
1631 #endif
1632         sheetType = SheetType::SHEET_CENTER;
1633         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN) &&
1634             sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_POPUP) {
1635             sheetType = SheetType::SHEET_POPUP;
1636             return;
1637         }
1638     } else {
1639         if (LessNotEqual(rootHeight, rootWidth)) {
1640             sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
1641         } else {
1642             sheetType = SheetType::SHEET_BOTTOM;
1643         }
1644     }
1645 }
1646 
1647 void SheetPresentationPattern::GetSheetTypeWithPopup(SheetType& sheetType)
1648 {
1649     auto pipelineContext = PipelineContext::GetCurrentContext();
1650     auto rootWidth = PipelineContext::GetCurrentRootWidth();
1651     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1652     CHECK_NULL_VOID(layoutProperty);
1653     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1654 #ifdef PREVIEW
1655     rootWidth = pipelineContext->GetDisplayWindowRectInfo().Width();
1656 #endif
1657     if (GreatOrEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
1658         if (sheetStyle.sheetType.has_value()) {
1659             sheetType = sheetStyle.sheetType.value();
1660         } else {
1661             sheetType = SheetType::SHEET_POPUP;
1662         }
1663     } else if (GreatOrEqual(rootWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
1664                LessNotEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
1665         if (sheetStyle.sheetType.has_value()) {
1666             sheetType = sheetStyle.sheetType.value();
1667         } else {
1668             sheetType = SheetType::SHEET_CENTER;
1669         }
1670     } else {
1671         sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
1672     }
1673     if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
1674         sheetType = SheetType::SHEET_CENTER;
1675     }
1676 }
1677 
1678 void SheetPresentationPattern::BubbleStyleSheetTransition(bool isTransitionIn)
1679 {
1680     auto host = this->GetHost();
1681     CHECK_NULL_VOID(host);
1682     if (!isTransitionIn) {
1683         const auto& overlayManager = GetOverlayManager();
1684         CHECK_NULL_VOID(overlayManager);
1685         auto maskNode = overlayManager->GetSheetMask(host);
1686         if (maskNode) {
1687             overlayManager->PlaySheetMaskTransition(maskNode, false);
1688         }
1689         StartOffsetExitingAnimation();
1690         StartAlphaExitingAnimation(
1691             [weakNode = AceType::WeakClaim(AceType::RawPtr(host)), weakPattern = AceType::WeakClaim(this)]() {
1692                 auto node = weakNode.Upgrade();
1693                 CHECK_NULL_VOID(node);
1694                 auto pattern = weakPattern.Upgrade();
1695                 CHECK_NULL_VOID(pattern);
1696                 const auto& overlayManager = pattern->GetOverlayManager();
1697                 CHECK_NULL_VOID(overlayManager);
1698                 overlayManager->FireAutoSave(node);
1699                 overlayManager->DestroySheet(node, pattern->GetSheetKey());
1700                 pattern->FireCallback("false");
1701             });
1702         overlayManager->CleanSheet(host, GetSheetKey());
1703     }
1704 }
1705 
1706 void SheetPresentationPattern::StartOffsetEnteringAnimation()
1707 {
1708     AnimationOption optionPosition;
1709     optionPosition.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
1710     optionPosition.SetCurve(Curves::FRICTION);
1711     AnimationUtils::Animate(
1712         optionPosition,
1713         [weak = WeakClaim(this)]() {
1714             auto pattern = weak.Upgrade();
1715             CHECK_NULL_VOID(pattern);
1716             auto renderContext = pattern->GetRenderContext();
1717             CHECK_NULL_VOID(renderContext);
1718             renderContext->UpdateTransformTranslate({ 0.0f, Dimension(pattern->sheetOffsetY_), 0.0f });
1719         },
1720         nullptr);
1721 }
1722 
1723 void SheetPresentationPattern::StartAlphaEnteringAnimation(std::function<void()> finish)
1724 {
1725     AnimationOption optionAlpha;
1726     optionAlpha.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
1727     optionAlpha.SetCurve(Curves::SHARP);
1728     AnimationUtils::Animate(
1729         optionAlpha,
1730         [weak = WeakClaim(this)]() {
1731             auto pattern = weak.Upgrade();
1732             CHECK_NULL_VOID(pattern);
1733             auto renderContext = pattern->GetRenderContext();
1734             CHECK_NULL_VOID(renderContext);
1735             renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
1736         },
1737         finish);
1738 }
1739 
1740 void SheetPresentationPattern::StartOffsetExitingAnimation()
1741 {
1742     AnimationOption optionPosition;
1743     optionPosition.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
1744     optionPosition.SetCurve(Curves::FRICTION);
1745     AnimationUtils::Animate(
1746         optionPosition,
1747         [weak = WeakClaim(this)]() {
1748             auto pattern = weak.Upgrade();
1749             CHECK_NULL_VOID(pattern);
1750             auto renderContext = pattern->GetRenderContext();
1751             CHECK_NULL_VOID(renderContext);
1752             renderContext->UpdateTransformTranslate(
1753                 { 0.0f, Dimension(pattern->sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
1754         },
1755         nullptr);
1756 }
1757 
1758 void SheetPresentationPattern::StartAlphaExitingAnimation(std::function<void()> finish)
1759 {
1760     AnimationOption optionAlpha;
1761     optionAlpha.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
1762     optionAlpha.SetCurve(Curves::SHARP);
1763     AnimationUtils::Animate(
1764         optionAlpha,
1765         [weak = WeakClaim(this)]() {
1766             auto pattern = weak.Upgrade();
1767             CHECK_NULL_VOID(pattern);
1768             auto renderContext = pattern->GetRenderContext();
1769             CHECK_NULL_VOID(renderContext);
1770             renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
1771         },
1772         finish);
1773 }
1774 
1775 RefPtr<RenderContext> SheetPresentationPattern::GetRenderContext()
1776 {
1777     auto frameNode = GetHost();
1778     CHECK_NULL_RETURN(frameNode, nullptr);
1779     return frameNode->GetRenderContext();
1780 }
1781 
1782 bool SheetPresentationPattern::PostTask(const TaskExecutor::Task& task, const std::string& name)
1783 {
1784     auto pipeline = PipelineBase::GetCurrentContext();
1785     CHECK_NULL_RETURN(pipeline, false);
1786     auto taskExecutor = pipeline->GetTaskExecutor();
1787     CHECK_NULL_RETURN(taskExecutor, false);
1788     return taskExecutor->PostTask(task, TaskExecutor::TaskType::UI, name);
1789 }
1790 
1791 void SheetPresentationPattern::ResetToInvisible()
1792 {
1793     auto renderContext = GetRenderContext();
1794     CHECK_NULL_VOID(renderContext);
1795     renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
1796     renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
1797 }
1798 
1799 bool SheetPresentationPattern::IsFoldExpand()
1800 {
1801     bool isExpand = false;
1802     auto container = Container::Current();
1803     CHECK_NULL_RETURN(container, false);
1804     auto foldStatus = container->GetCurrentFoldStatus();
1805     isExpand = foldStatus != FoldStatus::FOLDED && foldStatus != FoldStatus::UNKNOWN;
1806     if (isExpand) {
1807         TAG_LOGD(AceLogTag::ACE_SHEET, "Get Fold status IsFoldExpand is true");
1808         return true;
1809     } else {
1810         return false;
1811     }
1812 }
1813 
1814 void SheetPresentationPattern::ChangeSheetHeight(float height)
1815 {
1816     if (!NearEqual(height_, height)) {
1817         isDirectionUp_ = GreatNotEqual(height, height_);
1818         height_ = height;
1819         SetCurrentHeightToOverlay(height_);
1820     }
1821 }
1822 
1823 void SheetPresentationPattern::StartSheetTransitionAnimation(
1824     const AnimationOption& option, bool isTransitionIn, float offset)
1825 {
1826     auto host = GetHost();
1827     CHECK_NULL_VOID(host);
1828     auto context = host->GetRenderContext();
1829     CHECK_NULL_VOID(context);
1830     isAnimationProcess_ = true;
1831     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
1832     CHECK_NULL_VOID(sheetPattern);
1833     auto sheetParent = DynamicCast<FrameNode>(host->GetParent());
1834     CHECK_NULL_VOID(sheetParent);
1835     if (isTransitionIn) {
1836         animation_ = AnimationUtils::StartAnimation(
1837             option,
1838             [context, offset]() {
1839                 if (context) {
1840                     context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1841                 }
1842             },
1843             option.GetOnFinishEvent());
1844     } else {
1845         host->OnAccessibilityEvent(
1846             AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1847         sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
1848             HitTestMode::HTMTRANSPARENT);
1849         animation_ = AnimationUtils::StartAnimation(
1850             option,
1851             [context, this]() {
1852                 if (context) {
1853                     DismissSheetShadow(context);
1854                     context->UpdateTransformTranslate({ 0.0f, pageHeight_, 0.0f });
1855                 }
1856             },
1857             option.GetOnFinishEvent());
1858         const auto& overlayManager = GetOverlayManager();
1859         CHECK_NULL_VOID(overlayManager);
1860         overlayManager->CleanSheet(host, GetSheetKey());
1861     }
1862 }
1863 
1864 void SheetPresentationPattern::DismissSheetShadow(const RefPtr<RenderContext>& context)
1865 {
1866     auto shadow = context->GetBackShadow();
1867     if (!shadow.has_value()) {
1868         shadow = Shadow::CreateShadow(ShadowStyle::None);
1869     }
1870     auto color = shadow->GetColor();
1871     auto newColor = color.ChangeAlpha(0);
1872     shadow->SetColor(newColor);
1873     context->UpdateBackShadow(shadow.value());
1874 }
1875 
1876 void SheetPresentationPattern::ClipSheetNode()
1877 {
1878     auto host = GetHost();
1879     CHECK_NULL_VOID(host);
1880     auto geometryNode = host->GetGeometryNode();
1881     CHECK_NULL_VOID(geometryNode);
1882     auto sheetSize = geometryNode->GetFrameSize();
1883     auto pipeline = PipelineContext::GetCurrentContext();
1884     CHECK_NULL_VOID(pipeline);
1885     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1886     CHECK_NULL_VOID(sheetTheme);
1887     auto renderContext = host->GetRenderContext();
1888     CHECK_NULL_VOID(renderContext);
1889     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1890     CHECK_NULL_VOID(layoutProperty);
1891     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1892     ResetClipShape();
1893     auto sheetType = GetSheetType();
1894     BorderRadiusProperty borderRadius(sheetTheme->GetSheetRadius());
1895     CalculateSheetRadius(borderRadius);
1896     if (IsSheetBottom()) {
1897         // set 1px for avoiding doudble radius black lines.
1898         borderRadius.radiusBottomLeft = 1.0_px;
1899         borderRadius.radiusBottomRight = 1.0_px;
1900     }
1901     renderContext->UpdateBorderRadius(borderRadius);
1902     if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
1903         renderContext->UpdateOuterBorderRadius(borderRadius);
1904     }
1905     if (sheetType == SheetType::SHEET_POPUP) {
1906         std::string clipPath;
1907         clipPath = GetPopupStyleSheetClipPath(sheetSize, borderRadius);
1908         auto path = AceType::MakeRefPtr<Path>();
1909         path->SetValue(clipPath);
1910         path->SetBasicShapeType(BasicShapeType::PATH);
1911         renderContext->UpdateClipShape(path);
1912     }
1913 }
1914 
1915 bool SheetPresentationPattern::IsWindowSizeChangedWithUndefinedReason(
1916     int32_t width, int32_t height, WindowSizeChangeReason type)
1917 {
1918     bool isWindowChanged = false;
1919     if (windowSize_.has_value()) {
1920         isWindowChanged = (type == WindowSizeChangeReason::UNDEFINED &&
1921                            (windowSize_->Width() != width || windowSize_->Height() != height));
1922     }
1923     return isWindowChanged;
1924 }
1925 
1926 void SheetPresentationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1927 {
1928     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet WindowSizeChangeReason type is: %{public}d", type);
1929     auto sheetType = GetSheetType();
1930     if ((type == WindowSizeChangeReason::ROTATION) &&
1931         ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE))) {
1932         windowRotate_ = true;
1933         SetColumnMinSize(true);
1934         // Before rotation, reset to the initial mode sheet ratio of the current vertical or horizontal screen
1935         // It's actually a state where the soft keyboard is not pulled up
1936         if (isScrolling_) {
1937             ScrollTo(.0f);
1938         }
1939     }
1940     if (IsWindowSizeChangedWithUndefinedReason(width, height, type)) {
1941         windowChanged_ = true;
1942     }
1943     windowSize_ = SizeT<int32_t>(width, height);
1944     if (type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::DRAG ||
1945         type == WindowSizeChangeReason::RESIZE) {
1946         windowChanged_ = true;
1947     }
1948 
1949     if (type == WindowSizeChangeReason::ROTATION && sheetType == SheetType::SHEET_CENTER) {
1950         auto recoverTask = [weak = WeakClaim(this), id = Container::CurrentId()] () {
1951             ContainerScope scope(id);
1952             auto pattern = weak.Upgrade();
1953             CHECK_NULL_VOID(pattern);
1954             pattern->RecoverHalfFoldOrAvoidStatus();
1955         };
1956         PostTask(recoverTask, "ArkUISheetHalfFoldStatusSwitch");
1957     }
1958 
1959     auto host = GetHost();
1960     CHECK_NULL_VOID(host);
1961     auto pipelineContext = host->GetContext();
1962     CHECK_NULL_VOID(pipelineContext);
1963     UpdateSheetWhenSheetTypeChanged();
1964     auto windowManager = pipelineContext->GetWindowManager();
1965     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
1966         host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1967     }
1968 }
1969 
1970 void SheetPresentationPattern::TranslateTo(float height)
1971 {
1972     auto host = GetHost();
1973     CHECK_NULL_VOID(host);
1974     auto context = host->GetRenderContext();
1975     CHECK_NULL_VOID(context);
1976     context->UpdateTransformTranslate({ 0.0f, height, 0.0f });
1977 }
1978 
1979 void SheetPresentationPattern::ScrollTo(float height)
1980 {
1981     // height = 0 or height > 0
1982     auto host = GetHost();
1983     CHECK_NULL_VOID(host);
1984     auto scroll = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
1985     CHECK_NULL_VOID(scroll);
1986     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1987     CHECK_NULL_VOID(scrollPattern);
1988     auto layoutProp = scrollPattern->GetLayoutProperty<ScrollLayoutProperty>();
1989     CHECK_NULL_VOID(layoutProp);
1990     auto geometryNode = scroll->GetGeometryNode();
1991     CHECK_NULL_VOID(geometryNode);
1992     // height > 0, Scroll will reduce height, and become scrolling.
1993     isScrolling_ = height > 0;
1994     SetColumnMinSize(!isScrolling_);
1995     if (!AdditionalScrollTo(scroll, height)) {
1996         scrollHeight_ = height;
1997         float maxScrollDecreaseHeight = scrollHeight_;
1998         float maxAvoidSize = keyboardHeight_ - (sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.f);
1999         auto pipelineContext = host->GetContext();
2000         CHECK_NULL_VOID(pipelineContext);
2001         auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2002         /*
2003          * when the screen rotates from portrait to landscape, and the sheet needs to avoid caret twice,
2004          * there is a condition that, the caret position that does not exceed the height of sheet in portrait mode,
2005          * may be exceed the height of sheet in landscape mode. In that case,
2006          * the distance to avoid caret may exceed as well. To keep bindSheet display normally,
2007          * we need to obtain the minimum content height and then the avoidance is made.
2008          */
2009         if (useCaretAvoidMode && NonNegative(maxAvoidSize) && NonNegative(maxAvoidSize - sheetHeightUp_) &&
2010             maxScrollDecreaseHeight > maxAvoidSize - sheetHeightUp_) {
2011             maxScrollDecreaseHeight = maxAvoidSize - sheetHeightUp_;
2012         }
2013         layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
2014             CalcLength(GetScrollHeight() - maxScrollDecreaseHeight)));
2015         auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2016         scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2017     }
2018     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2019 }
2020 
2021 bool SheetPresentationPattern::AdditionalScrollTo(const RefPtr<FrameNode>& scroll, float height)
2022 {
2023     if (NonPositive(height)) {
2024         return false;
2025     }
2026     // If ScrollHeight is larger than childHeight
2027     // there will be a scene that is still larger than childHeight after reducing Scrollheight to moving sheet up
2028     // At this point, even if JumpToPosition is negative, the Scroll will still not to scroll
2029     auto buildContent = GetFirstFrameNodeOfBuilder();
2030     CHECK_NULL_RETURN(buildContent, false);
2031     auto scrollHeight = scroll->GetGeometryNode() ? scroll->GetGeometryNode()->GetFrameSize().Height() : .0f;
2032     auto host = GetHost();
2033     CHECK_NULL_RETURN(host, false);
2034     auto pipelineContext = host->GetContext();
2035     CHECK_NULL_RETURN(pipelineContext, false);
2036     auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2037     if (useCaretAvoidMode) {
2038         scrollHeight = GetScrollHeight();
2039     }
2040     auto childHeight = buildContent->GetGeometryNode() ? buildContent->GetGeometryNode()->GetFrameSize().Height() : .0f;
2041     if (scrollHeight <= childHeight) {
2042         return false;
2043     }
2044     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2045     CHECK_NULL_RETURN(layoutProp, false);
2046     auto geometryNode = scroll->GetGeometryNode();
2047     CHECK_NULL_RETURN(geometryNode, false);
2048     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2049     CHECK_NULL_RETURN(scrollPattern, false);
2050     // Scroll first shrinks to the same size as childHeight, then reduces the height to allow it to scroll
2051     scrollHeight_ = scrollHeight - childHeight + height;
2052     layoutProp->UpdateUserDefinedIdealSize(
2053         CalcSize(std::nullopt, CalcLength(GetScrollHeight() - (scrollHeight - childHeight + height))));
2054     // And then scroll move the content with '-height' offset
2055     auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2056     scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2057     return true;
2058 }
2059 
2060 float SheetPresentationPattern::GetFirstChildHeight() const
2061 {
2062     auto host = GetHost();
2063     CHECK_NULL_RETURN(host, 0.0f);
2064     auto firstChildNode = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
2065     CHECK_NULL_RETURN(firstChildNode, 0.0f);
2066     auto firstChildGeometryNode = firstChildNode->GetGeometryNode();
2067     CHECK_NULL_RETURN(firstChildGeometryNode, 0.0f);
2068     auto titleHeight = firstChildGeometryNode->GetFrameSize().Height();
2069     return titleHeight;
2070 }
2071 
2072 void SheetPresentationPattern::SetColumnMinSize(bool reset)
2073 {
2074     auto buildContent = GetFirstFrameNodeOfBuilder();
2075     CHECK_NULL_VOID(buildContent);
2076     auto geometryNode = buildContent->GetGeometryNode();
2077     CHECK_NULL_VOID(geometryNode);
2078     auto props = buildContent->GetLayoutProperty<LayoutProperty>();
2079     CHECK_NULL_VOID(props);
2080     if (reset) {
2081         props->ResetCalcMinSize();
2082         return;
2083     }
2084     props->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(builderHeight_)));
2085 }
2086 
2087 void SheetPresentationPattern::CalculateSheetRadius(BorderRadiusProperty& sheetRadius)
2088 {
2089     auto host = GetHost();
2090     CHECK_NULL_VOID(host);
2091     auto geometryNode = host->GetGeometryNode();
2092     CHECK_NULL_VOID(geometryNode);
2093     auto sheetSize = geometryNode->GetFrameSize();
2094     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2095     CHECK_NULL_VOID(layoutProperty);
2096     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2097     if (sheetSize.IsPositive()) {
2098         CalculateAloneSheetRadius(sheetRadius.radiusTopLeft, sheetStyle.radius->radiusTopLeft);
2099         CalculateAloneSheetRadius(sheetRadius.radiusTopRight, sheetStyle.radius->radiusTopRight);
2100         CalculateAloneSheetRadius(sheetRadius.radiusBottomLeft, sheetStyle.radius->radiusBottomLeft);
2101         CalculateAloneSheetRadius(sheetRadius.radiusBottomRight, sheetStyle.radius->radiusBottomRight);
2102     }
2103 }
2104 
2105 void SheetPresentationPattern::CalculateAloneSheetRadius(
2106     std::optional<Dimension>& sheetRadius, const std::optional<Dimension>& sheetStyleRadius)
2107 {
2108     auto host = GetHost();
2109     CHECK_NULL_VOID(host);
2110     auto geometryNode = host->GetGeometryNode();
2111     CHECK_NULL_VOID(geometryNode);
2112     auto sheetSize = geometryNode->GetFrameSize();
2113     float half = 0.5f;
2114     if (sheetStyleRadius.has_value() && GreatOrEqual(sheetStyleRadius->Value(), 0.0f)) {
2115         if (sheetStyleRadius->Unit() == DimensionUnit::PERCENT) {
2116             sheetRadius = Dimension(sheetStyleRadius->Value() * sheetSize.Width());
2117         } else {
2118             sheetRadius = sheetStyleRadius;
2119         }
2120     }
2121     // The maximum value of radius is half the width of the page.
2122     if (sheetSize.Width() * half < sheetRadius->ConvertToPx()) {
2123         sheetRadius = Dimension(sheetSize.Width() * half);
2124     }
2125 }
2126 
2127 std::string SheetPresentationPattern::GetPopupStyleSheetClipPath(
2128     const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
2129 {
2130     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
2131     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
2132     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
2133     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
2134     std::string path = MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
2135     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, SHEET_ARROW_HEIGHT.ConvertToPx());
2136     path +=
2137         LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
2138     path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
2139         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P2_OFFSET_Y.ConvertToPx()); // P2
2140     path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
2141         arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
2142         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P4_OFFSET_Y.ConvertToPx()); // P4
2143     path +=
2144         LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
2145     path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
2146     path += ArcTo(
2147         radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
2148     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
2149     path +=
2150         ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0, sheetSize.Width() - radiusBottomRight, sheetSize.Height());
2151     path += LineTo(radiusBottomLeft, sheetSize.Height());
2152     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f, sheetSize.Height() - radiusBottomLeft);
2153     return path + "Z";
2154 }
2155 
2156 std::string SheetPresentationPattern::GetCenterStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2157 {
2158     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2159     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2160     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2161     path += ArcTo(
2162         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2163     path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
2164     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
2165         sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
2166     path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
2167     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
2168         sheetSize.Height() - sheetRadius.ConvertToPx());
2169     return path + "Z";
2170 }
2171 
2172 std::string SheetPresentationPattern::GetBottomStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2173 {
2174     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2175     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2176     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2177     path += ArcTo(
2178         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2179     path += LineTo(sheetSize.Width(), sheetSize.Height());
2180     path += LineTo(0.0f, sheetSize.Height());
2181     return path + "Z";
2182 }
2183 
2184 std::string SheetPresentationPattern::MoveTo(double x, double y)
2185 {
2186     return "M" + std::to_string(x) + " " + std::to_string(y) + " ";
2187 }
2188 
2189 std::string SheetPresentationPattern::LineTo(double x, double y)
2190 {
2191     return "L" + std::to_string(x) + " " + std::to_string(y) + " ";
2192 }
2193 
2194 std::string SheetPresentationPattern::ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y)
2195 {
2196     int32_t sweep_flag = 1;
2197     return "A" + std::to_string(rx) + " " + std::to_string(ry) + " " + std::to_string(rotation) + " " +
2198            std::to_string(arc_flag) + " " + std::to_string(sweep_flag) + " " + std::to_string(x) + " " +
2199            std::to_string(y) + " ";
2200 }
2201 
2202 float SheetPresentationPattern::GetFitContentHeight()
2203 {
2204     auto sheetNode = GetHost();
2205     CHECK_NULL_RETURN(sheetNode, 0.0f);
2206     auto titleColumn = DynamicCast<FrameNode>(sheetNode->GetFirstChild());
2207     CHECK_NULL_RETURN(titleColumn, 0.0f);
2208     auto titleGeometryNode = titleColumn->GetGeometryNode();
2209     auto builderNode = GetFirstFrameNodeOfBuilder();
2210     CHECK_NULL_RETURN(builderNode, 0.0f);
2211     auto builderGeometryNode = builderNode->GetGeometryNode();
2212     return builderGeometryNode->GetMarginFrameSize().Height() + titleGeometryNode->GetFrameSize().Height();
2213 }
2214 void SheetPresentationPattern::ProcessColumnRect(float height)
2215 {
2216     const auto& overlayManager = GetOverlayManager();
2217     CHECK_NULL_VOID(overlayManager);
2218     auto maskNode = overlayManager->GetSheetMask(GetHost());
2219     if (maskNode && maskNode->GetTag() == V2::SHEET_WRAPPER_TAG) {
2220         return;
2221     }
2222     auto sheetNode = GetHost();
2223     CHECK_NULL_VOID(sheetNode);
2224     auto column = DynamicCast<FrameNode>(sheetNode->GetParent());
2225     CHECK_NULL_VOID(column);
2226     auto sheetType = GetSheetType();
2227     auto geometryNode = sheetNode->GetGeometryNode();
2228     CHECK_NULL_VOID(geometryNode);
2229     auto sheetSize = geometryNode->GetFrameSize();
2230     float sheetOffsetX = 0.0f;
2231     float sheetOffsetY = 0.0f;
2232     float sheetWidth = 0.0f;
2233     float sheetHeight = 0.0f;
2234     if (sheetType == SheetType::SHEET_POPUP) {
2235         sheetOffsetX = sheetOffsetX_;
2236         sheetWidth = sheetSize.Width();
2237         sheetOffsetY = sheetOffsetY_;
2238         sheetHeight = sheetSize.Height();
2239     } else if (sheetType == SheetType::SHEET_CENTER) {
2240         sheetOffsetX = sheetOffsetX_;
2241         sheetOffsetY = pageHeight_ - height;
2242         sheetWidth = sheetSize.Width();
2243         sheetHeight = sheetSize.Height();
2244     } else if ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOM_FREE_WINDOW)) {
2245         sheetOffsetY = pageHeight_ - height;
2246         sheetWidth = sheetSize.Width();
2247         sheetOffsetX = sheetOffsetX_;
2248         sheetHeight = height;
2249     } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE) {
2250         sheetOffsetX = sheetOffsetX_;
2251         sheetOffsetY = pageHeight_ - height;
2252         sheetWidth = sheetSize.Width();
2253         sheetHeight = height;
2254     }
2255     auto hub = column->GetEventHub<EventHub>();
2256     auto gestureHub = hub->GetOrCreateGestureEventHub();
2257     std::vector<DimensionRect> mouseResponseRegion;
2258     mouseResponseRegion.emplace_back(Dimension(sheetWidth), Dimension(sheetHeight),
2259         DimensionOffset(Dimension(sheetOffsetX), Dimension(sheetOffsetY)));
2260     gestureHub->SetMouseResponseRegion(mouseResponseRegion);
2261     gestureHub->SetResponseRegion(mouseResponseRegion);
2262 }
2263 
2264 RefPtr<OverlayManager> SheetPresentationPattern::GetOverlayManager()
2265 {
2266     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2267     CHECK_NULL_RETURN(layoutProp, nullptr);
2268     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2269     if (!showInPage) {
2270         return PipelineContext::GetCurrentContext()->GetOverlayManager();
2271     }
2272     auto host = GetHost();
2273     CHECK_NULL_RETURN(host, nullptr);
2274     auto sheetWrapper = host->GetParent();
2275     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2276     auto node = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2277     CHECK_NULL_RETURN(node, nullptr);
2278     RefPtr<OverlayManager> overlay;
2279     if (node->GetTag() == V2::PAGE_ETS_TAG) {
2280         auto pattern = node->GetPattern<PagePattern>();
2281         CHECK_NULL_RETURN(pattern, nullptr);
2282         overlay = pattern->GetOverlayManager();
2283     } else if (node->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
2284         auto pattern = node->GetPattern<NavDestinationPattern>();
2285         CHECK_NULL_RETURN(pattern, nullptr);
2286         overlay = pattern->GetOverlayManager();
2287     }
2288     if (!overlay) {
2289         auto overlayManager = overlayManager_.Upgrade();
2290         overlay = overlayManager;
2291     }
2292     return overlay;
2293 }
2294 
2295 RefPtr<FrameNode> SheetPresentationPattern::GetFirstFrameNodeOfBuilder() const
2296 {
2297     auto host = GetHost();
2298     CHECK_NULL_RETURN(host, nullptr);
2299     auto scrollNode = host->GetChildAtIndex(1);
2300     CHECK_NULL_RETURN(scrollNode, nullptr);
2301     auto buildNode = scrollNode->GetChildAtIndex(0);
2302     CHECK_NULL_RETURN(buildNode, nullptr);
2303     return AceType::DynamicCast<FrameNode>(buildNode->GetFrameChildByIndex(0, true));
2304 }
2305 
2306 void SheetPresentationPattern::GetBuilderInitHeight()
2307 {
2308     auto buildContent = GetFirstFrameNodeOfBuilder();
2309     CHECK_NULL_VOID(buildContent);
2310     auto geometryNode = buildContent->GetGeometryNode();
2311     CHECK_NULL_VOID(geometryNode);
2312     builderHeight_ = geometryNode->GetFrameSize().Height();
2313 }
2314 
2315 RefPtr<FrameNode> SheetPresentationPattern::GetOverlayRoot()
2316 {
2317     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2318     CHECK_NULL_RETURN(layoutProp, nullptr);
2319     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2320     if (!showInPage) {
2321         auto overlay = PipelineContext::GetCurrentContext()->GetOverlayManager();
2322         CHECK_NULL_RETURN(overlay, nullptr);
2323         return AceType::DynamicCast<FrameNode>(overlay->GetRootNode().Upgrade());
2324     }
2325     auto host = GetHost();
2326     CHECK_NULL_RETURN(host, nullptr);
2327     auto sheetWrapper = host->GetParent();
2328     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2329     return AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2330 }
2331 
2332 float SheetPresentationPattern::GetRootOffsetYToWindow()
2333 {
2334     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2335     CHECK_NULL_RETURN(layoutProp, .0f);
2336     const auto& showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2337     CHECK_NULL_RETURN(showInPage, .0f);
2338     const auto& overlayNode = GetOverlayRoot();
2339     CHECK_NULL_RETURN(overlayNode, .0f);
2340     auto parertOffset = overlayNode->GetOffsetRelativeToWindow();
2341     TAG_LOGD(AceLogTag::ACE_OVERLAY, "PageLevel Node's offset to window: %{public}s", parertOffset.ToString().c_str());
2342     return parertOffset.GetY();
2343 }
2344 
2345 void SheetPresentationPattern::DumpAdvanceInfo()
2346 {
2347     DumpLog::GetInstance().AddDesc("------------------------------------------");
2348     DumpLog::GetInstance().AddDesc(
2349         "TargetId: " + std::to_string(static_cast<int32_t>(targetId_)) + " , TargetTag : " + targetTag_);
2350     DumpLog::GetInstance().AddDesc("------------ SheetPage Pattern : ");
2351     DumpLog::GetInstance().AddDesc(
2352         std::string("SheetType: ").append(std::to_string(static_cast<int32_t>(GetSheetType()))));
2353     DumpLog::GetInstance().AddDesc(std::string("SheetPage Node Height: ").append(std::to_string(centerHeight_)));
2354     DumpLog::GetInstance().AddDesc(
2355         std::string("Sheet Height [start from the bottom, KeyboardHeight = 0]: ").append(std::to_string(height_)));
2356     DumpLog::GetInstance().AddDesc(
2357         std::string("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]: ")
2358             .append(std::to_string(sheetMaxHeight_)));
2359     DumpLog::GetInstance().AddDesc(std::string("Page Height: ").append(std::to_string(pageHeight_)));
2360     DumpLog::GetInstance().AddDesc(
2361         std::string("StatusBar Height [current sheetType needed]: ").append(std::to_string(sheetTopSafeArea_)));
2362     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetX: ").append(std::to_string(sheetOffsetX_)));
2363     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetY: ").append(std::to_string(sheetOffsetY_)));
2364     DumpLog::GetInstance().AddDesc(std::string("SheetMaxWidth: ").append(std::to_string(sheetMaxWidth_)));
2365     DumpLog::GetInstance().AddDesc(std::string("FitContent Height: ").append(std::to_string(sheetFitContentHeight_)));
2366     DumpLog::GetInstance().AddDesc("SheetThemeType: " + sheetThemeType_);
2367     DumpLog::GetInstance().AddDesc(std::string("currentOffset: ").append(std::to_string(currentOffset_)));
2368     DumpLog::GetInstance().AddDesc("------------");
2369     DumpLog::GetInstance().AddDesc(
2370         std::string("Height ScrollTo [KeyboardHeight > 0, and is scrolling]: ").append(std::to_string(-scrollHeight_)));
2371     DumpLog::GetInstance().AddDesc(std::string("KeyboardHeight: ").append(std::to_string(keyboardHeight_)));
2372     DumpLog::GetInstance().AddDesc(std::string("is scrolling: ").append(isScrolling_ ? "true" : "false"));
2373     DumpLog::GetInstance().AddDesc(std::string("SheetHeightUp[sheet offset to move up when avoiding keyboard]: ")
2374                                        .append(std::to_string(sheetHeightUp_)));
2375     DumpLog::GetInstance().AddDesc("------------");
2376     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2377     CHECK_NULL_VOID(layoutProperty);
2378     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2379     DumpLog::GetInstance().AddDesc(
2380         std::string("height: ").append(sheetStyle.sheetHeight.height.has_value() ?
2381         sheetStyle.sheetHeight.height->ToString() : "None"));
2382     DumpLog::GetInstance().AddDesc(
2383         ("sheetMode: ") + (sheetStyle.sheetHeight.sheetMode.has_value()
2384                                   ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value()))
2385                                   : "None"));
2386     DumpLog::GetInstance().AddDesc(std::string("detents' Size: ").append(std::to_string(sheetStyle.detents.size())));
2387     DumpLog::GetInstance().AddDesc(std::string("IsShouldDismiss: ").append(shouldDismiss_ ? "true" : "false"));
2388 }
2389 
2390 void SheetPresentationPattern::FireOnHeightDidChange()
2391 {
2392     auto height = 0.0f;
2393     if (!IsSheetBottomStyle()) {
2394         height = centerHeight_;
2395     } else {
2396         height = height_;
2397     }
2398     if (NearEqual(preDidHeight_, height)) {
2399         return;
2400     }
2401     OnHeightDidChange(height);
2402     preDidHeight_ = height;
2403 }
2404 
2405 void SheetPresentationPattern::FireOnDetentsDidChange(float height)
2406 {
2407     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2408     CHECK_NULL_VOID(layoutProperty);
2409     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2410     if (!IsSheetBottomStyle() || NearEqual(preDetentsHeight_, height) ||
2411         LessOrEqual(sheetStyle.detents.size(), 0)) {
2412         return;
2413     }
2414     OnDetentsDidChange(height);
2415     preDetentsHeight_ = height;
2416 }
2417 
2418 void SheetPresentationPattern::FireOnWidthDidChange(RefPtr<FrameNode> sheetNode)
2419 {
2420     auto sheetGeo = sheetNode->GetGeometryNode();
2421     CHECK_NULL_VOID(sheetGeo);
2422     auto width = sheetGeo->GetFrameSize().Width();
2423     if (NearEqual(preWidth_, width)) {
2424         return;
2425     }
2426     onWidthDidChange(width);
2427     preWidth_ = width;
2428 }
2429 
2430 void SheetPresentationPattern::FireOnTypeDidChange()
2431 {
2432     auto sheetType = sheetType_;
2433     if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE || sheetType == SheetType::SHEET_BOTTOM_FREE_WINDOW) {
2434         sheetType = SheetType::SHEET_BOTTOM;
2435     }
2436     if (preType_ == sheetType) {
2437         return;
2438     }
2439     onTypeDidChange(sheetType);
2440     preType_ = sheetType;
2441 }
2442 
2443 RefPtr<FrameNode> SheetPresentationPattern::GetScrollNode()
2444 {
2445     auto host = GetHost();
2446     CHECK_NULL_RETURN(host, nullptr);
2447     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
2448     CHECK_NULL_RETURN(scrollNode, nullptr);
2449     return scrollNode;
2450 }
2451 
2452 bool SheetPresentationPattern::IsScrollOutOfBoundary()
2453 {
2454     auto scrollNode = GetScrollNode();
2455     CHECK_NULL_RETURN(scrollNode, false);
2456     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2457     CHECK_NULL_RETURN(scrollPattern, false);
2458     return scrollPattern->OutBoundaryCallback();
2459 }
2460 
2461 void SheetPresentationPattern::OnScrollStartRecursive(
2462     WeakPtr<NestableScrollContainer> child, float position, float velocity)
2463 {
2464     InitScrollProps();
2465     if (animation_ && isAnimationProcess_) {
2466         AnimationUtils::StopAnimation(animation_);
2467         isAnimationBreak_ = true;
2468     }
2469     currentOffset_ = 0.0f;
2470     isSheetNeedScroll_ = false;
2471     isDirectionUp_ = true;
2472 }
2473 
2474 ScrollResult SheetPresentationPattern::HandleScroll(float scrollOffset, int32_t source, NestedState state,
2475     float velocity)
2476 {
2477     if (state == NestedState::CHILD_CHECK_OVER_SCROLL) {
2478         return {scrollOffset, true};
2479     }
2480     ScrollResult result = {0, true};
2481     if (GreatOrEqual(currentOffset_, 0.0) && (source == SCROLL_FROM_UPDATE) && !isSheetNeedScroll_) {
2482         isSheetNeedScroll_ = true;
2483     }
2484     if (!isSheetNeedScroll_ || IsScrollOutOfBoundary()) {
2485         return {scrollOffset, true};
2486     }
2487     ScrollState scrollState = source == SCROLL_FROM_ANIMATION ? ScrollState::FLING : ScrollState::SCROLL;
2488     if (state == NestedState::CHILD_SCROLL) {
2489         if (scrollState == ScrollState::SCROLL) {
2490             return HandleScrollWithSheet(scrollOffset);
2491         }
2492         if (isSheetPosChanged_) {
2493             HandleDragEnd(scrollOffset > 0 ? SHEET_VELOCITY_THRESHOLD : -SHEET_VELOCITY_THRESHOLD);
2494             isSheetPosChanged_ = false;
2495         }
2496     } else if (state == NestedState::CHILD_OVER_SCROLL) {
2497         isSheetNeedScroll_ = false;
2498         return {scrollOffset, true};
2499     }
2500     return result;
2501 }
2502 
2503 ScrollResult SheetPresentationPattern::HandleScrollWithSheet(float scrollOffset)
2504 {
2505     ScrollResult result = {0, true};
2506     auto sheetType = GetSheetType();
2507     auto sheetDetentsSize = sheetDetentHeight_.size();
2508     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
2509         isSheetNeedScroll_ = false;
2510         return {scrollOffset, true};
2511     }
2512 
2513     auto currentHeightPos = GetSheetHeightBeforeDragUpdate();
2514     bool isDraggingUp = LessNotEqual(scrollOffset, 0.0f);
2515     bool isReachMaxSheetHeight = GreatOrEqual(currentHeightPos, GetMaxSheetHeightBeforeDragUpdate());
2516 
2517     // When dragging up the sheet, and sheet height is larger than sheet content height,
2518     // the sheet height should be updated.
2519     // When dragging up the sheet, and sheet height is less than or equal to sheet content height,
2520     // the sheet content should scrolling.
2521     if ((NearZero(currentOffset_)) && isDraggingUp && isReachMaxSheetHeight) {
2522         isSheetNeedScroll_ = false;
2523         return {scrollOffset, true};
2524     }
2525 
2526     // When dragging up the sheet, and sheet height is larger than max height,
2527     // should set the coefficient of friction.
2528     bool isExceedMaxSheetHeight =
2529         GreatNotEqual((currentHeightPos - currentOffset_), GetMaxSheetHeightBeforeDragUpdate());
2530     bool isNeedCalculateFriction = isExceedMaxSheetHeight && isDraggingUp;
2531     if (isNeedCalculateFriction && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
2532         auto friction = CalculateFriction((currentHeightPos - currentOffset_) / sheetMaxHeight_);
2533         scrollOffset = scrollOffset * friction;
2534     }
2535 
2536     auto host = GetHost();
2537     CHECK_NULL_RETURN(host, result);
2538     currentOffset_ = currentOffset_ + scrollOffset;
2539     auto pageHeight = GetPageHeightWithoutOffset();
2540     auto sheetOffsetInPage = pageHeight - currentHeightPos + currentOffset_;
2541     if (LessOrEqual(sheetOffsetInPage, pageHeight - sheetMaxHeight_)) {
2542         sheetOffsetInPage = pageHeight - sheetMaxHeight_;
2543         currentOffset_ = currentHeightPos - sheetMaxHeight_;
2544     }
2545     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDraggingUp;
2546     if (isNeedChangeScrollHeight) {
2547         ChangeScrollHeight(currentHeightPos - currentOffset_);
2548     }
2549     ProcessColumnRect(currentHeightPos - currentOffset_);
2550     auto renderContext = host->GetRenderContext();
2551     renderContext->UpdateTransformTranslate({ 0.0f, sheetOffsetInPage, 0.0f });
2552     isSheetPosChanged_ = NearZero(scrollOffset) ? false : true;
2553     if (IsSheetBottomStyle()) {
2554         OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
2555     }
2556     isSheetPosChanged_ = true;
2557     return result;
2558 }
2559 
2560 void SheetPresentationPattern::OnScrollEndRecursive(const std::optional<float>& velocity)
2561 {
2562     if (isSheetPosChanged_) {
2563         HandleDragEnd(velocity.value_or(0.f));
2564         isSheetPosChanged_ = false;
2565     }
2566 }
2567 
2568 bool SheetPresentationPattern::HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child)
2569 {
2570     if (isSheetPosChanged_) {
2571         HandleDragEnd(velocity);
2572         isSheetPosChanged_ = false;
2573     }
2574     // Use child edge effect
2575     if (!isSheetNeedScroll_) {
2576         return false;
2577     }
2578     return true;
2579 }
2580 
2581 bool SheetPresentationPattern::IsTypeNeedAvoidAiBar()
2582 {
2583     auto overlay = GetOverlayManager();
2584     auto layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2585     if (overlay && overlay->IsRootExpansive() &&
2586         layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false)) {
2587         return false;
2588     }
2589     return sheetType_ == SheetType::SHEET_BOTTOM || sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE;
2590 }
2591 
2592 void SheetPresentationPattern::IsNeedPlayTransition(const SheetStyle& inputStyle)
2593 {
2594     isPlayTransition_ = false;
2595     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2596     CHECK_NULL_VOID(layoutProperty);
2597     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2598     if (preStyle.sheetHeight.height != inputStyle.sheetHeight.height) {
2599         isPlayTransition_ = true;
2600         return;
2601     }
2602     if (preStyle.detents != inputStyle.detents) {
2603         isPlayTransition_ = true;
2604         return;
2605     }
2606     if (preStyle.sheetHeight.sheetMode != inputStyle.sheetHeight.sheetMode) {
2607         isPlayTransition_ = true;
2608         return;
2609     }
2610     isPlayTransition_ = UpdateIndexByDetentSelection(inputStyle, false) || isPlayTransition_;
2611 }
2612 
2613 bool SheetPresentationPattern::UpdateIndexByDetentSelection(const SheetStyle& inputStyle, bool isFirstTransition)
2614 {
2615     if (!inputStyle.detentSelection.has_value() || inputStyle.detents.size() == 0) {
2616         // when input detentSelection or detent selection is invalid
2617         return false;
2618     }
2619     auto selection = inputStyle.detentSelection.value();
2620     if ((selection.sheetMode.has_value() && selection.sheetMode.value() == NG::SheetMode::AUTO) ||
2621         (selection.height.has_value() && selection.height.value().IsNegative())) {
2622         return false;
2623     }
2624     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2625     CHECK_NULL_RETURN(layoutProperty, false);
2626     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2627     if (!isFirstTransition && preStyle.detentSelection == inputStyle.detentSelection) {
2628         // only when sheet is first pulled up or pre-detents equal to current detents, otherwise false
2629         return false;
2630     }
2631     for (uint32_t index = 0; index < inputStyle.detents.size(); index++) {
2632         if (inputStyle.detents[index] == inputStyle.detentSelection.value()) {
2633             detentsFinalIndex_ = index;
2634             TAG_LOGI(AceLogTag::ACE_SHEET, "find detent selection is %u", index);
2635             return true;
2636         }
2637     }
2638     return false;
2639 }
2640 
2641 void SheetPresentationPattern::OverlayDismissSheet()
2642 {
2643     auto overlayManager = GetOverlayManager();
2644     CHECK_NULL_VOID(overlayManager);
2645     overlayManager->DismissSheet();
2646 }
2647 
2648 void SheetPresentationPattern::OverlaySheetSpringBack()
2649 {
2650     auto overlayManager = GetOverlayManager();
2651     CHECK_NULL_VOID(overlayManager);
2652     overlayManager->SheetSpringBack();
2653 }
2654 
2655 void SheetPresentationPattern::MarkSheetPageNeedRender()
2656 {
2657     auto parentHost = GetHost()->GetParent();
2658     CHECK_NULL_VOID(parentHost);
2659     auto frameNode = AceType::DynamicCast<FrameNode>(parentHost);
2660     CHECK_NULL_VOID(frameNode);
2661     frameNode->MarkNeedRenderOnly();
2662 }
2663 
2664 void SheetPresentationPattern::SetSheetOuterBorderWidth(
2665     const RefPtr<SheetTheme>& sheetTheme, const NG::SheetStyle& sheetStyle)
2666 {
2667     auto host = GetHost();
2668     CHECK_NULL_VOID(host);
2669     auto renderContext = host->GetRenderContext();
2670     CHECK_NULL_VOID(renderContext);
2671     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2672     CHECK_NULL_VOID(layoutProperty);
2673     auto sheetType = GetSheetType();
2674     if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
2675         BorderWidthProperty borderWidth;
2676         BorderWidthProperty outBorderWidth;
2677         BorderColorProperty borderColor;
2678         BorderColorProperty outBorderColor;
2679         borderWidth.SetBorderWidth(0.0_vp);
2680         outBorderWidth.SetBorderWidth(0.0_vp);
2681         if (sheetType != SheetType::SHEET_POPUP) {
2682             borderColor.SetColor(sheetTheme->GetSheetInnerBorderColor());
2683             outBorderColor.SetColor(sheetTheme->GetSheetOuterBorderColor());
2684             renderContext->UpdateOuterBorderColor(outBorderColor);
2685             renderContext->UpdateBorderColor(borderColor);
2686             if (sheetType == SheetType::SHEET_CENTER) {
2687                 borderWidth.SetBorderWidth(sheetTheme->GetSheetInnerBorderWidth());
2688                 outBorderWidth.SetBorderWidth(sheetTheme->GetSheetOuterBorderWidth());
2689             } else {
2690                 borderWidth.leftDimen = sheetTheme->GetSheetInnerBorderWidth();
2691                 borderWidth.topDimen = sheetTheme->GetSheetInnerBorderWidth();
2692                 borderWidth.rightDimen = sheetTheme->GetSheetInnerBorderWidth();
2693                 outBorderWidth.leftDimen = sheetTheme->GetSheetOuterBorderWidth();
2694                 outBorderWidth.topDimen = sheetTheme->GetSheetOuterBorderWidth();
2695                 outBorderWidth.rightDimen = sheetTheme->GetSheetOuterBorderWidth();
2696             }
2697         }
2698         layoutProperty->UpdateBorderWidth(borderWidth);
2699         renderContext->UpdateBorderWidth(borderWidth);
2700         layoutProperty->UpdateOuterBorderWidth(outBorderWidth);
2701         renderContext->UpdateOuterBorderWidth(outBorderWidth);
2702     }
2703 }
2704 
2705 void SheetPresentationPattern::AvoidKeyboardBySheetMode(bool forceAvoid)
2706 {
2707     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::NONE) {
2708         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet will not avoid keyboard.");
2709         return;
2710     }
2711     auto host = GetHost();
2712     CHECK_NULL_VOID(host);
2713     auto pipelineContext = host->GetContext();
2714     CHECK_NULL_VOID(pipelineContext);
2715     auto manager = pipelineContext->GetSafeAreaManager();
2716     if (keyboardHeight_ == manager->GetKeyboardInset().Length() && !forceAvoid) {
2717         return;
2718     }
2719     keyboardHeight_ = manager->GetKeyboardInset().Length();
2720 
2721     if (isDismissProcess_) {
2722         TAG_LOGD(AceLogTag::ACE_SHEET,
2723             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
2724         return;
2725     }
2726 
2727     // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY
2728     if (AvoidKeyboardBeforeTranslate()) {
2729         return;
2730     }
2731 
2732     // 2.handle upward logic
2733     CHECK_NULL_VOID(host->GetFocusHub());
2734     // When bindSheet lift height exceed the max height, hightUp = the remaining height that needs to scroll,
2735     // otherwise, hightUp = the height to be lifted up
2736     auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
2737     sheetHeightUp_ = heightUp;
2738     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet needs to deal with %{public}f height.", heightUp);
2739     auto offset = pageHeight_ - height_ - heightUp;
2740     auto renderContext = host->GetRenderContext();
2741 
2742     // when bindSheet height exceed the max height, lift it up to the maxHeight,
2743     // otherwise, lift it up to show input area
2744     if (isScrolling_) {
2745         if (NearZero(heightUp)) {
2746             // scroll needs to reset first when keyboard is down.
2747             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
2748         } else {
2749             sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
2750             // sheet is raised to the top first
2751             renderContext->UpdateTransformTranslate(
2752                 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
2753         }
2754     } else {
2755         // offset: translate endpoint, calculated from top
2756         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
2757     }
2758 
2759     // 3.deal with left height, scroll or resize
2760     if (isScrolling_) {
2761         AvoidKeyboardAfterTranslate(heightUp);
2762     }
2763 
2764     if (IsSheetBottomStyle()) {
2765         OnHeightDidChange(height_ + sheetHeightUp_);
2766     }
2767 }
2768 
2769 bool SheetPresentationPattern::AvoidKeyboardBeforeTranslate()
2770 {
2771     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY) {
2772         // resize bindSheet need to keep safe distance from keyboard
2773         auto distanceFromBottom = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
2774         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : keyboardHeight_ - distanceFromBottom);
2775         return true;
2776     }
2777     return false;
2778 }
2779 
2780 void SheetPresentationPattern::AvoidKeyboardAfterTranslate(float height)
2781 {
2782     switch (keyboardAvoidMode_) {
2783     case SheetKeyboardAvoidMode::NONE:
2784     case SheetKeyboardAvoidMode::RESIZE_ONLY:
2785         break;
2786     case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE:
2787         // resize bindSheet need to keep safe distance from keyboard
2788         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : height);
2789         break;
2790     case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL:
2791         ScrollTo(height);
2792         break;
2793     default:
2794         TAG_LOGW(AceLogTag::ACE_SHEET, "Invalid keyboard avoid mode %{public}d", keyboardAvoidMode_);
2795         break;
2796     }
2797 }
2798 
2799 void SheetPresentationPattern::DecreaseScrollHeightInSheet(float decreaseHeight)
2800 {
2801     auto host = GetHost();
2802     CHECK_NULL_VOID(host);
2803     auto scroll = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
2804     CHECK_NULL_VOID(scroll);
2805     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2806     CHECK_NULL_VOID(layoutProp);
2807 
2808     // height > 0, Scroll will reduce height, and need to set isScrolling true
2809     isScrolling_ = (decreaseHeight > 0);
2810 
2811     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, Scroll Height reduces by height %{public}f.", decreaseHeight);
2812     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight() - decreaseHeight)));
2813     resizeDecreasedHeight_ = decreaseHeight;
2814     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2815 }
2816 
2817 bool SheetPresentationPattern::IsResizeWhenAvoidKeyboard()
2818 {
2819     return keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE ||
2820         keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY;
2821 }
2822 
2823 void SheetPresentationPattern::ResetClipShape()
2824 {
2825     // need reset clip path,when system clip path change to user defined
2826     auto host = GetHost();
2827     CHECK_NULL_VOID(host);
2828     auto renderContext = host->GetRenderContext();
2829     CHECK_NULL_VOID(renderContext);
2830     renderContext->UpdateClipShape(nullptr);
2831     renderContext->ResetClipShape();
2832 }
2833 
2834 void SheetPresentationPattern::UpdateSheetWhenSheetTypeChanged()
2835 {
2836     auto sheetType = GetSheetType();
2837     if (sheetType_ != sheetType) {
2838         // It can only be MarkOuterBorder When the SheetType switches and the sheetType_ was SHEET_POPUP
2839         if (sheetType_ == SheetType::SHEET_POPUP) {
2840             MarkSheetPageNeedRender();
2841         }
2842         sheetType_ = sheetType;
2843         SetSheetBorderWidth();
2844     }
2845 }
2846 
2847 bool SheetPresentationPattern::IsCurSheetNeedHalfFoldHover()
2848 {
2849     auto host = GetHost();
2850     CHECK_NULL_RETURN(host, false);
2851     auto pipeline = host->GetContext();
2852     CHECK_NULL_RETURN(pipeline, false);
2853     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2854     CHECK_NULL_RETURN(sheetTheme, false);
2855     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2856     CHECK_NULL_RETURN(layoutProperty, false);
2857     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2858     auto enableHoverMode = sheetStyle.enableHoverMode.value_or(false);
2859     bool isHoverMode = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
2860     return isHoverMode && GetSheetType() == SheetType::SHEET_CENTER;
2861 }
2862 
2863 void SheetPresentationPattern::GetCurrentScrollHeight()
2864 {
2865     auto host = GetHost();
2866     CHECK_NULL_VOID(host);
2867     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
2868     CHECK_NULL_VOID(scrollNode);
2869     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2870     CHECK_NULL_VOID(scrollPattern);
2871     auto curOffset = scrollPattern->GetTotalOffset();
2872     if (NearEqual(scrollHeight_, curOffset)) {
2873         return;
2874     }
2875     TAG_LOGD(AceLogTag::ACE_SHEET, "scroll height changed because of user scrolling, %{public}f", curOffset);
2876     scrollHeight_ = curOffset;
2877 }
2878 
2879 void SheetPresentationPattern::InitFoldCreaseRegion()
2880 {
2881     auto host = GetHost();
2882     CHECK_NULL_VOID(host);
2883     auto pipeline = host->GetContext();
2884     CHECK_NULL_VOID(pipeline);
2885     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2886     CHECK_NULL_VOID(sheetTheme);
2887     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2888     CHECK_NULL_VOID(layoutProperty);
2889     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2890     auto enableHoverMode = sheetStyle.enableHoverMode.value_or(false);
2891     if (!enableHoverMode || !currentFoldCreaseRegion_.empty()) {
2892         return;
2893     }
2894     auto container = Container::Current();
2895     CHECK_NULL_VOID(container);
2896     auto displayInfo = container->GetDisplayInfo();
2897     CHECK_NULL_VOID(displayInfo);
2898     currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
2899 }
2900 
2901 Rect SheetPresentationPattern::GetFoldScreenRect() const
2902 {
2903     if (currentFoldCreaseRegion_.empty()) {
2904         TAG_LOGW(AceLogTag::ACE_SHEET, "FoldCreaseRegion is invalid.");
2905         return Rect();
2906     }
2907     return currentFoldCreaseRegion_.front();
2908 }
2909 
2910 void SheetPresentationPattern::FireHoverModeChangeCallback()
2911 {
2912     auto host = GetHost();
2913     CHECK_NULL_VOID(host);
2914     auto pipeline = host->GetContext();
2915     CHECK_NULL_VOID(pipeline);
2916     if (!IsCurSheetNeedHalfFoldHover()) {
2917         TAG_LOGD(AceLogTag::ACE_SHEET, "halfFoldHoverStatus: %{public}d, Sheet is not half folded.",
2918             pipeline->IsHalfFoldHoverStatus());
2919         return;
2920     }
2921     OnHeightDidChange(centerHeight_);
2922 }
2923 
2924 void SheetPresentationPattern::RecoverHalfFoldOrAvoidStatus()
2925 {
2926     TAG_LOGD(AceLogTag::ACE_SHEET, "recover half fold status because of window rotate");
2927     auto host = GetHost();
2928     CHECK_NULL_VOID(host);
2929     auto pipeline = host->GetContext();
2930     CHECK_NULL_VOID(pipeline);
2931     if (IsCurSheetNeedHalfFoldHover()) {
2932         RecoverAvoidKeyboardStatus();
2933     } else {
2934         AvoidSafeArea(true);
2935     }
2936 }
2937 
2938 void SheetPresentationPattern::RecoverAvoidKeyboardStatus()
2939 {
2940     RecoverScrollOrResizeAvoidStatus();
2941     sheetHeightUp_ = 0.f;
2942     OnHeightDidChange(centerHeight_);
2943 }
2944 
2945 void SheetPresentationPattern::RecoverScrollOrResizeAvoidStatus()
2946 {
2947     auto host = GetHost();
2948     CHECK_NULL_VOID(host);
2949     auto scroll = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
2950     CHECK_NULL_VOID(scroll);
2951     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2952     CHECK_NULL_VOID(layoutProp);
2953     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight())));
2954     resizeDecreasedHeight_ = 0.f;
2955     scrollHeight_ = 0.f;
2956     ScrollTo(0.f);
2957     isScrolling_ = false;
2958 }
2959 } // namespace OHOS::Ace::NG
2960