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