• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/log/dump_log.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/utils.h"
22 #include "base/window/foldable_window.h"
23 #include "core/animation/animation_pub.h"
24 #include "core/animation/curve.h"
25 #include "core/common/ace_engine.h"
26 #include "core/common/container.h"
27 #include "core/components/drag_bar/drag_bar_theme.h"
28 #include "core/components_ng/base/frame_node.h"
29 #include "core/components_ng/event/event_hub.h"
30 #include "core/components_ng/event/gesture_event_hub.h"
31 #include "core/components_ng/event/touch_event.h"
32 #include "core/components_ng/pattern/container_modal/enhance/container_modal_view_enhance.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/overlay/sheet_wrapper_pattern.h"
40 #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h"
41 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
42 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
43 #include "core/components_ng/pattern/stage/page_pattern.h"
44 #include "core/components_ng/pattern/text/text_layout_property.h"
45 #include "core/components_ng/pattern/text_field/text_field_manager.h"
46 #include "core/components_ng/property/accessibility_property_helper.h"
47 #ifdef WINDOW_SCENE_SUPPORTED
48 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
49 #endif
50 #include "core/components_ng/property/property.h"
51 #ifdef ENABLE_ROSEN_BACKEND
52 #include "core/components_ng/render/adapter/rosen_render_context.h"
53 #endif
54 #include "core/components/theme/shadow_theme.h"
55 #include "core/components_v2/inspector/inspector_constants.h"
56 #include "core/event/touch_event.h"
57 #include "core/pipeline_ng/pipeline_context.h"
58 
59 namespace OHOS::Ace::NG {
60 namespace {
61 constexpr float SHEET_VISIABLE_ALPHA = 1.0f;
62 constexpr float SHEET_INVISIABLE_ALPHA = 0.0f;
63 constexpr int32_t SHEET_ENTRY_ANIMATION_DURATION = 250;
64 constexpr int32_t SHEET_EXIT_ANIMATION_DURATION = 100;
65 constexpr float SHEET_INVISIABLE_OFFSET = 8.0;
66 constexpr int32_t SHEET_HALF_HEIGHT = 2;
67 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
68 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_X = 1.5_vp;
69 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_Y = 7.32_vp;
70 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_X = 1.5_vp;
71 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_Y = 7.32_vp;
72 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
73 constexpr Dimension ARROW_CORNER_P2_OFFSET_X = 12.8_vp;
74 constexpr Dimension ARROW_CORNER_P2_OFFSET_Y = 7.6_vp;
75 constexpr Dimension ARROW_CORNER_P4_OFFSET_Y = 6.0_vp;
76 constexpr Dimension ARROW_RADIUS = 2.0_vp;
77 constexpr Dimension SUBWINDOW_SHEET_TRANSLATION = 80.0_vp;
78 } // namespace
OnModifyDone()79 void SheetPresentationPattern::OnModifyDone()
80 {
81     auto host = GetHost();
82     CHECK_NULL_VOID(host);
83     auto renderContext = host->GetRenderContext();
84     if (renderContext) {
85         auto pipeline = host->GetContext();
86         CHECK_NULL_VOID(pipeline);
87         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
88         CHECK_NULL_VOID(sheetTheme);
89         auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
90         CHECK_NULL_VOID(layoutProperty);
91         auto sheetStyle = layoutProperty->GetSheetStyleValue();
92         BlurStyle blurStyle = static_cast<BlurStyle>(sheetTheme->GetSheetBackgroundBlurStyle());
93         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)
94             && blurStyle != BlurStyle::NO_MATERIAL) {
95             BlurStyleOption options;
96             options.blurStyle = blurStyle;
97             renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
98             renderContext->UpdateBackBlurStyle(sheetStyle.backgroundBlurStyle.value_or(options));
99         } else {
100             renderContext->UpdateBackgroundColor(
101                 sheetStyle.backgroundColor.value_or(sheetTheme->GetSheetBackgoundColor()));
102         }
103     }
104     InitPanEvent();
105     InitPageHeight();
106     InitScrollProps();
107     UpdateSheetType();
108     InitFoldCreaseRegion();
109 }
110 
111 // check device is phone, fold status, and device in landscape
IsPhoneInLandScape()112 bool SheetPresentationPattern::IsPhoneInLandScape()
113 {
114     auto host = GetHost();
115     CHECK_NULL_RETURN(host, false);
116     auto pipelineContext = host->GetContext();
117     CHECK_NULL_RETURN(pipelineContext, false);
118     auto containerId = Container::CurrentId();
119     auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
120     CHECK_NULL_RETURN(foldWindow, false);
121     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
122     CHECK_NULL_RETURN(sheetTheme, false);
123     auto sheetThemeType = sheetTheme->GetSheetType();
124     if (sheetThemeType == "auto" && !foldWindow->IsFoldExpand() &&
125         SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
126         return true;
127     }
128     return false;
129 }
130 
GetSheetTopSafeArea()131 float SheetPresentationPattern::GetSheetTopSafeArea()
132 {
133     auto host = GetHost();
134     CHECK_NULL_RETURN(host, 0.0f);
135     auto pipelineContext = host->GetContext();
136     CHECK_NULL_RETURN(pipelineContext, 0.0f);
137     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
138     auto sheetTopSafeArea = safeAreaInsets.top_.Length();
139     auto windowManager = pipelineContext->GetWindowManager();
140     auto sheetType = GetSheetType();
141     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
142     double deviceHeight = static_cast<double>(SystemProperties::GetDeviceHeight());
143 
144     // full screen subwindow sheet is also WINDOW_MODE_FLOATING, can not enter
145     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING &&
146         !NearEqual(windowGlobalRect.Height(), deviceHeight)) {
147         sheetTopSafeArea = SHEET_BLANK_FLOATING_STATUS_BAR.ConvertToPx();
148     } else if ((sheetType == SheetType::SHEET_BOTTOMLANDSPACE || sheetType == SheetType::SHEET_BOTTOM ||
149                 sheetType == SheetType::SHEET_BOTTOM_OFFSET) &&
150                Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
151         sheetTopSafeArea = GetBottomSafeArea();
152     } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE &&
153                AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
154         sheetTopSafeArea = 0.0f;
155     }
156     // before API14,ignore safeArea height when in landscape
157     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
158         auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
159         CHECK_NULL_RETURN(layoutProperty, 0.0f);
160         auto sheetStyle = layoutProperty->GetSheetStyleValue();
161         if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
162             IsPhoneInLandScape()) {
163             sheetTopSafeArea = 0.0f;
164         }
165     }
166     // if window titleBar hidden, avoid button area.
167     NG::RectF floatButtons;
168     if (GetWindowButtonRect(floatButtons)) {
169         sheetTopSafeArea = floatButtons.Height();
170     }
171     return sheetTopSafeArea;
172 }
173 
InitPageHeight()174 void SheetPresentationPattern::InitPageHeight()
175 {
176     auto pipelineContext = PipelineContext::GetCurrentContext();
177     CHECK_NULL_VOID(pipelineContext);
178     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
179     auto currentTopSafeArea = sheetTopSafeArea_;
180     TAG_LOGD(AceLogTag::ACE_SHEET, "statusBarHeight of sheet by GetSafeAreaWithoutProcess : %{public}u",
181         safeAreaInsets.top_.Length());
182     sheetTopSafeArea_ =
183         GetSheetType() != SheetType::SHEET_BOTTOMLANDSPACE ? safeAreaInsets.top_.Length() : .0f;
184     auto showInPage =
185         GetLayoutProperty<SheetPresentationProperty>()->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
186     auto overlay = GetOverlayManager();
187     if (overlay && overlay->IsRootExpansive() && showInPage) {
188         sheetTopSafeArea_ = .0f;
189     }
190     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
191     CHECK_NULL_VOID(layoutProperty);
192     auto sheetStyle = layoutProperty->GetSheetStyleValue();
193     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
194         IsPhoneInLandScape()) {
195         sheetTopSafeArea_ = 0.0f;
196     }
197     sheetTopSafeArea_ = GetSheetTopSafeArea();
198     TAG_LOGD(AceLogTag::ACE_SHEET, "sheetTopSafeArea of sheet is : %{public}f", sheetTopSafeArea_);
199     if (!NearEqual(currentTopSafeArea, sheetTopSafeArea_)) {
200         topSafeAreaChanged_ = true;
201     }
202     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
203     CHECK_NULL_VOID(sheetTheme);
204     sheetThemeType_ = sheetTheme->GetSheetType();
205     InitSheetMode();
206 }
207 
InitScrollProps()208 void SheetPresentationPattern::InitScrollProps()
209 {
210     auto scrollNode = GetSheetScrollNode();
211     CHECK_NULL_VOID(scrollNode);
212     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
213     CHECK_NULL_VOID(scrollPattern);
214 
215     // When sheet content height is larger than sheet height,
216     // the sheet height should set scroll always enabled.
217     auto edgeEffectAlwaysEnabled = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && IsScrollable();
218     if (sheetEffectEdge_ == SheetEffectEdge::NONE) {
219         scrollPattern->SetEdgeEffect(EdgeEffect::NONE, edgeEffectAlwaysEnabled);
220     } else {
221         scrollPattern->SetEdgeEffect(EdgeEffect::SPRING,
222             edgeEffectAlwaysEnabled, static_cast<EffectEdge>(sheetEffectEdge_));
223     }
224 }
225 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)226 bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap(
227     const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
228 {
229     if (config.skipMeasure && config.skipLayout) {
230         return false;
231     }
232     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
233     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
234     auto sheetLayoutAlgorithm =
235         DynamicCast<SheetPresentationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
236     CHECK_NULL_RETURN(sheetLayoutAlgorithm, false);
237     InitPageHeight();
238     if (sheetLayoutAlgorithm->GetSheetMaxHeight() > 0) {
239         pageHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight();
240         sheetMaxHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight() - sheetTopSafeArea_;
241         sheetMaxWidth_ = sheetLayoutAlgorithm->GetSheetMaxWidth();
242         centerHeight_ = sheetLayoutAlgorithm->GetCenterHeight();
243         if (!NearEqual(sheetOffsetX_, sheetLayoutAlgorithm->GetSheetOffsetX()) ||
244             !NearEqual(sheetOffsetY_, sheetLayoutAlgorithm->GetSheetOffsetY())) {
245             sheetOffsetX_ = sheetLayoutAlgorithm->GetSheetOffsetX();
246             sheetOffsetY_ = sheetLayoutAlgorithm->GetSheetOffsetY();
247             arrowOffset_ = OffsetF(sheetPopupInfo_.arrowOffsetX, .0f);
248             windowChanged_ = true;
249         }
250     }
251     GetArrowOffsetByPlacement(sheetLayoutAlgorithm);
252     InitialLayoutProps();
253     UpdateFontScaleStatus();
254     UpdateDragBarStatus();
255     UpdateCloseIconStatus();
256     UpdateTitlePadding();
257     UpdateSheetTitle();
258     ClipSheetNode();
259     CheckBuilderChange();
260     if (GetSheetType() != SheetType::SHEET_POPUP) {
261         if (windowRotate_) {
262             // When rotating the screen,
263             // first switch the sheet to the position corresponding to the proportion before rotation
264             TranslateTo(pageHeight_ - height_);
265             windowRotate_ = false;
266         } else {
267             // After rotation, if need to avoid the keyboard, trigger the avoidance behavior
268             AvoidSafeArea();
269         }
270     }
271     if (GetSheetType() == SheetType::SHEET_POPUP) {
272         MarkSheetPageNeedRender();
273     }
274     return true;
275 }
276 
CheckBuilderChange()277 void SheetPresentationPattern::CheckBuilderChange()
278 {
279     auto host = GetHost();
280     CHECK_NULL_VOID(host);
281     auto builderNode = GetFirstFrameNodeOfBuilder();
282     CHECK_NULL_VOID(builderNode);
283     auto eventHub = builderNode->GetEventHub<EventHub>();
284     CHECK_NULL_VOID(eventHub);
285     OnAreaChangedFunc onBuilderAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
286                                                      const OffsetF& /* oldOrigin */, const RectF& /* rect */,
287                                                      const OffsetF& /* origin */) {
288         auto sheetNode = sheetNodeWk.Upgrade();
289         CHECK_NULL_VOID(sheetNode);
290         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
291         CHECK_NULL_VOID(sheetPattern);
292         auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
293         CHECK_NULL_VOID(layoutProperty);
294         auto sheetStyle = layoutProperty->GetSheetStyleValue();
295         if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
296             auto sheetWrapper = sheetNode->GetParent();
297             CHECK_NULL_VOID(sheetWrapper);
298             sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
299         }
300     };
301     eventHub->AddInnerOnAreaChangedCallback(builderNode->GetId(), std::move(onBuilderAreaChangedFunc));
302 }
303 
AvoidAiBar()304 void SheetPresentationPattern::AvoidAiBar()
305 {
306     CHECK_NULL_VOID(Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN));
307     if (!IsTypeNeedAvoidAiBar()) {
308         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet need not avoid AiBar.");
309         return;
310     }
311     auto host = GetHost();
312     CHECK_NULL_VOID(host);
313     auto scrollNode = GetSheetScrollNode();
314     CHECK_NULL_VOID(scrollNode);
315     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
316     CHECK_NULL_VOID(scrollPattern);
317     if (NonPositive(scrollPattern->GetScrollableDistance()) || isScrolling_) {
318         return;
319     }
320     auto pipeline = PipelineContext::GetCurrentContext();
321     CHECK_NULL_VOID(pipeline);
322     auto inset = pipeline->GetSafeArea();
323     auto layoutProperty = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
324     layoutProperty->UpdateScrollContentEndOffset(inset.bottom_.Length());
325     TAG_LOGD(AceLogTag::ACE_SHEET, "AvoidAiBar function execution completed");
326     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
327 }
328 
IsScrollable() const329 bool SheetPresentationPattern::IsScrollable() const
330 {
331     auto scrollNode = GetSheetScrollNode();
332     CHECK_NULL_RETURN(scrollNode, false);
333     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
334     CHECK_NULL_RETURN(scrollPattern, false);
335     return Positive(scrollPattern->GetScrollableDistance());
336 }
337 
OnAttachToFrameNode()338 void SheetPresentationPattern::OnAttachToFrameNode()
339 {
340     auto host = GetHost();
341     CHECK_NULL_VOID(host);
342     auto pipelineContext = host->GetContext();
343     CHECK_NULL_VOID(pipelineContext);
344     scale_ = pipelineContext->GetFontScale();
345     InitFoldState();
346     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
347     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
348     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
349     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
350     CHECK_NULL_VOID(targetNode);
351     pipelineContext->AddOnAreaChangeNode(targetNode->GetId());
352     OnAreaChangedFunc onAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
353                                               const OffsetF& /* oldOrigin */, const RectF& /* rect */,
354                                               const OffsetF& /* origin */) {
355         auto sheetNode = sheetNodeWk.Upgrade();
356         CHECK_NULL_VOID(sheetNode);
357         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
358         CHECK_NULL_VOID(sheetPattern);
359         if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
360             auto sheetWrapper = sheetNode->GetParent();
361             CHECK_NULL_VOID(sheetWrapper);
362             sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
363         }
364     };
365     auto eventHub = targetNode->GetEventHub<EventHub>();
366     CHECK_NULL_VOID(eventHub);
367     eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc));
368 
369     auto gesture = host->GetOrCreateGestureEventHub();
370     CHECK_NULL_VOID(gesture);
371     auto touchTask = [](TouchEventInfo& info) {
372         info.SetStopPropagation(true);
373         TAG_LOGD(AceLogTag::ACE_SHEET, "The sheet hits the touch event.");
374     };
375     gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
376     RegisterHoverModeChangeCallback();
377     RegisterAvoidInfoChangeListener(host);
378 }
379 
OnDetachFromFrameNode(FrameNode * sheetNode)380 void SheetPresentationPattern::OnDetachFromFrameNode(FrameNode* sheetNode)
381 {
382     CHECK_NULL_VOID(sheetNode);
383     auto pipeline = sheetNode->GetContext();
384     CHECK_NULL_VOID(pipeline);
385     pipeline->RemoveWindowSizeChangeCallback(sheetNode->GetId());
386     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
387     CHECK_NULL_VOID(targetNode);
388     auto eventHub = targetNode->GetEventHub<EventHub>();
389     CHECK_NULL_VOID(eventHub);
390     eventHub->RemoveInnerOnAreaChangedCallback(sheetNode->GetId());
391     if (HasHoverModeChangedCallbackId()) {
392         pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
393     }
394     UnRegisterAvoidInfoChangeListener(sheetNode);
395 }
396 
RegisterHoverModeChangeCallback()397 void SheetPresentationPattern::RegisterHoverModeChangeCallback()
398 {
399     auto host = GetHost();
400     CHECK_NULL_VOID(host);
401     auto context = host->GetContext();
402     CHECK_NULL_VOID(context);
403     auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
404         auto pattern = weak.Upgrade();
405         CHECK_NULL_VOID(pattern);
406         auto sheetType = pattern->GetSheetType();
407         if (sheetType != SheetType::SHEET_CENTER) {
408             return;
409         }
410         auto host = pattern->GetHost();
411         CHECK_NULL_VOID(host);
412         auto context = host->GetContext();
413         CHECK_NULL_VOID(context);
414         AnimationOption optionPosition;
415         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
416         optionPosition.SetCurve(motion);
417         context->FlushUITasks();
418         context->Animate(
419             optionPosition, motion,
420             [host, context]() {
421                 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
422                 context->FlushUITasks();
423             },
424             [weak]() {
425                 auto pattern = weak.Upgrade();
426                 CHECK_NULL_VOID(pattern);
427                 pattern->FireHoverModeChangeCallback();
428             });
429     };
430     auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
431     UpdateHoverModeChangedCallbackId(hoverModeCallId);
432 }
433 
SetSheetBorderWidth(bool isPartialUpdate)434 void SheetPresentationPattern::SetSheetBorderWidth(bool isPartialUpdate)
435 {
436     auto host = GetHost();
437     CHECK_NULL_VOID(host);
438     auto pipeline = host->GetContext();
439     CHECK_NULL_VOID(pipeline);
440     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
441     CHECK_NULL_VOID(sheetTheme);
442     auto sheetType = GetSheetType();
443     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
444     CHECK_NULL_VOID(layoutProperty);
445     auto sheetStyle = layoutProperty->GetSheetStyleValue();
446     auto renderContext = host->GetRenderContext();
447     CHECK_NULL_VOID(renderContext);
448     renderContext->SetClipToBounds(true);
449     if (sheetStyle.borderWidth.has_value()) {
450         auto borderWidth = sheetStyle.borderWidth.value();
451         bool bottomDimenInvalid = !(sheetType == SheetType::SHEET_CENTER || sheetType == SheetType::SHEET_POPUP ||
452             sheetType == SheetType::SHEET_BOTTOM_OFFSET);
453         if (bottomDimenInvalid) {
454             borderWidth.bottomDimen = 0.0_vp;
455         }
456         layoutProperty->UpdateBorderWidth(borderWidth);
457         renderContext->UpdateBorderWidth(borderWidth);
458     } else if (renderContext->GetBorderWidth().has_value() && !isPartialUpdate) {
459         BorderWidthProperty borderWidth;
460         borderWidth.SetBorderWidth(0.0_vp);
461         layoutProperty->UpdateBorderWidth(borderWidth);
462         renderContext->UpdateBorderWidth(borderWidth);
463     }
464 
465     SetSheetOuterBorderWidth(sheetTheme, sheetStyle);
466 }
467 
468 // initial drag gesture event
InitPanEvent()469 void SheetPresentationPattern::InitPanEvent()
470 {
471     auto host = GetHost();
472     CHECK_NULL_VOID(host);
473     auto focusHub = host->GetFocusHub();
474     CHECK_NULL_VOID(focusHub);
475     InitOnkeyEvent(focusHub);
476     if (IsShowInSubWindowTwoInOne()) {
477         return;
478     }
479 
480     auto hub = host->GetEventHub<EventHub>();
481     CHECK_NULL_VOID(hub);
482     auto gestureHub = hub->GetOrCreateGestureEventHub();
483     CHECK_NULL_VOID(gestureHub);
484     if (panEvent_) {
485         return;
486     }
487 
488     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& event) {
489         auto pattern = weak.Upgrade();
490         if (pattern) {
491             pattern->HandleDragStart();
492         }
493     };
494 
495     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
496         auto pattern = weak.Upgrade();
497         if (pattern) {
498             pattern->HandleDragUpdate(info);
499         }
500     };
501 
502     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
503         auto pattern = weak.Upgrade();
504         if (pattern) {
505             pattern->HandleDragEnd(info.GetMainVelocity());
506         }
507     };
508     auto actionCancelTask = [weak = WeakClaim(this)]() {
509         auto pattern = weak.Upgrade();
510         if (pattern) {
511             pattern->HandleDragEnd({});
512         }
513     };
514     PanDirection panDirection;
515     panDirection.type = PanDirection::VERTICAL;
516     panEvent_ = MakeRefPtr<PanEvent>(
517         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
518     gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
519 }
520 
InitOnkeyEvent(const RefPtr<FocusHub> & focusHub)521 void SheetPresentationPattern::InitOnkeyEvent(const RefPtr<FocusHub>& focusHub)
522 {
523     CHECK_NULL_VOID(focusHub);
524     focusHub->SetOnFocusInternal([weak = WeakClaim(this)]() {
525         auto pattern = weak.Upgrade();
526         if (pattern) {
527             pattern->HandleFocusEvent();
528         }
529     });
530 
531     focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
532         auto pattern = weak.Upgrade();
533         if (pattern) {
534             pattern->HandleBlurEvent();
535         }
536     });
537 }
538 
SetShadowStyle(bool isFocused)539 void SheetPresentationPattern::SetShadowStyle(bool isFocused)
540 {
541     auto host = GetHost();
542     CHECK_NULL_VOID(host);
543     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
544     CHECK_NULL_VOID(layoutProperty);
545     auto sheetStyle = layoutProperty->GetSheetStyleValue();
546     if (sheetStyle.shadow.has_value()) {
547         return;
548     }
549     auto pipeline = host->GetContext();
550     CHECK_NULL_VOID(pipeline);
551     auto renderContext = host->GetRenderContext();
552     CHECK_NULL_VOID(renderContext);
553     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
554     CHECK_NULL_VOID(sheetTheme);
555     auto style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfig());
556     if (!isFocused) {
557         style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfigS());
558     }
559     auto shadow = GetShadowFromTheme(style);
560     renderContext->UpdateBackShadow(shadow);
561 }
562 
HandleFocusEvent()563 void SheetPresentationPattern::HandleFocusEvent()
564 {
565     auto host = GetHost();
566     CHECK_NULL_VOID(host);
567     auto sheetId = host->GetId();
568     TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet get focus, and id is : %{public}d", sheetId);
569     SheetManager::GetInstance().SetFocusSheetId(sheetId);
570     SetShadowStyle(true);
571 }
572 
HandleBlurEvent()573 void SheetPresentationPattern::HandleBlurEvent()
574 {
575     TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet lost focus");
576     SheetManager::GetInstance().SetFocusSheetId(std::nullopt);
577     SetShadowStyle(false);
578 }
579 
HandleDragStart()580 void SheetPresentationPattern::HandleDragStart()
581 {
582     InitScrollProps();
583     SetIsDragging(true);
584     if (animation_ && isAnimationProcess_) {
585         AnimationUtils::StopAnimation(animation_);
586         isAnimationBreak_ = true;
587     }
588     currentOffset_ = 0.0f;
589     isDirectionUp_ = true;
590     GetCurrentBroadcastDetentsIndex();
591 }
592 
HandleDragUpdate(const GestureEvent & info)593 void SheetPresentationPattern::HandleDragUpdate(const GestureEvent& info)
594 {
595     auto sheetType = GetSheetType();
596     if (sheetType == SheetType::SHEET_POPUP) {
597         return;
598     }
599     auto mainDelta = static_cast<float>(info.GetMainDelta());
600     auto host = GetHost();
601     CHECK_NULL_VOID(host);
602     auto tempOffset = currentOffset_;
603     auto detentSize = sheetDetentHeight_.size();
604     if (detentSize <= 0) {
605         return;
606     }
607     auto height = GetSheetHeightBeforeDragUpdate();
608     auto maxDetentSize = GetMaxSheetHeightBeforeDragUpdate();
609     if (GreatOrEqual((height - currentOffset_), maxDetentSize)) {
610         if (LessNotEqual(mainDelta, 0) && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
611             auto friction = CalculateFriction((height - currentOffset_) / sheetMaxHeight_, GetRadio());
612             mainDelta = mainDelta * friction;
613         }
614     }
615     currentOffset_ = currentOffset_ + mainDelta;
616     if (NearEqual(currentOffset_, tempOffset)) {
617         return;
618     }
619     auto pageHeight = GetPageHeightWithoutOffset();
620     auto offset = pageHeight - height + currentOffset_;
621     if (LessOrEqual(offset, (pageHeight - sheetMaxHeight_))) {
622         offset = pageHeight - sheetMaxHeight_;
623         currentOffset_ = height - sheetMaxHeight_;
624     }
625     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && currentOffset_ < 0;
626     if (isNeedChangeScrollHeight) {
627         ChangeScrollHeight(height - currentOffset_);
628     }
629     HandleFollowAccessibilityEvent(height - currentOffset_);
630     auto renderContext = host->GetRenderContext();
631     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
632     if (IsSheetBottomStyle()) {
633         OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
634     }
635 }
636 
SendTextUpdateEvent()637 void SheetPresentationPattern::SendTextUpdateEvent()
638 {
639     auto sheetNode = GetHost();
640     CHECK_NULL_VOID(sheetNode);
641     // Use TEXT_CHANGE to send events.
642     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent TEXT_CHANGE event, when follow up.");
643     sheetNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, "", "");
644 }
645 
SendSelectedEvent()646 void SheetPresentationPattern::SendSelectedEvent()
647 {
648     auto sheetNode = GetHost();
649     CHECK_NULL_VOID(sheetNode);
650     // Use SELECTED to send events.
651     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent SELECTED event, when get out of your hands.");
652     sheetNode->OnAccessibilityEvent(AccessibilityEventType::SELECTED, "", "");
653 }
654 
RegisterElementInfoCallBack()655 void SheetPresentationPattern::RegisterElementInfoCallBack()
656 {
657     auto sheetNode = GetHost();
658     CHECK_NULL_VOID(sheetNode);
659     auto accessibilityProperty = sheetNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
660     CHECK_NULL_VOID(accessibilityProperty);
661     auto callBack = [sheetDetents = std::to_string(static_cast<int32_t>(sheetDetents_))]
662         (Accessibility::ExtraElementInfo& extraElementInfo) {
663         extraElementInfo.SetExtraElementInfo("BindSheet", sheetDetents);
664     };
665     accessibilityProperty->SetRelatedElementInfoCallback(callBack);
666 }
667 
UpdateAccessibilityDetents(float height)668 bool SheetPresentationPattern::UpdateAccessibilityDetents(float height)
669 {
670     auto sheetDetentsSize = sheetDetentHeight_.size();
671     bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
672     if (invalid) {
673         return false;
674     }
675     for (uint32_t i = 0; i < sheetDetentsSize; i++) {
676         if (NearEqual(height, sheetDetentHeight_[i])) {
677             // size is 2, corresponds to high and low.
678             // size is 3, corresponds to high、medium and low.
679             // The lower of the two detents, corresponds to "LOW".
680             bool lowOfTwoDetents = sheetDetentsSize == 2 && i == 0;
681             sheetDetents_ = lowOfTwoDetents
682                 ? static_cast<SheetAccessibilityDetents>(sheetDetentsSize - i)
683                 : static_cast<SheetAccessibilityDetents>(sheetDetentsSize -1 - i);
684             TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet detents enum value: %{public}d", sheetDetents_);
685             RegisterElementInfoCallBack();
686             return true;
687         }
688     }
689     return false;
690 }
691 
GetCurrentBroadcastDetentsIndex()692 uint32_t SheetPresentationPattern::GetCurrentBroadcastDetentsIndex()
693 {
694     bool invalid = sheetDetentHeight_.size() < 2 || !IsSheetBottomStyle();
695     if (invalid) {
696         return broadcastPreDetentsIndex_;
697     }
698     // get currrent detents index.
699     auto it = std::find(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), height_);
700     if (it != sheetDetentHeight_.end()) {
701         broadcastPreDetentsIndex_ = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), it));
702     }
703     return broadcastPreDetentsIndex_;
704 }
705 
HandleFollowAccessibilityEvent(float currHeight)706 void SheetPresentationPattern::HandleFollowAccessibilityEvent(float currHeight)
707 {
708     auto sheetDetentsSize = sheetDetentHeight_.size();
709     bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
710     if (invalid) {
711         return;
712     }
713     if (currHeight < sheetDetentHeight_[0] || currHeight > sheetDetentHeight_[sheetDetentsSize - 1]) {
714         return;
715     }
716     float upHeight = 0.0f;
717     float downHeight = 0.0f;
718     float finalHeight = 0.0f;
719 
720     // record current position info.
721     uint32_t detentsLowerPos = 0;
722     uint32_t detentsUpperPos = 0;
723     uint32_t broadcastCurrDetentsIndex = 0;
724     ComputeDetentsPos(currHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
725 
726     if (GreatNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
727         finalHeight = downHeight;
728         broadcastCurrDetentsIndex = detentsLowerPos;
729     } else if (LessNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
730         finalHeight = upHeight;
731         broadcastCurrDetentsIndex = detentsUpperPos;
732     }
733 
734     // Broadcast once when enter other effect area.
735     if (broadcastCurrDetentsIndex != broadcastPreDetentsIndex_) {
736         UpdateAccessibilityDetents(finalHeight);
737         SendTextUpdateEvent();
738         broadcastPreDetentsIndex_ = broadcastCurrDetentsIndex;
739     }
740 }
741 
HandleDragEndAccessibilityEvent()742 void SheetPresentationPattern::HandleDragEndAccessibilityEvent()
743 {
744     if (UpdateAccessibilityDetents(GetSheetHeightBeforeDragUpdate())) {
745         SendSelectedEvent();
746     }
747 }
HandleDragEnd(float dragVelocity)748 void SheetPresentationPattern::HandleDragEnd(float dragVelocity)
749 {
750     isNeedProcessHeight_ = true;
751     SetIsDragging(false);
752     auto sheetDetentsSize = sheetDetentHeight_.size();
753     if ((sheetDetentsSize == 0) || (GetSheetType() == SheetType::SHEET_POPUP) || IsShowInSubWindowTwoInOne()) {
754         return;
755     }
756     float upHeight = 0.0f;
757     float downHeight = 0.0f;
758     auto height = GetSheetHeightBeforeDragUpdate();
759     auto currentSheetHeight =
760         GreatNotEqual((height - currentOffset_), sheetMaxHeight_) ? sheetMaxHeight_ : (height - currentOffset_);
761     start_ = currentSheetHeight;
762     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet HandleDragEnd, current height is: %{public}f", currentSheetHeight);
763 
764     // record the drag position
765     uint32_t detentsLowerPos = 0;
766     uint32_t detentsUpperPos = 0;
767     ComputeDetentsPos(currentSheetHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
768 
769     // when drag velocity is under the threshold and the sheet height is not in the middle of lower and upper bound.
770     if ((LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) &&
771         (!NearEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight)))) {
772         // check whether the lower or upper index is closer to the current height of the sheet page
773         if (GreatNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
774             if (NearZero(downHeight)) {
775                 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
776             } else {
777                 detentsIndex_ = detentsLowerPos;
778                 ChangeSheetHeight(downHeight);
779                 ChangeSheetPage(height);
780                 SheetTransition(true, std::abs(dragVelocity));
781             }
782         } else if (LessNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
783             detentsIndex_ = detentsUpperPos;
784             ChangeSheetHeight(upHeight);
785             ChangeSheetPage(height);
786             SheetTransition(true, std::abs(dragVelocity));
787         }
788     } else {
789         // when drag velocity is over the threshold
790         if (GreatOrEqual(dragVelocity, 0.0f)) {
791             if (NearZero(downHeight)) {
792                 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
793             } else {
794                 detentsIndex_ = detentsLowerPos;
795                 ChangeSheetHeight(downHeight);
796                 ChangeSheetPage(height);
797                 SheetTransition(true, std::abs(dragVelocity));
798             }
799         } else {
800             detentsIndex_ = detentsUpperPos;
801             ChangeSheetHeight(upHeight);
802             ChangeSheetPage(height);
803             SheetTransition(true, std::abs(dragVelocity));
804         }
805     }
806 
807     // match the sorted detents index to the unsorted one
808     auto detentHeight = sheetDetentHeight_[detentsIndex_];
809     auto pos = std::find(unSortedSheetDentents_.begin(), unSortedSheetDentents_.end(), detentHeight);
810     if (pos != std::end(unSortedSheetDentents_)) {
811         auto idx = static_cast<uint32_t>(std::distance(unSortedSheetDentents_.begin(), pos));
812         detentsFinalIndex_ = idx;
813     }
814 }
815 
ComputeDetentsPos(float currentSheetHeight,float & upHeight,float & downHeight,uint32_t & detentsLowerPos,uint32_t & detentsUpperPos)816 void SheetPresentationPattern::ComputeDetentsPos(
817     float currentSheetHeight, float& upHeight, float& downHeight, uint32_t& detentsLowerPos, uint32_t& detentsUpperPos)
818 {
819     // when drag the sheet page, find the lower and upper index range
820     auto lowerIter = std::lower_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
821     auto upperIter = std::upper_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
822     auto sheetDetentsSize = sheetDetentHeight_.size();
823     if (lowerIter == sheetDetentHeight_.end() || upperIter == sheetDetentHeight_.end()) {
824         // when drag over the highest sheet page
825         upHeight = sheetDetentHeight_[sheetDetentsSize - 1];
826         downHeight = sheetDetentHeight_[sheetDetentsSize - 1];
827         detentsLowerPos = sheetDetentsSize - 1;
828         detentsUpperPos = sheetDetentsSize - 1;
829     } else {
830         auto lowerPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), lowerIter));
831         auto upperPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), upperIter));
832         if (lowerPosition == 0) {
833             upHeight = sheetDetentHeight_[lowerPosition];
834             downHeight = 0;
835         } else {
836             // the first largest height greater than the currentsheet height
837             upHeight = sheetDetentHeight_[upperPosition];
838 
839             // the largest height lower than the currentsheet height
840             downHeight = sheetDetentHeight_[lowerPosition - 1];
841             detentsLowerPos = lowerPosition - 1;
842             detentsUpperPos = upperPosition;
843         }
844     }
845 }
846 
ChangeSheetPage(float height)847 void SheetPresentationPattern::ChangeSheetPage(float height)
848 {
849     if (IsAvoidingKeyboard() && keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL) {
850         return;
851     }
852     ChangeScrollHeight(height);
853 }
854 
OnCoordScrollStart()855 void SheetPresentationPattern::OnCoordScrollStart()
856 {
857     if (animation_ && isAnimationProcess_) {
858         AnimationUtils::StopAnimation(animation_);
859         isAnimationBreak_ = true;
860     }
861     currentOffset_ = 0.0f;
862     GetCurrentBroadcastDetentsIndex();
863 }
864 
OnCoordScrollUpdate(float scrollOffset)865 bool SheetPresentationPattern::OnCoordScrollUpdate(float scrollOffset)
866 {
867     if (!GetShowState() || !IsScrollable()) {
868         return false;
869     }
870 
871     auto sheetType = GetSheetType();
872     auto sheetDetentsSize = sheetDetentHeight_.size();
873     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
874         return false;
875     }
876     auto height = GetSheetHeightBeforeDragUpdate();
877     if ((NearZero(currentOffset_)) && (LessNotEqual(scrollOffset, 0.0f)) &&
878         (GreatOrEqual(height, GetMaxSheetHeightBeforeDragUpdate()))) {
879         return false;
880     }
881     auto host = GetHost();
882     CHECK_NULL_RETURN(host, false);
883     currentOffset_ = currentOffset_ + scrollOffset;
884     auto pageHeight = GetPageHeightWithoutOffset();
885     auto offset = pageHeight - height + currentOffset_;
886     if (LessOrEqual(offset, pageHeight - sheetMaxHeight_)) {
887         offset = pageHeight - sheetMaxHeight_;
888         currentOffset_ = height - sheetMaxHeight_;
889     }
890     HandleFollowAccessibilityEvent(height - currentOffset_);
891     auto renderContext = host->GetRenderContext();
892     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
893     return true;
894 }
895 
OnCoordScrollEnd(float dragVelocity)896 void SheetPresentationPattern::OnCoordScrollEnd(float dragVelocity)
897 {
898     HandleDragEnd(dragVelocity);
899 }
900 
InitialLayoutProps()901 void SheetPresentationPattern::InitialLayoutProps()
902 {
903     CheckSheetHeightChange();
904     InitSheetDetents();
905 }
906 
GetWindowButtonRect(NG::RectF & floatButtons)907 bool SheetPresentationPattern::GetWindowButtonRect(NG::RectF& floatButtons)
908 {
909     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_EIGHTEEN)) {
910         return false;
911     }
912     auto host = GetHost();
913     CHECK_NULL_RETURN(host, false);
914     auto pipelineContext = host->GetContext();
915     CHECK_NULL_RETURN(pipelineContext, false);
916     auto avoidInfoMgr = pipelineContext->GetAvoidInfoManager();
917     CHECK_NULL_RETURN(avoidInfoMgr, false);
918     NG::RectF floatContainerModal;
919     if (avoidInfoMgr->NeedAvoidContainerModal() &&
920         avoidInfoMgr->GetContainerModalButtonsRect(floatContainerModal, floatButtons)) {
921         TAG_LOGD(AceLogTag::ACE_SHEET, "When hidden, floatButtons rect is %{public}s", floatButtons.ToString().c_str());
922         return true;
923     };
924     TAG_LOGD(AceLogTag::ACE_SHEET, "Window title builder shown");
925     return false;
926 }
927 
InitialSingleGearHeight(NG::SheetStyle & sheetStyle)928 float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetStyle)
929 {
930     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
931     float sheetHeight = largeHeight;
932     auto sheetNode = GetHost();
933     CHECK_NULL_RETURN(sheetNode, sheetHeight);
934     if (sheetStyle.sheetHeight.sheetMode.has_value()) {
935         auto pipelineContext = sheetNode->GetContext();
936         CHECK_NULL_RETURN(pipelineContext, sheetHeight);
937         auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
938         CHECK_NULL_RETURN(sheetTheme, sheetHeight);
939         if (sheetStyle.sheetHeight.sheetMode == SheetMode::MEDIUM) {
940             sheetHeight = pageHeight_ * sheetTheme->GetMediumPercent();
941             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
942                 sheetHeight = pageHeight_ * MEDIUM_SIZE_PRE;
943             }
944         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::LARGE) {
945             sheetHeight = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
946             sheetHeight *= sheetTheme->GetLargePercent();
947         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
948             sheetHeight = GetFitContentHeight();
949             if (sheetHeight > largeHeight) {
950                 sheetHeight = largeHeight;
951             }
952             HandleFitContontChange(sheetHeight);
953         }
954     } else {
955         float height = 0.0f;
956         if (sheetStyle.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
957             height = sheetStyle.sheetHeight.height->ConvertToPxWithSize(sheetMaxHeight_);
958         } else {
959             height = sheetStyle.sheetHeight.height->ConvertToPx();
960         }
961         if (GreatNotEqual(height, largeHeight)) {
962             sheetHeight = largeHeight;
963         } else if (LessNotEqual(height, 0)) {
964             sheetHeight = largeHeight;
965         } else {
966             sheetHeight = height;
967         }
968     }
969     return sheetHeight;
970 }
971 
AvoidSafeArea(bool forceAvoid)972 void SheetPresentationPattern::AvoidSafeArea(bool forceAvoid)
973 {
974     auto sheetType = GetSheetType();
975     if (sheetType == SheetType::SHEET_POPUP || IsCurSheetNeedHalfFoldHover() ||
976         sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
977         return;
978     }
979     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
980         AvoidKeyboardBySheetMode(forceAvoid);
981         return;
982     }
983     auto host = GetHost();
984     CHECK_NULL_VOID(host);
985     auto pipelineContext = PipelineContext::GetCurrentContext();
986     CHECK_NULL_VOID(pipelineContext);
987     auto manager = pipelineContext->GetSafeAreaManager();
988     if (!forceAvoid && keyboardHeight_ == manager->GetKeyboardInset().Length()) {
989         return;
990     }
991     keyboardHeight_ = manager->GetKeyboardInset().Length();
992     CHECK_NULL_VOID(host->GetFocusHub());
993     auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
994     sheetHeightUp_ = heightUp;
995     if (isDismissProcess_) {
996         TAG_LOGD(AceLogTag::ACE_SHEET,
997             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
998         return;
999     }
1000     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet height increase %{public}f.", heightUp);
1001     auto offset = pageHeight_ - height_ - heightUp;
1002     auto renderContext = host->GetRenderContext();
1003     if (isScrolling_) {
1004         // if scrolling and keyboard will down, scroll needs to reset.
1005         if (NearZero(heightUp)) {
1006             ScrollTo(.0f);
1007             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1008         } else {
1009             sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
1010             // Otherwise, sheet is necessary to raise and trigger scroll scrolling
1011             // sheet is raised to the top first
1012             renderContext->UpdateTransformTranslate(
1013                 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
1014             // Then adjust the remaining height(heightUp = h - maxH) difference by scrolling
1015             ScrollTo(heightUp);
1016         }
1017     } else {
1018         // offset: translate endpoint, calculated from top
1019         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1020     }
1021     if (IsSheetBottomStyle()) {
1022         OnHeightDidChange(height_ + sheetHeightUp_);
1023     }
1024 }
1025 
GetSheetHeightChange()1026 float SheetPresentationPattern::GetSheetHeightChange()
1027 {
1028     // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode
1029     // TextFieldManagerNG::GetHeight: the cursor Height + 24vp
1030     auto host = GetHost();
1031     CHECK_NULL_RETURN(host, .0f);
1032     auto pipelineContext = host->GetContext();
1033     CHECK_NULL_RETURN(pipelineContext, .0f);
1034     auto manager = pipelineContext->GetSafeAreaManager();
1035     auto keyboardInsert = manager->GetKeyboardInset();
1036     if (keyboardInsert.Length() == 0) {
1037         return 0.f;
1038     }
1039     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
1040     // inputH : Distance from input component's Caret to bottom of screen
1041     // = caret's offset + caret's height + 24vp
1042     if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() &&
1043         !pipelineContext->UsingCaretAvoidMode()) {
1044         TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time");
1045         return .0f;
1046     }
1047     float inputH = 0.f;
1048     if (pipelineContext->UsingCaretAvoidMode()) {
1049         // when user scroll after avoiding keyboard, we need to update scroll offset before avoid keyboard twice.
1050         GetCurrentScrollHeight();
1051         // when avoiding keyboard twice, recover input height before avoiding is needed.
1052         inputH = textFieldManager ? pipelineContext->GetRootHeight() -
1053             textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight() - sheetHeightUp_ -
1054             scrollHeight_ : 0.f;
1055     } else {
1056         inputH = textFieldManager ? (pipelineContext->GetRootHeight() -
1057             textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight()) : 0.f;
1058     }
1059     // keyboardH : keyboard height + height of the bottom navigation bar
1060     auto keyboardH = keyboardInsert.Length() + manager->GetSystemSafeArea().bottom_.Length();
1061     // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
1062     auto inputMinH = keyboardH;
1063     // the LARGE sheet is 15vp from the status bar, and SHEET_CENTER's Node height not equal to screen height.
1064     auto largeHeight = pipelineContext->GetRootHeight() - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea_;
1065     // maxH : height that the sheet can reach the stage = the LARGE sheet - Current sheet height
1066     auto maxH = largeHeight - height_;
1067     if (inputH >= inputMinH) {
1068         // sheet needs not up
1069         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet needs not up");
1070         return .0f;
1071     }
1072     // The expected height of the sheet to be lifted
1073     auto h = inputMinH - inputH;
1074     if (h <= maxH) {
1075         RecoverScrollOrResizeAvoidStatus();
1076         // sheet is lifted up with h
1077         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is lifted up with h = %{public}f", h);
1078         return h;
1079     }
1080     // h > maxH, sheet goes up to the LARGE, then adjust the remaining height(h - maxH) difference by scrolling
1081     if (IsResizeWhenAvoidKeyboard()) {
1082         // remaing height need to update to (keyboardH - bottomDistance) when in resize mode after translate
1083         inputH = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
1084         h = inputMinH - inputH;
1085     }
1086     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is LARGE, and there is [%{public}f] height left to be processed.", h - maxH);
1087     isScrolling_ = true;
1088     return h - maxH;
1089 }
1090 
CreatePropertyCallback()1091 void SheetPresentationPattern::CreatePropertyCallback()
1092 {
1093     if (property_) {
1094         return;
1095     }
1096     auto propertyCallback = [weak = AceType::WeakClaim(this)](float position) {
1097         auto ref = weak.Upgrade();
1098         CHECK_NULL_VOID(ref);
1099         ref->OnHeightDidChange(static_cast<int>(position));
1100     };
1101     property_ = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(0.0, std::move(propertyCallback));
1102 }
1103 
ModifyFireSheetTransition(float dragVelocity)1104 void SheetPresentationPattern::ModifyFireSheetTransition(float dragVelocity)
1105 {
1106     TAG_LOGD(AceLogTag::ACE_SHEET, "ModifyFireSheetTransition function enter");
1107     auto host = GetHost();
1108     CHECK_NULL_VOID(host);
1109     auto renderContext = host->GetRenderContext();
1110     CHECK_NULL_VOID(renderContext);
1111     AnimationOption option;
1112     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
1113         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1114     option.SetCurve(curve);
1115     option.SetFillMode(FillMode::FORWARDS);
1116     auto offset = UpdateSheetTransitionOffset();
1117     CreatePropertyCallback();
1118     CHECK_NULL_VOID(property_);
1119     renderContext->AttachNodeAnimatableProperty(property_);
1120     property_->SetPropertyUnit(PropertyUnit::PIXEL_POSITION);
1121 
1122     auto finishCallback = [weak = AceType::WeakClaim(this)]() {
1123         auto ref = weak.Upgrade();
1124         CHECK_NULL_VOID(ref);
1125         if (!ref->GetAnimationBreak()) {
1126             ref->SetAnimationProcess(false);
1127             ref->ChangeSheetPage(ref->height_);
1128         } else {
1129             ref->isAnimationBreak_ = false;
1130         }
1131         ref->AvoidAiBar();
1132         ref->isNeedProcessHeight_ = false;
1133         ref->FireOnDetentsDidChange(ref->height_);
1134         ref->preDidHeight_ = ref->height_;
1135         ref->isSpringBack_ = false;
1136     };
1137 
1138     isAnimationProcess_ = true;
1139     HandleDragEndAccessibilityEvent();
1140     property_->Set(start_);
1141     animation_ = AnimationUtils::StartAnimation(option,
1142         [weak = AceType::WeakClaim(this), renderContext, offset]() {
1143             auto ref = weak.Upgrade();
1144             CHECK_NULL_VOID(ref);
1145             if (renderContext) {
1146                 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1147                 ref->property_->Set(ref->height_ + ref->sheetHeightUp_);
1148                 bool isNeedChangeScrollHeight =
1149                     ref->scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && ref->isDirectionUp_;
1150                 if (isNeedChangeScrollHeight) {
1151                     ref->ChangeScrollHeight(ref->height_);
1152                 }
1153             }
1154         },
1155         finishCallback);
1156 }
1157 
1158 /**
1159  * @brief Get the max height before drag or nestedScroll.
1160  * the height is relative to the bottom of screen.
1161  */
GetMaxSheetHeightBeforeDragUpdate()1162 float SheetPresentationPattern::GetMaxSheetHeightBeforeDragUpdate()
1163 {
1164     if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET || IsShowInSubWindow()) {
1165         return GetPageHeightWithoutOffset() - sheetOffsetY_;
1166     }
1167     auto sheetDetentsSize = sheetDetentHeight_.size();
1168     if (sheetDetentsSize <= 0) {
1169         TAG_LOGW(AceLogTag::ACE_SHEET, "sheetDetentsSize is nonPositive");
1170         return 0.0f;
1171     }
1172     // The value can be returned in other scenarios as follows:
1173     // 1. bottom sheet tyle : maxHeight is maxDetent.
1174     // 2. center and other sheet tyle, except for popup tyle :
1175     // maxHeight is the height of the top left corner of sheet from the bottom of screen
1176     // 3. scene in setting offsetY : add offsetY to the following value
1177     return sheetDetentHeight_[sheetDetentsSize - 1];
1178 }
1179 
1180 /**
1181  * @brief Get the height before drag or nestedScroll.
1182  * the height is relative to the bottom of screen.
1183  */
GetSheetHeightBeforeDragUpdate()1184 float SheetPresentationPattern::GetSheetHeightBeforeDragUpdate()
1185 {
1186     if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET || IsShowInSubWindow()) {
1187         return GetPageHeightWithoutOffset() - sheetOffsetY_;
1188     }
1189     // height_ : from the bottom of screen, after the sheet entry action has ended.
1190     // sheetHeightUp_ : increased height to avoid soft keyboard.
1191     // -bottomOffsetY_ : increased height by setting offsetY. bottomOffsetY_ is a negative number.
1192     return height_ + sheetHeightUp_;
1193 }
1194 
UpdateSheetTransitionOffset()1195 float SheetPresentationPattern::UpdateSheetTransitionOffset()
1196 {
1197     // dentets greater than 1 and no rebound
1198     if (!WillSpringBack() && sheetDetentHeight_.size() > 1) {
1199         // When avoiding keyboards
1200         // don't consider the height difference introduced by avoidance after switching detents
1201         sheetHeightUp_ = 0.0f;
1202     }
1203     // apply to springBack scene
1204     // return the offset before drag
1205     auto offset = GetPageHeightWithoutOffset() - GetSheetHeightBeforeDragUpdate();
1206     return offset;
1207 }
1208 
SetSheetAnimationOption(AnimationOption & option) const1209 void SheetPresentationPattern::SetSheetAnimationOption(AnimationOption& option) const
1210 {
1211     option.SetFillMode(FillMode::FORWARDS);
1212     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1213         option.SetDuration(SHEET_ANIMATION_DURATION);
1214     }
1215 }
1216 
SheetTransition(bool isTransitionIn,float dragVelocity)1217 void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity)
1218 {
1219     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDirectionUp_;
1220     if ((HasOnHeightDidChange() && IsSheetBottomStyle() && isTransitionIn && isNeedProcessHeight_)
1221         || isNeedChangeScrollHeight) {
1222         ModifyFireSheetTransition(dragVelocity);
1223         return;
1224     }
1225     auto host = GetHost();
1226     CHECK_NULL_VOID(host);
1227     AnimationOption option;
1228     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
1229         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1230     option.SetCurve(curve);
1231     SetSheetAnimationOption(option);
1232     auto offset = UpdateSheetTransitionOffset();
1233     if (!isTransitionIn) {
1234         const auto& overlayManager = GetOverlayManager();
1235         CHECK_NULL_VOID(overlayManager);
1236         auto maskNode = overlayManager->GetSheetMask(host);
1237         if (maskNode) {
1238             overlayManager->PlaySheetMaskTransition(maskNode, host, false);
1239         }
1240     }
1241     option.SetOnFinishEvent([weak = AceType::WeakClaim(this), isTransitionIn]() {
1242         auto pattern = weak.Upgrade();
1243         CHECK_NULL_VOID(pattern);
1244         if (isTransitionIn) {
1245             if (!pattern->GetAnimationBreak()) {
1246                 pattern->SetAnimationProcess(false);
1247                 pattern->ChangeSheetPage(pattern->height_);
1248             } else {
1249                 pattern->isAnimationBreak_ = false;
1250             }
1251             pattern->AvoidAiBar();
1252             pattern->FireOnDetentsDidChange(pattern->height_);
1253             pattern->isSpringBack_ = false;
1254         } else {
1255             pattern->SetAnimationProcess(false);
1256             const auto& overlayManager = pattern->GetOverlayManager();
1257             CHECK_NULL_VOID(overlayManager);
1258             auto host = pattern->GetHost();
1259             CHECK_NULL_VOID(host);
1260             overlayManager->FireAutoSave(host);
1261             pattern->OnDisappear();
1262             overlayManager->RemoveSheet(host);
1263             pattern->FireCallback("false");
1264         }
1265     });
1266     StartSheetTransitionAnimation(option, isTransitionIn, offset);
1267 }
1268 
SheetInteractiveDismiss(BindSheetDismissReason dismissReason,float dragVelocity)1269 void SheetPresentationPattern::SheetInteractiveDismiss(BindSheetDismissReason dismissReason, float dragVelocity)
1270 {
1271     isDirectionUp_ = false;
1272     if (HasShouldDismiss() || HasOnWillDismiss()) {
1273         const auto& overlayManager = GetOverlayManager();
1274         CHECK_NULL_VOID(overlayManager);
1275         overlayManager->SetDismissTarget(DismissTarget(sheetKey_));
1276         auto host = GetHost();
1277         CHECK_NULL_VOID(host);
1278         SheetManager::GetInstance().SetDismissSheet(host->GetId());
1279         if (dismissReason == BindSheetDismissReason::SLIDE_DOWN) {
1280             isSpringBack_ = true;
1281             if (HasSheetSpringBack()) {
1282                 CallSheetSpringBack();
1283             } else {
1284                 isDismissProcess_ = false;
1285                 SheetTransition(true);
1286             }
1287         }
1288         CallShouldDismiss();
1289         CallOnWillDismiss(static_cast<int32_t>(dismissReason));
1290     } else {
1291         DismissTransition(false, dragVelocity);
1292     }
1293 }
1294 
DismissTransition(bool isTransitionIn,float dragVelocity)1295 void SheetPresentationPattern::DismissTransition(bool isTransitionIn, float dragVelocity)
1296 {
1297     isDismissProcess_ = true;
1298     const auto& overlayManager = GetOverlayManager();
1299     CHECK_NULL_VOID(overlayManager);
1300     overlayManager->ModalPageLostFocus(GetHost());
1301     if (!isTransitionIn) {
1302         OnWillDisappear();
1303     }
1304     auto sheetType = GetSheetType();
1305     if (sheetType == SheetType::SHEET_POPUP) {
1306         BubbleStyleSheetTransition(isTransitionIn);
1307     } else {
1308         SheetTransition(isTransitionIn, dragVelocity);
1309     }
1310 }
1311 
ChangeScrollHeight(float height)1312 void SheetPresentationPattern::ChangeScrollHeight(float height)
1313 {
1314     auto host = GetHost();
1315     CHECK_NULL_VOID(host);
1316     auto geometryNode = host->GetGeometryNode();
1317     CHECK_NULL_VOID(geometryNode);
1318     auto operationNode = GetTitleBuilderNode();
1319     CHECK_NULL_VOID(operationNode);
1320     auto perationGeometryNode = operationNode->GetGeometryNode();
1321     CHECK_NULL_VOID(perationGeometryNode);
1322     auto operationHeight = perationGeometryNode->GetFrameSize().Height();
1323     auto scrollNode = GetSheetScrollNode();
1324     CHECK_NULL_VOID(scrollNode);
1325     auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
1326     CHECK_NULL_VOID(scrollProps);
1327     auto scrollHeight = height - operationHeight - resizeDecreasedHeight_;
1328     auto sheetType = GetSheetType();
1329     if (sheetType == SheetType::SHEET_POPUP || sheetType == SheetType::SHEET_CENTER ||
1330         sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
1331         auto sheetHeight = geometryNode->GetFrameSize().Height();
1332         scrollHeight = sheetHeight - operationHeight - resizeDecreasedHeight_;
1333     }
1334     scrollProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(scrollHeight)));
1335     scrollNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1336 }
1337 
UpdateDragBarStatus()1338 void SheetPresentationPattern::UpdateDragBarStatus()
1339 {
1340     auto host = GetHost();
1341     CHECK_NULL_VOID(host);
1342     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1343     CHECK_NULL_VOID(layoutProperty);
1344     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1345     auto showDragIndicator = sheetStyle.showDragBar.value_or(true);
1346 
1347     auto titleColumn = DynamicCast<FrameNode>(host->GetFirstChild());
1348     CHECK_NULL_VOID(titleColumn);
1349     auto sheetDragBar = DynamicCast<FrameNode>(titleColumn->GetFirstChild());
1350     CHECK_NULL_VOID(sheetDragBar);
1351     auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
1352     CHECK_NULL_VOID(dragBarLayoutProperty);
1353     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1354         dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1355         sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1356         return;
1357     }
1358     if (IsSheetBottomStyle() && (sheetDetentHeight_.size() > 1)) {
1359         if (sheetStyle.isTitleBuilder.has_value()) {
1360             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1361         } else {
1362             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1363         }
1364     } else {
1365         if (sheetStyle.isTitleBuilder.has_value()) {
1366             dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1367         } else {
1368             dragBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
1369         }
1370     }
1371     sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1372 }
1373 
GetCloseIconPosX(const SizeF & sheetSize,const RefPtr<SheetTheme> & sheetTheme)1374 float SheetPresentationPattern::GetCloseIconPosX(const SizeF& sheetSize, const RefPtr<SheetTheme>& sheetTheme)
1375 {
1376     auto closeIconX = sheetSize.Width() - static_cast<float>(SHEET_CLOSE_ICON_WIDTH.ConvertToPx()) -
1377                       static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1378     if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
1379         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1380         closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1381     }
1382     return closeIconX;
1383 }
1384 
IsShowCloseIcon()1385 bool SheetPresentationPattern::IsShowCloseIcon()
1386 {
1387     auto host = GetHost();
1388     CHECK_NULL_RETURN(host, false);
1389     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1390     CHECK_NULL_RETURN(layoutProperty, false);
1391     return layoutProperty->GetSheetStyleValue().showCloseIcon.value_or(true);
1392 }
1393 
GetTitleNode()1394 RefPtr<FrameNode> SheetPresentationPattern::GetTitleNode()
1395 {
1396     auto operationNode = GetTitleBuilderNode();
1397     CHECK_NULL_RETURN(operationNode, nullptr);
1398     return DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1399 }
1400 
UpdateTitleTextColor()1401 void SheetPresentationPattern::UpdateTitleTextColor()
1402 {
1403     auto host = GetHost();
1404     CHECK_NULL_VOID(host);
1405     auto pipeline = host->GetContext();
1406     CHECK_NULL_VOID(pipeline);
1407     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1408     CHECK_NULL_VOID(sheetTheme);
1409     auto firstChild = host->GetChildAtIndex(0);
1410     CHECK_NULL_VOID(firstChild);
1411     auto sheetTitleColumn = firstChild->GetChildAtIndex(1);
1412     CHECK_NULL_VOID(sheetTitleColumn);
1413     auto mainRow = sheetTitleColumn->GetChildAtIndex(0);
1414     CHECK_NULL_VOID(mainRow);
1415     auto mainTitleText = DynamicCast<FrameNode>(mainRow->GetChildAtIndex(0));
1416     CHECK_NULL_VOID(mainTitleText);
1417     auto mainTitleProp = mainTitleText->GetLayoutProperty<TextLayoutProperty>();
1418     CHECK_NULL_VOID(mainTitleProp);
1419     mainTitleProp->UpdateTextColor(sheetTheme->GetTitleTextFontColor());
1420 
1421     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1422     CHECK_NULL_VOID(layoutProperty);
1423     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1424     if (sheetStyle.sheetSubtitle.has_value()) {
1425         auto subRow = sheetTitleColumn->GetChildAtIndex(1);
1426         CHECK_NULL_VOID(subRow);
1427         auto subTitleText = DynamicCast<FrameNode>(subRow->GetChildAtIndex(0));
1428         CHECK_NULL_VOID(subTitleText);
1429         auto subTitleProp = subTitleText->GetLayoutProperty<TextLayoutProperty>();
1430         CHECK_NULL_VOID(subTitleProp);
1431         subTitleProp->UpdateTextColor(sheetTheme->GetSubtitleTextFontColor());
1432     }
1433 }
1434 
UpdateTitlePadding()1435 void SheetPresentationPattern::UpdateTitlePadding()
1436 {
1437     auto host = GetHost();
1438     CHECK_NULL_VOID(host);
1439     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1440     CHECK_NULL_VOID(layoutProperty);
1441     if (!layoutProperty->GetSheetStyleValue().isTitleBuilder.has_value()) {
1442         return;
1443     }
1444 
1445     auto titleNode = GetTitleNode();
1446     CHECK_NULL_VOID(titleNode);
1447     auto titleLayoutProperty = DynamicCast<LinearLayoutProperty>(titleNode->GetLayoutProperty());
1448     CHECK_NULL_VOID(titleLayoutProperty);
1449     auto pipeline = host->GetContext();
1450     CHECK_NULL_VOID(pipeline);
1451     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1452     CHECK_NULL_VOID(sheetTheme);
1453     auto showCloseIcon = true;
1454     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN)) {
1455         showCloseIcon = IsShowCloseIcon();
1456     }
1457     PaddingProperty padding;
1458 
1459     // The title bar area is reserved for the close button area size by default.
1460     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1461         auto sheetCloseIconTitleSpace = sheetTheme->IsOuterBorderEnable() ? 0.0_vp : SHEET_CLOSE_ICON_TITLE_SPACE_NEW;
1462         padding.end = CalcLength(showCloseIcon ? sheetCloseIconTitleSpace + SHEET_CLOSE_ICON_WIDTH : 0.0_vp);
1463     } else {
1464         padding.right = CalcLength(SHEET_CLOSE_ICON_TITLE_SPACE + SHEET_CLOSE_ICON_WIDTH);
1465     }
1466     titleLayoutProperty->UpdatePadding(padding);
1467     auto titleColumnPattern = titleNode->GetPattern<LinearLayoutPattern>();
1468     CHECK_NULL_VOID(titleColumnPattern);
1469     titleColumnPattern->CheckLocalized();
1470     titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1471 }
1472 
UpdateCloseIconStatus()1473 void SheetPresentationPattern::UpdateCloseIconStatus()
1474 {
1475     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1476         TAG_LOGI(AceLogTag::ACE_SHEET, "PlatformVersion less or equal to version 10");
1477         return;
1478     }
1479     auto showCloseIcon = IsShowCloseIcon();
1480     auto sheetCloseIcon = GetSheetCloseIcon();
1481     CHECK_NULL_VOID(sheetCloseIcon);
1482     auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
1483     CHECK_NULL_VOID(iconLayoutProperty);
1484     iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1485     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1486 }
1487 
UpdateSheetTitle()1488 void SheetPresentationPattern::UpdateSheetTitle()
1489 {
1490     auto host = GetHost();
1491     CHECK_NULL_VOID(host);
1492     auto pipeline = PipelineContext::GetCurrentContext();
1493     CHECK_NULL_VOID(pipeline);
1494     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1495     CHECK_NULL_VOID(layoutProperty);
1496     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1497     if (sheetStyle.sheetTitle.has_value()) {
1498         auto titleId = GetTitleId();
1499         auto titleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(titleId));
1500         CHECK_NULL_VOID(titleNode);
1501         auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
1502         CHECK_NULL_VOID(titleProp);
1503         titleProp->UpdateContent(sheetStyle.sheetTitle.value());
1504         if (pipeline->GetFontScale() != scale_) {
1505             titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1506         }
1507         titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1508         if (sheetStyle.sheetSubtitle.has_value()) {
1509             auto subtitleId = GetSubtitleId();
1510             auto subtitleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(subtitleId));
1511             CHECK_NULL_VOID(subtitleNode);
1512             auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
1513             CHECK_NULL_VOID(subtitleProp);
1514             subtitleProp->UpdateContent(sheetStyle.sheetSubtitle.value());
1515             subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1516         }
1517     }
1518 }
1519 
UpdateFontScaleStatus()1520 void SheetPresentationPattern::UpdateFontScaleStatus()
1521 {
1522     auto host = GetHost();
1523     CHECK_NULL_VOID(host);
1524     auto pipeline = PipelineContext::GetCurrentContext();
1525     CHECK_NULL_VOID(pipeline);
1526     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1527     CHECK_NULL_VOID(layoutProperty);
1528     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1529     if (pipeline->GetFontScale() != scale_) {
1530         auto operationNode = GetTitleBuilderNode();
1531         CHECK_NULL_VOID(operationNode);
1532         auto titleColumnNode = DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1533         CHECK_NULL_VOID(titleColumnNode);
1534         auto layoutProps = operationNode->GetLayoutProperty<LinearLayoutProperty>();
1535         CHECK_NULL_VOID(layoutProps);
1536         auto titleLayoutProps = titleColumnNode->GetLayoutProperty<LinearLayoutProperty>();
1537         CHECK_NULL_VOID(titleLayoutProps);
1538         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1539         CHECK_NULL_VOID(sheetTheme);
1540         bool isSheetHasNoTitle = !sheetStyle.isTitleBuilder.has_value();
1541         bool isFontScaledInSystemTitle = sheetStyle.isTitleBuilder.has_value() && !sheetStyle.isTitleBuilder.value() &&
1542                                          GreatNotEqual(pipeline->GetFontScale(), sheetTheme->GetSheetNormalScale());
1543         if (isSheetHasNoTitle || isFontScaledInSystemTitle) {
1544             layoutProps->ClearUserDefinedIdealSize(false, true);
1545             titleLayoutProps->ClearUserDefinedIdealSize(false, true);
1546         } else if (sheetStyle.isTitleBuilder.has_value()) {
1547             auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1548             CHECK_NULL_VOID(sheetTheme);
1549             auto operationAreaHeight = sheetTheme->GetOperationAreaHeight();
1550             layoutProps->UpdateUserDefinedIdealSize(
1551                 CalcSize(std::nullopt, CalcLength(operationAreaHeight - sheetTheme->GetSheetTitleAreaMargin())));
1552             titleLayoutProps->UpdateUserDefinedIdealSize(
1553                 CalcSize(std::nullopt, CalcLength(operationAreaHeight)));
1554             if (sheetStyle.sheetSubtitle.has_value()) {
1555                 layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
1556                     CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - sheetTheme->GetSheetTitleAreaMargin())));
1557                 titleLayoutProps->UpdateUserDefinedIdealSize(
1558                     CalcSize(std::nullopt,
1559                         CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - SHEET_DOUBLE_TITLE_BOTTON_MARGIN)));
1560             }
1561         }
1562         UpdateSheetTitle();
1563         scale_ = pipeline->GetFontScale();
1564         auto sheetWrapper = host->GetParent();
1565         CHECK_NULL_VOID(sheetWrapper);
1566         sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1567     }
1568 }
1569 
OnColorConfigurationUpdate()1570 void SheetPresentationPattern::OnColorConfigurationUpdate()
1571 {
1572     auto host = GetHost();
1573     CHECK_NULL_VOID(host);
1574     auto pipeline = host->GetContext();
1575     CHECK_NULL_VOID(pipeline);
1576     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1577     CHECK_NULL_VOID(sheetTheme);
1578 
1579     UpdateTitleTextColor();
1580     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
1581     CHECK_NULL_VOID(sheetCloseIcon);
1582     auto renderContext = sheetCloseIcon->GetRenderContext();
1583     CHECK_NULL_VOID(renderContext);
1584     renderContext->UpdateBackgroundColor(sheetTheme->GetCloseIconColor());
1585     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1586     auto iconNode = DynamicCast<FrameNode>(sheetCloseIcon->GetChildAtIndex(0));
1587     CHECK_NULL_VOID(iconNode);
1588 
1589     // when api >= 12, use symbol format image, else use image format.
1590     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
1591         SystemProperties::IsNeedSymbol()) {
1592         auto symbolLayoutProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
1593         CHECK_NULL_VOID(symbolLayoutProperty);
1594         symbolLayoutProperty->UpdateSymbolColorList({sheetTheme->GetCloseIconSymbolColor()});
1595     } else {
1596         auto imagePaintProperty = iconNode->GetPaintProperty<ImageRenderProperty>();
1597         CHECK_NULL_VOID(imagePaintProperty);
1598         imagePaintProperty->UpdateSvgFillColor(sheetTheme->GetCloseIconImageColor());
1599     }
1600     iconNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1601 }
1602 
GetWrapperHeight()1603 float SheetPresentationPattern::GetWrapperHeight()
1604 {
1605     auto host = GetHost();
1606     CHECK_NULL_RETURN(host, 0.0f);
1607     auto sheetWrapper = host->GetParent();
1608     CHECK_NULL_RETURN(sheetWrapper, 0.0f);
1609     auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
1610     CHECK_NULL_RETURN(sheetWrapperNode, 0.0f);
1611     auto sheetWrapperGeometryNode = sheetWrapperNode->GetGeometryNode();
1612     CHECK_NULL_RETURN(sheetWrapperGeometryNode, 0.0f);
1613     return sheetWrapperGeometryNode->GetFrameSize().Height();
1614 }
1615 
SheetHeightNeedChanged()1616 bool SheetPresentationPattern::SheetHeightNeedChanged()
1617 {
1618     auto host = GetHost();
1619     CHECK_NULL_RETURN(host, false);
1620     auto sheetGeometryNode = host->GetGeometryNode();
1621     CHECK_NULL_RETURN(sheetGeometryNode, false);
1622     if (!NearEqual(sheetGeometryNode->GetFrameSize().Height(), sheetHeight_) ||
1623         !NearEqual(GetWrapperHeight(), wrapperHeight_)) {
1624         return true;
1625     }
1626     return false;
1627 }
1628 
UpdateMaskBackgroundColor()1629 void SheetPresentationPattern::UpdateMaskBackgroundColor()
1630 {
1631     auto host = GetHost();
1632     CHECK_NULL_VOID(host);
1633     auto pipeline = host->GetContext();
1634     CHECK_NULL_VOID(pipeline);
1635     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1636     CHECK_NULL_VOID(sheetTheme);
1637     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1638     CHECK_NULL_VOID(layoutProperty);
1639     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1640     sheetMaskColor_ = sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor());
1641     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1642         if (sheetStyle.maskColor.has_value()) {
1643             sheetMaskColor_ = sheetStyle.maskColor.value();
1644         } else {
1645             sheetMaskColor_ = Color::TRANSPARENT;
1646         }
1647     } else {
1648         if ((!sheetStyle.interactive.has_value() && GetSheetType() == SheetType::SHEET_POPUP) ||
1649             sheetStyle.interactive.value_or(false)) {
1650             sheetMaskColor_ = Color::TRANSPARENT;
1651         }
1652     }
1653 }
1654 
UpdateMaskBackgroundColorRender()1655 void SheetPresentationPattern::UpdateMaskBackgroundColorRender()
1656 {
1657     auto host = GetHost();
1658     CHECK_NULL_VOID(host);
1659     UpdateMaskBackgroundColor();
1660     const auto& overlayManager = GetOverlayManager();
1661     CHECK_NULL_VOID(overlayManager);
1662     auto maskNode = overlayManager->GetSheetMask(host);
1663     CHECK_NULL_VOID(maskNode);
1664     auto maskRenderContext = maskNode->GetRenderContext();
1665     CHECK_NULL_VOID(maskRenderContext);
1666     maskRenderContext->UpdateBackgroundColor(sheetMaskColor_);
1667 }
1668 
FireCommonCallback()1669 void SheetPresentationPattern::FireCommonCallback()
1670 {
1671     auto host = GetHost();
1672     CHECK_NULL_VOID(host);
1673     FireOnTypeDidChange();
1674     FireOnWidthDidChange(host);
1675     FireOnHeightDidChange();
1676 }
1677 
CheckSheetHeightChange()1678 void SheetPresentationPattern::CheckSheetHeightChange()
1679 {
1680     auto host = GetHost();
1681     CHECK_NULL_VOID(host);
1682     auto sheetGeometryNode = host->GetGeometryNode();
1683     CHECK_NULL_VOID(sheetGeometryNode);
1684     if (isFirstInit_) {
1685         sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1686         wrapperHeight_ = GetWrapperHeight();
1687         isFirstInit_ = false;
1688     } else {
1689         if (sheetType_ != GetSheetType()) {
1690             if (sheetType_ == SheetType::SHEET_POPUP) {
1691                 MarkSheetPageNeedRender();
1692             }
1693             SetSheetBorderWidth();
1694         }
1695         if (SheetHeightNeedChanged() || (sheetType_ != GetSheetType()) || windowChanged_ || topSafeAreaChanged_) {
1696             sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1697             wrapperHeight_ = GetWrapperHeight();
1698             const auto& overlayManager = GetOverlayManager();
1699             CHECK_NULL_VOID(overlayManager);
1700             auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1701             CHECK_NULL_VOID(layoutProperty);
1702             auto sheetStyle = layoutProperty->GetSheetStyleValue();
1703             overlayManager->ComputeSheetOffset(sheetStyle, host);
1704             if (sheetType_ == SheetType::SHEET_POPUP) {
1705                 auto renderContext = GetRenderContext();
1706                 CHECK_NULL_VOID(renderContext);
1707                 renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_), 0.0f });
1708                 renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
1709                 FireCommonCallback();
1710             } else {
1711                 overlayManager->PlaySheetTransition(host, true, false);
1712             }
1713             auto maskNode = overlayManager->GetSheetMask(host);
1714             if (maskNode) {
1715                 UpdateMaskBackgroundColorRender();
1716             }
1717             windowChanged_ = false;
1718             topSafeAreaChanged_ = false;
1719         }
1720     }
1721     GetBuilderInitHeight();
1722 }
1723 
IsCustomDetentsChanged(SheetStyle sheetStyle)1724 void SheetPresentationPattern::IsCustomDetentsChanged(SheetStyle sheetStyle)
1725 {
1726     unsigned int preDetentsSize = preDetents_.size();
1727     unsigned int userSetDetentsSize = sheetStyle.detents.size();
1728     // if preview detents size is not equal to the new one, set detents index to zero
1729     if (preDetentsSize != userSetDetentsSize) {
1730         detentsFinalIndex_ = 0;
1731         return;
1732     }
1733 
1734     // check whether the new coming one's content is equal to the last time input
1735     unsigned int length = std::min(preDetentsSize, userSetDetentsSize);
1736     for (unsigned int index = 0; index < length; index++) {
1737         if (sheetStyle.detents[index] != preDetents_[index]) {
1738             // if detents has been changed, set detents index to zero
1739             detentsFinalIndex_ = 0;
1740             break;
1741         }
1742     }
1743 }
1744 
InitSheetDetents()1745 void SheetPresentationPattern::InitSheetDetents()
1746 {
1747     // record input detents
1748     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1749     CHECK_NULL_VOID(layoutProperty);
1750     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1751     IsCustomDetentsChanged(sheetStyle);
1752     preDetents_.clear();
1753     sheetDetentHeight_.clear();
1754     unSortedSheetDentents_.clear();
1755     float height = 0.0f;
1756     auto sheetNode = GetHost();
1757     CHECK_NULL_VOID(sheetNode);
1758     auto geometryNode = sheetNode->GetGeometryNode();
1759     CHECK_NULL_VOID(geometryNode);
1760     auto pipelineContext = sheetNode->GetContext();
1761     CHECK_NULL_VOID(pipelineContext);
1762     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
1763     CHECK_NULL_VOID(sheetTheme);
1764     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1765     auto sheetType = GetSheetType();
1766     auto sheetFrameHeight = geometryNode->GetFrameSize().Height();
1767     auto mediumSize = sheetTheme->GetMediumPercent();
1768     float largeHeightOfTheme = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
1769     largeHeightOfTheme *= sheetTheme->GetLargePercent();
1770     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1771         mediumSize = MEDIUM_SIZE_PRE;
1772     }
1773     switch (sheetType) {
1774         case SheetType::SHEET_BOTTOMLANDSPACE:
1775             if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1776                 height = sheetFrameHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1777                 sheetDetentHeight_.emplace_back(height);
1778                 break;
1779             }
1780             [[fallthrough]];
1781         case SheetType::SHEET_BOTTOM:
1782             [[fallthrough]];
1783         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
1784             if (sheetStyle.detents.size() <= 0) {
1785                 height = InitialSingleGearHeight(sheetStyle);
1786                 sheetDetentHeight_.emplace_back(height);
1787                 break;
1788             }
1789             InitDetents(sheetStyle, height, mediumSize, largeHeightOfTheme, largeHeight);
1790             std::sort(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), std::less<float>());
1791             sheetDetentHeight_.erase(
1792                 std::unique(sheetDetentHeight_.begin(), sheetDetentHeight_.end()), sheetDetentHeight_.end());
1793             break;
1794         case SheetType::SHEET_CENTER:
1795             height = (centerHeight_ + pageHeight_) / SHEET_HALF_HEIGHT;
1796             sheetDetentHeight_.emplace_back(height);
1797             break;
1798         case SheetType::SHEET_BOTTOM_OFFSET:
1799             height = InitialSingleGearHeight(sheetStyle);
1800             sheetDetentHeight_.emplace_back(height);
1801             break;
1802         default:
1803             break;
1804     }
1805 }
1806 
InitDetents(SheetStyle sheetStyle,float height,double mediumSize,float largeHeightOfTheme,double largeHeight)1807 void SheetPresentationPattern::InitDetents(
1808     SheetStyle sheetStyle, float height, double mediumSize, float largeHeightOfTheme, double largeHeight)
1809 {
1810     for (auto iter : sheetStyle.detents) {
1811         preDetents_.emplace_back(iter);
1812         if (iter.sheetMode.has_value()) {
1813             if (iter.sheetMode == SheetMode::MEDIUM) {
1814                 height = pageHeight_ * mediumSize;
1815             } else if (iter.sheetMode == SheetMode::LARGE) {
1816                 height = largeHeightOfTheme;
1817             } else if (iter.sheetMode == SheetMode::AUTO) {
1818                 height = GetFitContentHeight();
1819                 height = GreatNotEqual(height, largeHeight) ? largeHeight : height;
1820                 HandleFitContontChange(height);
1821             }
1822         } else {
1823             if (iter.height->Unit() == DimensionUnit::PERCENT) {
1824                 height = iter.height->ConvertToPxWithSize(sheetMaxHeight_);
1825             } else {
1826                 height = iter.height->ConvertToPx();
1827             }
1828             if (GreatNotEqual(height, largeHeight)) {
1829                 height = largeHeight;
1830             } else if (LessNotEqual(height, 0)) {
1831                 height = largeHeight;
1832             }
1833         }
1834         sheetDetentHeight_.emplace_back(height);
1835         unSortedSheetDentents_.emplace_back(height);
1836     }
1837 }
1838 
HandleFitContontChange(float height)1839 void SheetPresentationPattern::HandleFitContontChange(float height)
1840 {
1841     if ((NearEqual(height_, sheetFitContentHeight_)) && (!NearEqual(height, sheetFitContentHeight_))) {
1842         ChangeSheetHeight(height);
1843         ChangeSheetPage(height_);
1844         SheetTransition(true);
1845     }
1846     sheetFitContentHeight_ = height;
1847 }
1848 
ComputeTransitionOffset(float sheetHeight)1849 float SheetPresentationPattern::ComputeTransitionOffset(float sheetHeight)
1850 {
1851     float offset = 0.0f;
1852     auto sheetType = GetSheetType();
1853     if (sheetType == SheetType::SHEET_POPUP ||
1854         sheetType == SheetType::SHEET_BOTTOM_OFFSET || IsCurSheetNeedHalfFoldHover()
1855         || IsShowInSubWindow()) {
1856         offset = GetSheetOffset();
1857     } else {
1858         offset = GetPageHeightWithoutOffset() - sheetHeight;
1859     }
1860     return offset;
1861 }
1862 
GetSubWindowId()1863 int32_t SheetPresentationPattern::GetSubWindowId()
1864 {
1865     auto host = GetHost();
1866     CHECK_NULL_RETURN(host, INVALID_SUBWINDOW_ID);
1867     auto sheetWrapper = host->GetParent();
1868     CHECK_NULL_RETURN(sheetWrapper, INVALID_SUBWINDOW_ID);
1869     auto wrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
1870     auto sheetWrapperPattern = wrapperNode->GetPattern<SheetWrapperPattern>();
1871     CHECK_NULL_RETURN(sheetWrapperPattern, INVALID_SUBWINDOW_ID);
1872     return sheetWrapperPattern->GetSubWindowId();
1873 }
1874 
ComputeSheetTypeInSubWindow()1875 SheetType SheetPresentationPattern::ComputeSheetTypeInSubWindow()
1876 {
1877     SheetType sheetType = SheetType::SHEET_CENTER;
1878     auto instanceId = SubwindowManager::GetInstance()->GetParentContainerId(GetSubWindowId());
1879     auto container = AceEngine::Get().GetContainer(instanceId);
1880     CHECK_NULL_RETURN(container, sheetType);
1881     auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1882     CHECK_NULL_RETURN(mainWindowContext, sheetType);
1883     auto windowWidth = mainWindowContext->GetDisplayWindowRectInfo().Width();
1884     if (container->IsUIExtensionWindow()) {
1885         auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(GetSubWindowId(),
1886             SubwindowType::TYPE_SHEET);
1887         CHECK_NULL_RETURN(subwindow, sheetType);
1888         windowWidth = subwindow->GetUIExtensionHostWindowRect().Width();
1889     }
1890     if (GreatOrEqual(windowWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())
1891         && sheetKey_.hasValidTargetNode) {
1892         sheetType =  SheetType::SHEET_POPUP;
1893     }
1894     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1895     CHECK_NULL_RETURN(layoutProperty, sheetType);
1896     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1897     if (sheetStyle.sheetType.has_value()) {
1898         sheetType = sheetStyle.sheetType.value();
1899     }
1900     if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
1901         sheetType =  SheetType::SHEET_CENTER;
1902     }
1903     return sheetType;
1904 }
1905 
InitSheetTransitionAction(float offset)1906 void SheetPresentationPattern::InitSheetTransitionAction(float offset)
1907 {
1908     auto sheetNode = GetHost();
1909     CHECK_NULL_VOID(sheetNode);
1910     auto context = sheetNode->GetRenderContext();
1911     CHECK_NULL_VOID(context);
1912     if (IsShowInSubWindowTwoInOne()) {
1913         context->UpdateOpacity(0.0);
1914         context->UpdateTransformTranslate({ 0.0f, SUBWINDOW_SHEET_TRANSLATION.ConvertToPx() + offset, 0.0f });
1915     } else {
1916         context->UpdateTransformTranslate({ 0.0f, pageHeight_, 0.0f });
1917     }
1918 }
1919 
SheetTransitionAction(float offset,bool isStart,bool isTransitionIn)1920 void SheetPresentationPattern::SheetTransitionAction(float offset, bool isStart, bool isTransitionIn)
1921 {
1922     auto sheetNode = GetHost();
1923     CHECK_NULL_VOID(sheetNode);
1924     auto context = sheetNode->GetRenderContext();
1925     CHECK_NULL_VOID(context);
1926     if (!isTransitionIn) {
1927         // play sheet dismiss transition and move sheet down to out of screen
1928         InitSheetTransitionAction(offset);
1929         return;
1930     }
1931     // play sheet enter transition
1932     if (isStart) {
1933         // move sheet down to out of screen
1934         InitSheetTransitionAction(offset);
1935     } else {
1936         // move sheet up
1937         if (IsShowInSubWindowTwoInOne()) {
1938             context->UpdateOpacity(1.0);
1939         }
1940         context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1941     }
1942 }
1943 
GetSheetType()1944 SheetType SheetPresentationPattern::GetSheetType()
1945 {
1946     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1947         return SHEET_BOTTOM;
1948     }
1949     SheetType sheetType = SheetType::SHEET_BOTTOM;
1950     auto pipelineContext = PipelineContext::GetCurrentContext();
1951     CHECK_NULL_RETURN(pipelineContext, sheetType);
1952     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1953     CHECK_NULL_RETURN(layoutProperty, sheetType);
1954     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1955     if (sheetStyle.showInSubWindow.value_or(false)) {
1956         return ComputeSheetTypeInSubWindow();
1957     }
1958     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
1959     TAG_LOGD(AceLogTag::ACE_SHEET, "GetSheetType displayWindowRect info is : %{public}s",
1960         windowGlobalRect.ToString().c_str());
1961     DeviceType deviceType = SystemProperties::GetDeviceType();
1962     // only bottom when width is less than 600vp
1963     if ((windowGlobalRect.Width() < SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) ||
1964         (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM)) {
1965         return sheetStyle.bottomOffset.has_value() && deviceType == DeviceType::TWO_IN_ONE ?
1966             SheetType::SHEET_BOTTOM_OFFSET : SheetType::SHEET_BOTTOM;
1967     }
1968     if (sheetThemeType_ == "auto") {
1969         GetSheetTypeWithAuto(sheetType);
1970     } else if (sheetThemeType_ == "popup") {
1971         GetSheetTypeWithPopup(sheetType);
1972     }
1973     return sheetType;
1974 }
1975 
InitSheetMode()1976 void SheetPresentationPattern::InitSheetMode()
1977 {
1978     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1979     CHECK_NULL_VOID(layoutProperty);
1980     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1981     scrollSizeMode_ = sheetStyle.scrollSizeMode.value_or(ScrollSizeMode::FOLLOW_DETENT);
1982     keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL);
1983     sheetEffectEdge_ = sheetStyle.sheetEffectEdge.value_or(SheetEffectEdge::ALL);
1984 }
1985 
GetSheetTypeWithAuto(SheetType & sheetType)1986 void SheetPresentationPattern::GetSheetTypeWithAuto(SheetType& sheetType)
1987 {
1988     auto rootHeight = PipelineContext::GetCurrentRootHeight();
1989     auto rootWidth = PipelineContext::GetCurrentRootWidth();
1990     auto pipeline = PipelineContext::GetCurrentContext();
1991     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1992     CHECK_NULL_VOID(sheetTheme);
1993 #ifdef PREVIEW
1994     auto container = Container::Current();
1995     CHECK_NULL_VOID(container);
1996     if (container->IsFoldable() && container->GetCurrentFoldStatus() == FoldStatus::EXPAND) {
1997 #else
1998     // when big fold expand
1999     if (IsFoldExpand() && !sheetTheme->IsOnlyBottom()) {
2000 #endif
2001         sheetType = SheetType::SHEET_CENTER;
2002         auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2003         CHECK_NULL_VOID(layoutProperty);
2004         auto sheetStyle = layoutProperty->GetSheetStyleValue();
2005         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN) &&
2006             sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_POPUP) {
2007             sheetType = SheetType::SHEET_POPUP;
2008         }
2009     } else {
2010         if (LessNotEqual(rootHeight, rootWidth)) {
2011             sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
2012         } else {
2013             sheetType = SheetType::SHEET_BOTTOM;
2014         }
2015     }
2016 }
2017 
2018 void SheetPresentationPattern::GetSheetTypeWithPopup(SheetType& sheetType)
2019 {
2020     auto pipelineContext = PipelineContext::GetCurrentContext();
2021     double rootWidth = 0.0;
2022     if (windowSize_.has_value()) {
2023         rootWidth = windowSize_.value().Width();
2024     } else {
2025         rootWidth = PipelineContext::GetCurrentRootWidth();
2026     }
2027     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2028     CHECK_NULL_VOID(layoutProperty);
2029     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2030 #ifdef PREVIEW
2031     rootWidth = pipelineContext->GetDisplayWindowRectInfo().Width();
2032 #endif
2033     if (GreatOrEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2034         if (sheetStyle.sheetType.has_value()) {
2035             sheetType = sheetStyle.sheetType.value();
2036         } else {
2037             sheetType = SheetType::SHEET_POPUP;
2038         }
2039     } else if (GreatOrEqual(rootWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
2040                LessNotEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2041         if (sheetStyle.sheetType.has_value()) {
2042             sheetType = sheetStyle.sheetType.value();
2043         } else {
2044             sheetType = SheetType::SHEET_CENTER;
2045         }
2046     } else {
2047         sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
2048     }
2049     if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
2050         sheetType = SheetType::SHEET_CENTER;
2051     }
2052 }
2053 
2054 void SheetPresentationPattern::SetUIFirstSwitch(bool isFirstTransition, bool isNone)
2055 {
2056 #ifdef ENABLE_ROSEN_BACKEND
2057     if (!isFirstTransition) {
2058         return;
2059     }
2060     auto host = GetHost();
2061     CHECK_NULL_VOID(host);
2062     auto rosenContext = DynamicCast<RosenRenderContext>(host->GetRenderContext());
2063     CHECK_NULL_VOID(rosenContext);
2064     rosenContext->SetUIFirstSwitch(
2065         isNone ? OHOS::Rosen::RSUIFirstSwitch::NONE : OHOS::Rosen::RSUIFirstSwitch::MODAL_WINDOW_CLOSE);
2066 #endif
2067 }
2068 
2069 void SheetPresentationPattern::BubbleStyleSheetTransition(bool isTransitionIn)
2070 {
2071     auto host = this->GetHost();
2072     CHECK_NULL_VOID(host);
2073     if (!isTransitionIn) {
2074         const auto& overlayManager = GetOverlayManager();
2075         CHECK_NULL_VOID(overlayManager);
2076         auto maskNode = overlayManager->GetSheetMask(host);
2077         if (maskNode) {
2078             overlayManager->PlaySheetMaskTransition(maskNode, host, false);
2079         }
2080         StartOffsetExitingAnimation();
2081         StartAlphaExitingAnimation(
2082             [weakNode = AceType::WeakClaim(AceType::RawPtr(host)), weakPattern = AceType::WeakClaim(this)]() {
2083                 auto node = weakNode.Upgrade();
2084                 CHECK_NULL_VOID(node);
2085                 auto pattern = weakPattern.Upgrade();
2086                 CHECK_NULL_VOID(pattern);
2087                 const auto& overlayManager = pattern->GetOverlayManager();
2088                 CHECK_NULL_VOID(overlayManager);
2089                 overlayManager->FireAutoSave(node);
2090                 pattern->OnDisappear();
2091                 overlayManager->RemoveSheet(node);;
2092                 pattern->FireCallback("false");
2093             });
2094         overlayManager->CleanSheet(host, GetSheetKey());
2095     }
2096 }
2097 
2098 void SheetPresentationPattern::StartOffsetEnteringAnimation()
2099 {
2100     AnimationOption optionPosition;
2101     optionPosition.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2102     optionPosition.SetCurve(Curves::FRICTION);
2103     AnimationUtils::Animate(
2104         optionPosition,
2105         [weak = WeakClaim(this)]() {
2106             auto pattern = weak.Upgrade();
2107             CHECK_NULL_VOID(pattern);
2108             auto renderContext = pattern->GetRenderContext();
2109             CHECK_NULL_VOID(renderContext);
2110             renderContext->UpdateTransformTranslate({ 0.0f, Dimension(pattern->sheetOffsetY_), 0.0f });
2111         },
2112         nullptr);
2113 }
2114 
2115 void SheetPresentationPattern::StartAlphaEnteringAnimation(std::function<void()> finish)
2116 {
2117     AnimationOption optionAlpha;
2118     optionAlpha.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2119     optionAlpha.SetCurve(Curves::SHARP);
2120     AnimationUtils::Animate(
2121         optionAlpha,
2122         [weak = WeakClaim(this)]() {
2123             auto pattern = weak.Upgrade();
2124             CHECK_NULL_VOID(pattern);
2125             auto renderContext = pattern->GetRenderContext();
2126             CHECK_NULL_VOID(renderContext);
2127             renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
2128         },
2129         finish);
2130 }
2131 
2132 void SheetPresentationPattern::StartOffsetExitingAnimation()
2133 {
2134     AnimationOption optionPosition;
2135     optionPosition.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2136     optionPosition.SetCurve(Curves::FRICTION);
2137     AnimationUtils::Animate(
2138         optionPosition,
2139         [weak = WeakClaim(this)]() {
2140             auto pattern = weak.Upgrade();
2141             CHECK_NULL_VOID(pattern);
2142             auto renderContext = pattern->GetRenderContext();
2143             CHECK_NULL_VOID(renderContext);
2144             renderContext->UpdateTransformTranslate(
2145                 { 0.0f, Dimension(pattern->sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2146         },
2147         nullptr);
2148 }
2149 
2150 void SheetPresentationPattern::StartAlphaExitingAnimation(std::function<void()> finish)
2151 {
2152     AnimationOption optionAlpha;
2153     optionAlpha.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2154     optionAlpha.SetCurve(Curves::SHARP);
2155     AnimationUtils::Animate(
2156         optionAlpha,
2157         [weak = WeakClaim(this)]() {
2158             auto pattern = weak.Upgrade();
2159             CHECK_NULL_VOID(pattern);
2160             auto renderContext = pattern->GetRenderContext();
2161             CHECK_NULL_VOID(renderContext);
2162             renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2163         },
2164         finish);
2165 }
2166 
2167 RefPtr<RenderContext> SheetPresentationPattern::GetRenderContext()
2168 {
2169     auto frameNode = GetHost();
2170     CHECK_NULL_RETURN(frameNode, nullptr);
2171     return frameNode->GetRenderContext();
2172 }
2173 
2174 bool SheetPresentationPattern::PostTask(const TaskExecutor::Task& task, const std::string& name)
2175 {
2176     auto pipeline = PipelineBase::GetCurrentContext();
2177     CHECK_NULL_RETURN(pipeline, false);
2178     auto taskExecutor = pipeline->GetTaskExecutor();
2179     CHECK_NULL_RETURN(taskExecutor, false);
2180     return taskExecutor->PostTask(task, TaskExecutor::TaskType::UI, name);
2181 }
2182 
2183 void SheetPresentationPattern::ResetToInvisible()
2184 {
2185     auto renderContext = GetRenderContext();
2186     CHECK_NULL_VOID(renderContext);
2187     renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2188     renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2189 }
2190 
2191 bool SheetPresentationPattern::IsFoldExpand()
2192 {
2193     bool isExpand = false;
2194     auto container = Container::Current();
2195     CHECK_NULL_RETURN(container, false);
2196     auto foldStatus = container->GetCurrentFoldStatus();
2197     isExpand = foldStatus != FoldStatus::FOLDED && foldStatus != FoldStatus::UNKNOWN;
2198     if (isExpand) {
2199         TAG_LOGD(AceLogTag::ACE_SHEET, "Get Fold status IsFoldExpand is true");
2200         return true;
2201     } else {
2202         return false;
2203     }
2204 }
2205 
2206 void SheetPresentationPattern::ChangeSheetHeight(float height)
2207 {
2208     if (!NearEqual(height_, height)) {
2209         isDirectionUp_ = GreatNotEqual(height, height_);
2210         height_ = height;
2211         SetCurrentHeightToOverlay(height_);
2212     }
2213 }
2214 
2215 void SheetPresentationPattern::StartSheetTransitionAnimation(
2216     const AnimationOption& option, bool isTransitionIn, float offset)
2217 {
2218     auto host = GetHost();
2219     CHECK_NULL_VOID(host);
2220     auto context = host->GetRenderContext();
2221     CHECK_NULL_VOID(context);
2222     isAnimationProcess_ = true;
2223     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
2224     CHECK_NULL_VOID(sheetPattern);
2225     auto sheetParent = DynamicCast<FrameNode>(host->GetParent());
2226     CHECK_NULL_VOID(sheetParent);
2227     if (isTransitionIn) {
2228         HandleDragEndAccessibilityEvent();
2229         animation_ = AnimationUtils::StartAnimation(
2230             option,
2231             [context, offset]() {
2232                 if (context) {
2233                     context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
2234                 }
2235             },
2236             option.GetOnFinishEvent());
2237     } else {
2238         host->OnAccessibilityEvent(
2239             AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
2240         sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2241             HitTestMode::HTMTRANSPARENT);
2242         animation_ = AnimationUtils::StartAnimation(
2243             option,
2244             [context, weak = WeakClaim(this), offset, isTransitionIn]() {
2245                 if (context) {
2246                     auto pattern = weak.Upgrade();
2247                     pattern->SheetTransitionAction(offset, false, isTransitionIn);
2248                     pattern->DismissSheetShadow(context);
2249                 }
2250             },
2251             option.GetOnFinishEvent());
2252         const auto& overlayManager = GetOverlayManager();
2253         CHECK_NULL_VOID(overlayManager);
2254         overlayManager->CleanSheet(host, GetSheetKey());
2255     }
2256 }
2257 
2258 void SheetPresentationPattern::DismissSheetShadow(const RefPtr<RenderContext>& context)
2259 {
2260     auto shadow = context->GetBackShadow();
2261     if (!shadow.has_value()) {
2262         shadow = Shadow::CreateShadow(ShadowStyle::None);
2263     }
2264     auto color = shadow->GetColor();
2265     auto newColor = color.ChangeAlpha(0);
2266     shadow->SetColor(newColor);
2267     context->UpdateBackShadow(shadow.value());
2268 }
2269 
2270 void SheetPresentationPattern::ClipSheetNode()
2271 {
2272     auto host = GetHost();
2273     CHECK_NULL_VOID(host);
2274     auto geometryNode = host->GetGeometryNode();
2275     CHECK_NULL_VOID(geometryNode);
2276     auto sheetSize = geometryNode->GetFrameSize();
2277     auto pipeline = PipelineContext::GetCurrentContext();
2278     CHECK_NULL_VOID(pipeline);
2279     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2280     CHECK_NULL_VOID(sheetTheme);
2281     auto renderContext = host->GetRenderContext();
2282     CHECK_NULL_VOID(renderContext);
2283     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2284     CHECK_NULL_VOID(layoutProperty);
2285     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2286     ResetClipShape();
2287     auto sheetType = GetSheetType();
2288     BorderRadiusProperty borderRadius(sheetTheme->GetSheetRadius());
2289     CalculateSheetRadius(borderRadius);
2290     if (IsSheetBottom()) {
2291         // set 1px for avoiding doudble radius black lines.
2292         borderRadius.radiusBottomLeft = 1.0_px;
2293         borderRadius.radiusBottomRight = 1.0_px;
2294     }
2295     renderContext->UpdateBorderRadius(borderRadius);
2296     if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
2297         renderContext->UpdateOuterBorderRadius(borderRadius);
2298     }
2299     if (sheetType == SheetType::SHEET_POPUP && sheetPopupInfo_.showArrow) {
2300         std::string clipPath;
2301         clipPath = GetPopupStyleSheetClipPath(sheetSize, borderRadius);
2302         auto path = AceType::MakeRefPtr<Path>();
2303         path->SetValue(clipPath);
2304         path->SetBasicShapeType(BasicShapeType::PATH);
2305         renderContext->UpdateClipShape(path);
2306     }
2307 }
2308 
2309 bool SheetPresentationPattern::IsWindowSizeChangedWithUndefinedReason(
2310     int32_t width, int32_t height, WindowSizeChangeReason type)
2311 {
2312     bool isWindowChanged = false;
2313     if (windowSize_.has_value()) {
2314         isWindowChanged = (type == WindowSizeChangeReason::UNDEFINED &&
2315                            (windowSize_->Width() != width || windowSize_->Height() != height));
2316     }
2317     return isWindowChanged;
2318 }
2319 
2320 void SheetPresentationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
2321 {
2322     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet WindowSizeChangeReason type is: %{public}d", type);
2323     auto sheetType = GetSheetType();
2324     if ((type == WindowSizeChangeReason::ROTATION) &&
2325         ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE) ||
2326          (sheetType == SheetType::SHEET_BOTTOM_OFFSET))) {
2327         windowRotate_ = true;
2328         SetColumnMinSize(true);
2329         // Before rotation, reset to the initial mode sheet ratio of the current vertical or horizontal screen
2330         // It's actually a state where the soft keyboard is not pulled up
2331         if (isScrolling_) {
2332             ScrollTo(.0f);
2333         }
2334     }
2335     if (IsWindowSizeChangedWithUndefinedReason(width, height, type)) {
2336         windowChanged_ = true;
2337     }
2338     windowSize_ = SizeT<int32_t>(width, height);
2339     if (type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::DRAG ||
2340         type == WindowSizeChangeReason::RESIZE) {
2341         windowChanged_ = true;
2342     }
2343 
2344     if (type == WindowSizeChangeReason::ROTATION && sheetType == SheetType::SHEET_CENTER) {
2345         auto recoverTask = [weak = WeakClaim(this), id = Container::CurrentId()] () {
2346             ContainerScope scope(id);
2347             auto pattern = weak.Upgrade();
2348             CHECK_NULL_VOID(pattern);
2349             pattern->RecoverHalfFoldOrAvoidStatus();
2350         };
2351         PostTask(recoverTask, "ArkUISheetHalfFoldStatusSwitch");
2352     }
2353 
2354     auto host = GetHost();
2355     CHECK_NULL_VOID(host);
2356     auto pipelineContext = host->GetContext();
2357     CHECK_NULL_VOID(pipelineContext);
2358     UpdateSheetWhenSheetTypeChanged();
2359     auto windowManager = pipelineContext->GetWindowManager();
2360     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
2361         host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2362     }
2363 }
2364 
2365 void SheetPresentationPattern::TranslateTo(float height)
2366 {
2367     auto host = GetHost();
2368     CHECK_NULL_VOID(host);
2369     auto context = host->GetRenderContext();
2370     CHECK_NULL_VOID(context);
2371     context->UpdateTransformTranslate({ 0.0f, height, 0.0f });
2372 }
2373 
2374 void SheetPresentationPattern::ScrollTo(float height)
2375 {
2376     // height = 0 or height > 0
2377     auto host = GetHost();
2378     CHECK_NULL_VOID(host);
2379     auto scroll = GetSheetScrollNode();
2380     CHECK_NULL_VOID(scroll);
2381     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2382     CHECK_NULL_VOID(scrollPattern);
2383     auto layoutProp = scrollPattern->GetLayoutProperty<ScrollLayoutProperty>();
2384     CHECK_NULL_VOID(layoutProp);
2385     auto geometryNode = scroll->GetGeometryNode();
2386     CHECK_NULL_VOID(geometryNode);
2387     // height > 0, Scroll will reduce height, and become scrolling.
2388     isScrolling_ = height > 0;
2389     SetColumnMinSize(!isScrolling_);
2390     if (!AdditionalScrollTo(scroll, height)) {
2391         scrollHeight_ = height;
2392         float maxScrollDecreaseHeight = scrollHeight_;
2393         float maxAvoidSize = keyboardHeight_ - (sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.f);
2394         auto pipelineContext = host->GetContext();
2395         CHECK_NULL_VOID(pipelineContext);
2396         auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2397         /*
2398          * when the screen rotates from portrait to landscape, and the sheet needs to avoid caret twice,
2399          * there is a condition that, the caret position that does not exceed the height of sheet in portrait mode,
2400          * may be exceed the height of sheet in landscape mode. In that case,
2401          * the distance to avoid caret may exceed as well. To keep bindSheet display normally,
2402          * we need to obtain the minimum content height and then the avoidance is made.
2403          */
2404         if (useCaretAvoidMode && NonNegative(maxAvoidSize) && NonNegative(maxAvoidSize - sheetHeightUp_) &&
2405             maxScrollDecreaseHeight > maxAvoidSize - sheetHeightUp_) {
2406             maxScrollDecreaseHeight = maxAvoidSize - sheetHeightUp_;
2407         }
2408         layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
2409             CalcLength(GetScrollHeight() - maxScrollDecreaseHeight)));
2410         auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2411         scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2412     }
2413     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2414 }
2415 
2416 bool SheetPresentationPattern::AdditionalScrollTo(const RefPtr<FrameNode>& scroll, float height)
2417 {
2418     if (NonPositive(height)) {
2419         return false;
2420     }
2421     // If ScrollHeight is larger than childHeight
2422     // there will be a scene that is still larger than childHeight after reducing Scrollheight to moving sheet up
2423     // At this point, even if JumpToPosition is negative, the Scroll will still not to scroll
2424     auto buildContent = GetFirstFrameNodeOfBuilder();
2425     CHECK_NULL_RETURN(buildContent, false);
2426     auto scrollHeight = scroll->GetGeometryNode() ? scroll->GetGeometryNode()->GetFrameSize().Height() : .0f;
2427     auto host = GetHost();
2428     CHECK_NULL_RETURN(host, false);
2429     auto pipelineContext = host->GetContext();
2430     CHECK_NULL_RETURN(pipelineContext, false);
2431     auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2432     if (useCaretAvoidMode) {
2433         scrollHeight = GetScrollHeight();
2434     }
2435     auto childHeight = buildContent->GetGeometryNode() ? buildContent->GetGeometryNode()->GetFrameSize().Height() : .0f;
2436     if (scrollHeight <= childHeight) {
2437         return false;
2438     }
2439     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2440     CHECK_NULL_RETURN(layoutProp, false);
2441     auto geometryNode = scroll->GetGeometryNode();
2442     CHECK_NULL_RETURN(geometryNode, false);
2443     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2444     CHECK_NULL_RETURN(scrollPattern, false);
2445     // Scroll first shrinks to the same size as childHeight, then reduces the height to allow it to scroll
2446     scrollHeight_ = scrollHeight - childHeight + height;
2447     layoutProp->UpdateUserDefinedIdealSize(
2448         CalcSize(std::nullopt, CalcLength(GetScrollHeight() - (scrollHeight - childHeight + height))));
2449     // And then scroll move the content with '-height' offset
2450     auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2451     scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2452     return true;
2453 }
2454 
2455 float SheetPresentationPattern::GetFirstChildHeight() const
2456 {
2457     auto firstChildNode = GetTitleBuilderNode();
2458     CHECK_NULL_RETURN(firstChildNode, 0.0f);
2459     auto firstChildGeometryNode = firstChildNode->GetGeometryNode();
2460     CHECK_NULL_RETURN(firstChildGeometryNode, 0.0f);
2461     auto titleHeight = firstChildGeometryNode->GetFrameSize().Height();
2462     return titleHeight;
2463 }
2464 
2465 void SheetPresentationPattern::SetColumnMinSize(bool reset)
2466 {
2467     auto buildContent = GetFirstFrameNodeOfBuilder();
2468     CHECK_NULL_VOID(buildContent);
2469     auto geometryNode = buildContent->GetGeometryNode();
2470     CHECK_NULL_VOID(geometryNode);
2471     auto props = buildContent->GetLayoutProperty<LayoutProperty>();
2472     CHECK_NULL_VOID(props);
2473     if (reset) {
2474         props->ResetCalcMinSize();
2475         return;
2476     }
2477     props->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(builderHeight_)));
2478 }
2479 
2480 void SheetPresentationPattern::CalculateSheetRadius(BorderRadiusProperty& sheetRadius)
2481 {
2482     auto host = GetHost();
2483     CHECK_NULL_VOID(host);
2484     auto geometryNode = host->GetGeometryNode();
2485     CHECK_NULL_VOID(geometryNode);
2486     auto sheetSize = geometryNode->GetFrameSize();
2487     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2488     CHECK_NULL_VOID(layoutProperty);
2489     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2490     if (sheetSize.IsPositive()) {
2491         CalculateAloneSheetRadius(sheetRadius.radiusTopLeft, sheetStyle.radius->radiusTopLeft);
2492         CalculateAloneSheetRadius(sheetRadius.radiusTopRight, sheetStyle.radius->radiusTopRight);
2493         CalculateAloneSheetRadius(sheetRadius.radiusBottomLeft, sheetStyle.radius->radiusBottomLeft);
2494         CalculateAloneSheetRadius(sheetRadius.radiusBottomRight, sheetStyle.radius->radiusBottomRight);
2495     }
2496 }
2497 
2498 void SheetPresentationPattern::CalculateAloneSheetRadius(
2499     std::optional<Dimension>& sheetRadius, const std::optional<Dimension>& sheetStyleRadius)
2500 {
2501     auto host = GetHost();
2502     CHECK_NULL_VOID(host);
2503     auto geometryNode = host->GetGeometryNode();
2504     CHECK_NULL_VOID(geometryNode);
2505     auto sheetSize = geometryNode->GetFrameSize();
2506     float half = 0.5f;
2507     if (sheetStyleRadius.has_value() && GreatOrEqual(sheetStyleRadius->Value(), 0.0f)) {
2508         if (sheetStyleRadius->Unit() == DimensionUnit::PERCENT) {
2509             sheetRadius = Dimension(sheetStyleRadius->Value() * sheetSize.Width());
2510         } else {
2511             sheetRadius = sheetStyleRadius;
2512         }
2513     }
2514     // The maximum value of radius is half the width of the page.
2515     if (sheetSize.Width() * half < sheetRadius->ConvertToPx()) {
2516         sheetRadius = Dimension(sheetSize.Width() * half);
2517     }
2518 }
2519 
2520 std::string SheetPresentationPattern::GetPopupStyleSheetClipPath(
2521     const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
2522 {
2523     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2524         return GetPopupStyleSheetClipPathNew(sheetSize, sheetRadius);
2525     }
2526     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
2527     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
2528     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
2529     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
2530     std::string path = MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
2531     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, SHEET_ARROW_HEIGHT.ConvertToPx());
2532     path +=
2533         LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
2534     path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
2535         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P2_OFFSET_Y.ConvertToPx()); // P2
2536     path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
2537         arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
2538         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P4_OFFSET_Y.ConvertToPx()); // P4
2539     path +=
2540         LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
2541     path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
2542     path += ArcTo(
2543         radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
2544     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
2545     path +=
2546         ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0, sheetSize.Width() - radiusBottomRight, sheetSize.Height());
2547     path += LineTo(radiusBottomLeft, sheetSize.Height());
2548     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f, sheetSize.Height() - radiusBottomLeft);
2549     return path + "Z";
2550 }
2551 
2552 std::string SheetPresentationPattern::GetCenterStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2553 {
2554     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2555     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2556     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2557     path += ArcTo(
2558         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2559     path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
2560     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
2561         sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
2562     path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
2563     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
2564         sheetSize.Height() - sheetRadius.ConvertToPx());
2565     return path + "Z";
2566 }
2567 
2568 std::string SheetPresentationPattern::GetBottomStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2569 {
2570     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2571     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2572     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2573     path += ArcTo(
2574         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2575     path += LineTo(sheetSize.Width(), sheetSize.Height());
2576     path += LineTo(0.0f, sheetSize.Height());
2577     return path + "Z";
2578 }
2579 
2580 std::string SheetPresentationPattern::MoveTo(double x, double y)
2581 {
2582     return "M" + std::to_string(x) + " " + std::to_string(y) + " ";
2583 }
2584 
2585 std::string SheetPresentationPattern::LineTo(double x, double y)
2586 {
2587     return "L" + std::to_string(x) + " " + std::to_string(y) + " ";
2588 }
2589 
2590 std::string SheetPresentationPattern::ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y)
2591 {
2592     int32_t sweep_flag = 1;
2593     return "A" + std::to_string(rx) + " " + std::to_string(ry) + " " + std::to_string(rotation) + " " +
2594            std::to_string(arc_flag) + " " + std::to_string(sweep_flag) + " " + std::to_string(x) + " " +
2595            std::to_string(y) + " ";
2596 }
2597 
2598 float SheetPresentationPattern::GetFitContentHeight()
2599 {
2600     auto sheetNode = GetHost();
2601     CHECK_NULL_RETURN(sheetNode, 0.0f);
2602     auto titleColumn = DynamicCast<FrameNode>(sheetNode->GetFirstChild());
2603     CHECK_NULL_RETURN(titleColumn, 0.0f);
2604     auto titleGeometryNode = titleColumn->GetGeometryNode();
2605     auto builderNode = GetFirstFrameNodeOfBuilder();
2606     CHECK_NULL_RETURN(builderNode, 0.0f);
2607     auto builderGeometryNode = builderNode->GetGeometryNode();
2608     return builderGeometryNode->GetMarginFrameSize().Height() + titleGeometryNode->GetFrameSize().Height();
2609 }
2610 
2611 RefPtr<OverlayManager> SheetPresentationPattern::GetOverlayManager()
2612 {
2613     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2614     CHECK_NULL_RETURN(layoutProp, nullptr);
2615     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2616 
2617     if (layoutProp->GetSheetStyleValue(SheetStyle()).showInSubWindow.value_or(false)) {
2618         auto aceContainer = AceEngine::Get().GetContainer(GetSubWindowId());
2619         CHECK_NULL_RETURN(aceContainer, nullptr);
2620         auto context = DynamicCast<NG::PipelineContext>(aceContainer->GetPipelineContext());
2621         CHECK_NULL_RETURN(context, nullptr);
2622         auto overlayManager = context->GetOverlayManager();
2623         return overlayManager;
2624     }
2625     if (!showInPage) {
2626         return PipelineContext::GetCurrentContext()->GetOverlayManager();
2627     }
2628     auto host = GetHost();
2629     CHECK_NULL_RETURN(host, nullptr);
2630     auto sheetWrapper = host->GetParent();
2631     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2632     auto node = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2633     CHECK_NULL_RETURN(node, nullptr);
2634     RefPtr<OverlayManager> overlay;
2635     if (node->GetTag() == V2::PAGE_ETS_TAG) {
2636         auto pattern = node->GetPattern<PagePattern>();
2637         CHECK_NULL_RETURN(pattern, nullptr);
2638         overlay = pattern->GetOverlayManager();
2639     } else if (node->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
2640         auto pattern = node->GetPattern<NavDestinationPattern>();
2641         CHECK_NULL_RETURN(pattern, nullptr);
2642         overlay = pattern->GetOverlayManager();
2643     }
2644     if (!overlay) {
2645         auto overlayManager = overlayManager_.Upgrade();
2646         overlay = overlayManager;
2647     }
2648     return overlay;
2649 }
2650 
2651 RefPtr<FrameNode> SheetPresentationPattern::GetFirstFrameNodeOfBuilder() const
2652 {
2653     auto scrollNode = GetSheetScrollNode();
2654     CHECK_NULL_RETURN(scrollNode, nullptr);
2655     auto buildNode = scrollNode->GetChildAtIndex(0);
2656     CHECK_NULL_RETURN(buildNode, nullptr);
2657     return AceType::DynamicCast<FrameNode>(buildNode->GetFrameChildByIndex(0, true));
2658 }
2659 
2660 void SheetPresentationPattern::GetBuilderInitHeight()
2661 {
2662     auto buildContent = GetFirstFrameNodeOfBuilder();
2663     CHECK_NULL_VOID(buildContent);
2664     auto geometryNode = buildContent->GetGeometryNode();
2665     CHECK_NULL_VOID(geometryNode);
2666     builderHeight_ = geometryNode->GetFrameSize().Height();
2667 }
2668 
2669 RefPtr<FrameNode> SheetPresentationPattern::GetOverlayRoot()
2670 {
2671     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2672     CHECK_NULL_RETURN(layoutProp, nullptr);
2673     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2674     if (!showInPage) {
2675         auto overlay = PipelineContext::GetCurrentContext()->GetOverlayManager();
2676         CHECK_NULL_RETURN(overlay, nullptr);
2677         return AceType::DynamicCast<FrameNode>(overlay->GetRootNode().Upgrade());
2678     }
2679     auto host = GetHost();
2680     CHECK_NULL_RETURN(host, nullptr);
2681     auto sheetWrapper = host->GetParent();
2682     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2683     return AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2684 }
2685 
2686 float SheetPresentationPattern::GetRootOffsetYToWindow()
2687 {
2688     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2689     CHECK_NULL_RETURN(layoutProp, .0f);
2690     const auto& showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2691     CHECK_NULL_RETURN(showInPage, .0f);
2692     const auto& overlayNode = GetOverlayRoot();
2693     CHECK_NULL_RETURN(overlayNode, .0f);
2694     auto parertOffset = overlayNode->GetOffsetRelativeToWindow();
2695     TAG_LOGD(AceLogTag::ACE_OVERLAY, "PageLevel Node's offset to window: %{public}s", parertOffset.ToString().c_str());
2696     return parertOffset.GetY();
2697 }
2698 
2699 void SheetPresentationPattern::DumpAdvanceInfo()
2700 {
2701     DumpLog::GetInstance().AddDesc("------------------------------------------");
2702     DumpLog::GetInstance().AddDesc(
2703         "TargetId: " + std::to_string(static_cast<int32_t>(targetId_)) + " , TargetTag : " + targetTag_);
2704     DumpLog::GetInstance().AddDesc("------------ SheetPage Pattern : ");
2705     DumpLog::GetInstance().AddDesc(
2706         std::string("SheetType: ").append(std::to_string(static_cast<int32_t>(GetSheetType()))));
2707     DumpLog::GetInstance().AddDesc(std::string("SheetPage Node Height: ").append(std::to_string(centerHeight_)));
2708     DumpLog::GetInstance().AddDesc(
2709         std::string("Sheet Height [start from the bottom, KeyboardHeight = 0]: ").append(std::to_string(height_)));
2710     DumpLog::GetInstance().AddDesc(
2711         std::string("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]: ")
2712             .append(std::to_string(sheetMaxHeight_)));
2713     DumpLog::GetInstance().AddDesc(std::string("Page Height: ").append(std::to_string(pageHeight_)));
2714     DumpLog::GetInstance().AddDesc(
2715         std::string("StatusBar Height [current sheetType needed]: ").append(std::to_string(sheetTopSafeArea_)));
2716     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetX: ").append(std::to_string(sheetOffsetX_)));
2717     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetY: ").append(std::to_string(sheetOffsetY_)));
2718     DumpLog::GetInstance().AddDesc(std::string("SheetMaxWidth: ").append(std::to_string(sheetMaxWidth_)));
2719     DumpLog::GetInstance().AddDesc(std::string("FitContent Height: ").append(std::to_string(sheetFitContentHeight_)));
2720     DumpLog::GetInstance().AddDesc("SheetThemeType: " + sheetThemeType_);
2721     DumpLog::GetInstance().AddDesc(std::string("currentOffset: ").append(std::to_string(currentOffset_)));
2722     DumpLog::GetInstance().AddDesc("------------");
2723     DumpLog::GetInstance().AddDesc(
2724         std::string("Height ScrollTo [KeyboardHeight > 0, and is scrolling]: ").append(std::to_string(-scrollHeight_)));
2725     DumpLog::GetInstance().AddDesc(std::string("KeyboardHeight: ").append(std::to_string(keyboardHeight_)));
2726     DumpLog::GetInstance().AddDesc(std::string("is scrolling: ").append(isScrolling_ ? "true" : "false"));
2727     DumpLog::GetInstance().AddDesc(std::string("SheetHeightUp[sheet offset to move up when avoiding keyboard]: ")
2728                                        .append(std::to_string(sheetHeightUp_)));
2729     DumpLog::GetInstance().AddDesc("------------");
2730     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2731     CHECK_NULL_VOID(layoutProperty);
2732     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2733     DumpLog::GetInstance().AddDesc(
2734         std::string("height: ").append(sheetStyle.sheetHeight.height.has_value() ?
2735         sheetStyle.sheetHeight.height->ToString() : "None"));
2736     DumpLog::GetInstance().AddDesc(
2737         ("sheetMode: ") + (sheetStyle.sheetHeight.sheetMode.has_value()
2738                                   ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value()))
2739                                   : "None"));
2740     DumpLog::GetInstance().AddDesc(std::string("detents' Size: ").append(std::to_string(sheetStyle.detents.size())));
2741     DumpLog::GetInstance().AddDesc(std::string("IsShouldDismiss: ").append(shouldDismiss_ ? "true" : "false"));
2742 }
2743 
2744 void SheetPresentationPattern::FireOnHeightDidChange()
2745 {
2746     auto height = 0.0f;
2747     if (!IsSheetBottomStyle()) {
2748         height = centerHeight_;
2749     } else {
2750         height = height_;
2751     }
2752     if (NearEqual(preDidHeight_, height)) {
2753         return;
2754     }
2755     OnHeightDidChange(height);
2756     preDidHeight_ = height;
2757 }
2758 
2759 void SheetPresentationPattern::FireOnDetentsDidChange(float height)
2760 {
2761     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2762     CHECK_NULL_VOID(layoutProperty);
2763     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2764     if (!IsSheetBottomStyle() || NearEqual(preDetentsHeight_, height) ||
2765         LessOrEqual(sheetStyle.detents.size(), 0)) {
2766         return;
2767     }
2768     OnDetentsDidChange(height);
2769     preDetentsHeight_ = height;
2770 }
2771 
2772 void SheetPresentationPattern::FireOnWidthDidChange(RefPtr<FrameNode> sheetNode)
2773 {
2774     auto sheetGeo = sheetNode->GetGeometryNode();
2775     CHECK_NULL_VOID(sheetGeo);
2776     auto width = sheetGeo->GetFrameSize().Width();
2777     if (NearEqual(preWidth_, width)) {
2778         return;
2779     }
2780     onWidthDidChange(width);
2781     preWidth_ = width;
2782 }
2783 
2784 void SheetPresentationPattern::FireOnTypeDidChange()
2785 {
2786     auto sheetType = sheetType_;
2787     if (IsSheetBottomStyle() || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
2788         sheetType = SheetType::SHEET_BOTTOM;
2789     }
2790     if (preType_ == sheetType) {
2791         return;
2792     }
2793     onTypeDidChange(sheetType);
2794     preType_ = sheetType;
2795 }
2796 
2797 bool SheetPresentationPattern::IsScrollOutOfBoundary()
2798 {
2799     auto scrollNode = GetSheetScrollNode();
2800     CHECK_NULL_RETURN(scrollNode, false);
2801     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2802     CHECK_NULL_RETURN(scrollPattern, false);
2803     return scrollPattern->OutBoundaryCallback();
2804 }
2805 
2806 void SheetPresentationPattern::OnScrollStartRecursive(
2807     WeakPtr<NestableScrollContainer> child, float position, float velocity)
2808 {
2809     InitScrollProps();
2810     if (animation_ && isAnimationProcess_) {
2811         AnimationUtils::StopAnimation(animation_);
2812         isAnimationBreak_ = true;
2813     }
2814     currentOffset_ = 0.0f;
2815     isSheetNeedScroll_ = false;
2816     isDirectionUp_ = true;
2817     GetCurrentBroadcastDetentsIndex();
2818 }
2819 
2820 ScrollResult SheetPresentationPattern::HandleScroll(float scrollOffset, int32_t source, NestedState state,
2821     float velocity)
2822 {
2823     if (state == NestedState::CHILD_CHECK_OVER_SCROLL) {
2824         return {scrollOffset, true};
2825     }
2826     ScrollResult result = {0, true};
2827     if (GreatOrEqual(currentOffset_, 0.0) && (source == SCROLL_FROM_UPDATE) && !isSheetNeedScroll_) {
2828         isSheetNeedScroll_ = true;
2829     }
2830     if (!isSheetNeedScroll_ || IsScrollOutOfBoundary()) {
2831         return {scrollOffset, true};
2832     }
2833     ScrollState scrollState = source == SCROLL_FROM_ANIMATION ? ScrollState::FLING : ScrollState::SCROLL;
2834     if (state == NestedState::CHILD_SCROLL) {
2835         if (scrollState == ScrollState::SCROLL) {
2836             return HandleScrollWithSheet(scrollOffset);
2837         }
2838         if (isSheetPosChanged_) {
2839             HandleDragEnd(scrollOffset > 0 ? SHEET_VELOCITY_THRESHOLD : -SHEET_VELOCITY_THRESHOLD);
2840             isSheetPosChanged_ = false;
2841         }
2842     } else if (state == NestedState::CHILD_OVER_SCROLL) {
2843         isSheetNeedScroll_ = false;
2844         return {scrollOffset, true};
2845     }
2846     return result;
2847 }
2848 
2849 ScrollResult SheetPresentationPattern::HandleScrollWithSheet(float scrollOffset)
2850 {
2851     ScrollResult result = {0, true};
2852     auto sheetType = GetSheetType();
2853     auto sheetDetentsSize = sheetDetentHeight_.size();
2854     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0) || IsShowInSubWindowTwoInOne()) {
2855         isSheetNeedScroll_ = false;
2856         return {scrollOffset, true};
2857     }
2858 
2859     auto currentHeightPos = GetSheetHeightBeforeDragUpdate();
2860     bool isDraggingUp = LessNotEqual(scrollOffset, 0.0f);
2861     bool isReachMaxSheetHeight = GreatOrEqual(currentHeightPos, GetMaxSheetHeightBeforeDragUpdate());
2862 
2863     // When dragging up the sheet, and sheet height is larger than sheet content height,
2864     // the sheet height should be updated.
2865     // When dragging up the sheet, and sheet height is less than or equal to sheet content height,
2866     // the sheet content should scrolling.
2867     if ((NearZero(currentOffset_)) && isDraggingUp && isReachMaxSheetHeight) {
2868         isSheetNeedScroll_ = false;
2869         return {scrollOffset, true};
2870     }
2871 
2872     // When dragging up the sheet, and sheet height is larger than max height,
2873     // should set the coefficient of friction.
2874     bool isExceedMaxSheetHeight =
2875         GreatNotEqual((currentHeightPos - currentOffset_), GetMaxSheetHeightBeforeDragUpdate());
2876     bool isNeedCalculateFriction = isExceedMaxSheetHeight && isDraggingUp;
2877     if (isNeedCalculateFriction && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
2878         auto friction = CalculateFriction((currentHeightPos - currentOffset_) / sheetMaxHeight_, GetRadio());
2879         scrollOffset = scrollOffset * friction;
2880     }
2881 
2882     auto host = GetHost();
2883     CHECK_NULL_RETURN(host, result);
2884     currentOffset_ = currentOffset_ + scrollOffset;
2885     auto pageHeight = GetPageHeightWithoutOffset();
2886     auto sheetOffsetInPage = pageHeight - currentHeightPos + currentOffset_;
2887     if (LessOrEqual(sheetOffsetInPage, pageHeight - sheetMaxHeight_)) {
2888         sheetOffsetInPage = pageHeight - sheetMaxHeight_;
2889         currentOffset_ = currentHeightPos - sheetMaxHeight_;
2890     }
2891     bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDraggingUp;
2892     if (isNeedChangeScrollHeight) {
2893         ChangeScrollHeight(currentHeightPos - currentOffset_);
2894     }
2895     HandleFollowAccessibilityEvent(currentHeightPos - currentOffset_);
2896     auto renderContext = host->GetRenderContext();
2897     renderContext->UpdateTransformTranslate({ 0.0f, sheetOffsetInPage, 0.0f });
2898     isSheetPosChanged_ = NearZero(scrollOffset) ? false : true;
2899     if (IsSheetBottomStyle()) {
2900         OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
2901     }
2902     isSheetPosChanged_ = true;
2903     return result;
2904 }
2905 
2906 void SheetPresentationPattern::OnScrollEndRecursive(const std::optional<float>& velocity)
2907 {
2908     if (isSheetPosChanged_) {
2909         HandleDragEnd(velocity.value_or(0.f));
2910         isSheetPosChanged_ = false;
2911     }
2912 }
2913 
2914 bool SheetPresentationPattern::HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child)
2915 {
2916     if (isSheetPosChanged_) {
2917         HandleDragEnd(velocity);
2918         isSheetPosChanged_ = false;
2919     }
2920     // Use child edge effect
2921     if (!isSheetNeedScroll_) {
2922         return false;
2923     }
2924     return true;
2925 }
2926 
2927 bool SheetPresentationPattern::IsTypeNeedAvoidAiBar()
2928 {
2929     auto overlay = GetOverlayManager();
2930     auto layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2931     if (overlay && overlay->IsRootExpansive() &&
2932         layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false)) {
2933         return false;
2934     }
2935     return sheetType_ == SheetType::SHEET_BOTTOM || sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE ||
2936            sheetType_ == SheetType::SHEET_BOTTOM_OFFSET;
2937 }
2938 
2939 void SheetPresentationPattern::IsNeedPlayTransition(const SheetStyle& inputStyle)
2940 {
2941     isPlayTransition_ = false;
2942     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2943     CHECK_NULL_VOID(layoutProperty);
2944     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2945     if (preStyle.sheetHeight.height != inputStyle.sheetHeight.height) {
2946         isPlayTransition_ = true;
2947         return;
2948     }
2949     if (preStyle.detents != inputStyle.detents) {
2950         isPlayTransition_ = true;
2951         return;
2952     }
2953     if (preStyle.sheetHeight.sheetMode != inputStyle.sheetHeight.sheetMode) {
2954         isPlayTransition_ = true;
2955         return;
2956     }
2957     isPlayTransition_ = UpdateIndexByDetentSelection(inputStyle, false) || isPlayTransition_;
2958 }
2959 
2960 bool SheetPresentationPattern::UpdateIndexByDetentSelection(const SheetStyle& inputStyle, bool isFirstTransition)
2961 {
2962     if (!inputStyle.detentSelection.has_value() || inputStyle.detents.size() == 0) {
2963         // when input detentSelection or detent selection is invalid
2964         return false;
2965     }
2966     auto selection = inputStyle.detentSelection.value();
2967     if ((selection.sheetMode.has_value() && selection.sheetMode.value() == NG::SheetMode::AUTO) ||
2968         (selection.height.has_value() && selection.height.value().IsNegative())) {
2969         return false;
2970     }
2971     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2972     CHECK_NULL_RETURN(layoutProperty, false);
2973     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2974     if (!isFirstTransition && preStyle.detentSelection == inputStyle.detentSelection) {
2975         // only when sheet is first pulled up or pre-detents equal to current detents, otherwise false
2976         return false;
2977     }
2978     for (uint32_t index = 0; index < inputStyle.detents.size(); index++) {
2979         if (inputStyle.detents[index] == inputStyle.detentSelection.value()) {
2980             detentsFinalIndex_ = index;
2981             TAG_LOGI(AceLogTag::ACE_SHEET, "find detent selection is %u", index);
2982             return true;
2983         }
2984     }
2985     return false;
2986 }
2987 
2988 void SheetPresentationPattern::OverlayDismissSheet()
2989 {
2990     auto overlayManager = GetOverlayManager();
2991     CHECK_NULL_VOID(overlayManager);
2992     overlayManager->DismissSheet();
2993 }
2994 
2995 void SheetPresentationPattern::OverlaySheetSpringBack()
2996 {
2997     auto overlayManager = GetOverlayManager();
2998     CHECK_NULL_VOID(overlayManager);
2999     overlayManager->SheetSpringBack();
3000 }
3001 
3002 PipelineContext* SheetPresentationPattern::GetSheetMainPipeline() const
3003 {
3004     auto host = GetHost();
3005     CHECK_NULL_RETURN(host, nullptr);
3006     auto pipelineContext = host->GetContext();
3007     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3008     CHECK_NULL_RETURN(layoutProperty, nullptr);
3009     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3010 
3011     if (sheetStyle.instanceId.has_value()) {
3012         // need to get mainWindow's pipeline, and get mainWindow's cutoutSafeArea
3013         auto container = Container::GetContainer(sheetStyle.instanceId.value());
3014         CHECK_NULL_RETURN(container, nullptr);
3015         auto parentId = container->GetParentId();
3016         TAG_LOGI(AceLogTag::ACE_SHEET, "mainWindow id : %{public}d", parentId);
3017         auto parentContainer = Container::GetContainer(parentId);
3018         CHECK_NULL_RETURN(parentContainer, nullptr);
3019         auto parentPipelineBase = parentContainer->GetPipelineContext();
3020         CHECK_NULL_RETURN(parentPipelineBase, nullptr);
3021         auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
3022         pipelineContext = RawPtr(parentPipelineContext);
3023     }
3024     return pipelineContext;
3025 }
3026 
3027 float SheetPresentationPattern::GetBottomSafeArea()
3028 {
3029     auto pipelineContext = GetSheetMainPipeline();
3030     CHECK_NULL_RETURN(pipelineContext, .0f);
3031     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
3032     auto manager = pipelineContext->GetSafeAreaManager();
3033     CHECK_NULL_RETURN(manager, .0f);
3034     auto cutoutSafeArea = manager->GetCutoutSafeAreaWithoutProcess();
3035     if (cutoutSafeArea.top_.IsValid()) {
3036         auto topAreaInWindow = GetTopAreaInWindow();
3037         TAG_LOGD(AceLogTag::ACE_SHEET, "rosen window sheetTopSafeArea of sheet is : %{public}f", topAreaInWindow);
3038         return topAreaInWindow;
3039     } else {
3040         return safeAreaInsets.top_.Length();
3041     }
3042 }
3043 
3044 // Height of status bar
3045 float SheetPresentationPattern::GetTopAreaInWindow() const
3046 {
3047     auto host = GetHost();
3048     CHECK_NULL_RETURN(host, 0.0f);
3049     auto pipelineContext = host->GetContext();
3050     CHECK_NULL_RETURN(pipelineContext, 0.0f);
3051     auto window = pipelineContext->GetWindow();
3052     CHECK_NULL_RETURN(window, 0.0f);
3053     return window->GetStatusBarHeight();
3054 }
3055 
3056 void SheetPresentationPattern::MarkSheetPageNeedRender()
3057 {
3058     auto parentHost = GetHost()->GetParent();
3059     CHECK_NULL_VOID(parentHost);
3060     auto frameNode = AceType::DynamicCast<FrameNode>(parentHost);
3061     CHECK_NULL_VOID(frameNode);
3062     frameNode->MarkNeedRenderOnly();
3063 }
3064 
3065 void SheetPresentationPattern::SetSheetOuterBorderWidth(
3066     const RefPtr<SheetTheme>& sheetTheme, const NG::SheetStyle& sheetStyle)
3067 {
3068     auto host = GetHost();
3069     CHECK_NULL_VOID(host);
3070     auto renderContext = host->GetRenderContext();
3071     CHECK_NULL_VOID(renderContext);
3072     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
3073     CHECK_NULL_VOID(layoutProperty);
3074     auto sheetType = GetSheetType();
3075     if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
3076         BorderWidthProperty borderWidth;
3077         BorderWidthProperty outBorderWidth;
3078         BorderColorProperty borderColor;
3079         BorderColorProperty outBorderColor;
3080         borderWidth.SetBorderWidth(0.0_vp);
3081         outBorderWidth.SetBorderWidth(0.0_vp);
3082         if (sheetType != SheetType::SHEET_POPUP) {
3083             borderColor.SetColor(sheetTheme->GetSheetInnerBorderColor());
3084             outBorderColor.SetColor(sheetTheme->GetSheetOuterBorderColor());
3085             renderContext->UpdateOuterBorderColor(outBorderColor);
3086             renderContext->UpdateBorderColor(borderColor);
3087             if (sheetType == SheetType::SHEET_CENTER || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
3088                 borderWidth.SetBorderWidth(sheetTheme->GetSheetInnerBorderWidth());
3089                 outBorderWidth.SetBorderWidth(sheetTheme->GetSheetOuterBorderWidth());
3090             } else {
3091                 borderWidth.leftDimen = sheetTheme->GetSheetInnerBorderWidth();
3092                 borderWidth.topDimen = sheetTheme->GetSheetInnerBorderWidth();
3093                 borderWidth.rightDimen = sheetTheme->GetSheetInnerBorderWidth();
3094                 outBorderWidth.leftDimen = sheetTheme->GetSheetOuterBorderWidth();
3095                 outBorderWidth.topDimen = sheetTheme->GetSheetOuterBorderWidth();
3096                 outBorderWidth.rightDimen = sheetTheme->GetSheetOuterBorderWidth();
3097             }
3098         }
3099         layoutProperty->UpdateBorderWidth(borderWidth);
3100         renderContext->UpdateBorderWidth(borderWidth);
3101         layoutProperty->UpdateOuterBorderWidth(outBorderWidth);
3102         renderContext->UpdateOuterBorderWidth(outBorderWidth);
3103     }
3104 }
3105 
3106 void SheetPresentationPattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
3107 {
3108     json->Put("TargetId", static_cast<int32_t>(targetId_));
3109     json->Put("TargetTag", targetTag_.c_str());
3110     std::unique_ptr<JsonValue> children = JsonUtil::Create(true);
3111     children->Put("SheetType", static_cast<int32_t>(GetSheetType()));
3112     children->Put("SheetPage Node Height", centerHeight_);
3113     children->Put("Sheet Height [start from the bottom, KeyboardHeight = 0]", height_);
3114     children->Put("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]", sheetMaxHeight_);
3115     children->Put("Page Height", pageHeight_);
3116     children->Put("StatusBar Height [current sheetType needed]", sheetTopSafeArea_);
3117     children->Put("PopupSheet OffsetX", sheetOffsetX_);
3118     children->Put("PopupSheet OffsetX", sheetOffsetY_);
3119     children->Put("SheetMaxWidth", sheetMaxWidth_);
3120     children->Put("FitContent Height", sheetFitContentHeight_);
3121     children->Put("SheetThemeType", sheetThemeType_.c_str());
3122     children->Put("currentOffset", currentOffset_);
3123     json->Put("SheetPage Pattern", children);
3124 
3125     json->Put("Height ScrollTo [KeyboardHeight > 0, and is scrolling]", -scrollHeight_);
3126     json->Put("KeyboardHeight", static_cast<int32_t>(keyboardHeight_));
3127     json->Put("is scrolling", isScrolling_);
3128     json->Put("SheetHeightUp[sheet offset to move up when avoiding keyboard]", sheetHeightUp_);
3129 
3130     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3131     CHECK_NULL_VOID(layoutProperty);
3132     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3133     json->Put("height", sheetStyle.sheetHeight.height.has_value() ?
3134         sheetStyle.sheetHeight.height->ToString().c_str() : "None");
3135     json->Put("sheetMode", sheetStyle.sheetHeight.sheetMode.has_value()
3136                                ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value())).c_str()
3137                                : "None");
3138     json->Put("detents Size", static_cast<int32_t>(sheetStyle.detents.size()));
3139     json->Put("IsShouldDismiss", shouldDismiss_ ? "true" : "false");
3140 }
3141 
3142 void SheetPresentationPattern::AvoidKeyboardBySheetMode(bool forceAvoid)
3143 {
3144     auto host = GetHost();
3145     CHECK_NULL_VOID(host);
3146     bool isCurrentFocus = host->GetFocusHub()->IsCurrentFocus();
3147     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::NONE || !isCurrentFocus) {
3148         TAG_LOGD(AceLogTag::ACE_SHEET,
3149             "Sheet will not avoid keyboard.keyboardAvoidMode:%{public}d, isCurrentFocus:%{public}d.",
3150             keyboardAvoidMode_, isCurrentFocus);
3151         return;
3152     }
3153     auto pipelineContext = host->GetContext();
3154     CHECK_NULL_VOID(pipelineContext);
3155     auto manager = pipelineContext->GetSafeAreaManager();
3156     if (keyboardHeight_ == manager->GetKeyboardInset().Length() && !forceAvoid) {
3157         return;
3158     }
3159     keyboardHeight_ = manager->GetKeyboardInset().Length();
3160 
3161     if (isDismissProcess_) {
3162         TAG_LOGD(AceLogTag::ACE_SHEET,
3163             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
3164         return;
3165     }
3166 
3167     // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY
3168     if (AvoidKeyboardBeforeTranslate()) {
3169         return;
3170     }
3171 
3172     // 2.handle upward logic
3173     CHECK_NULL_VOID(host->GetFocusHub());
3174     // When bindSheet lift height exceed the max height, hightUp = the remaining height that needs to scroll,
3175     // otherwise, hightUp = the height to be lifted up
3176     auto heightUp = isCurrentFocus ? GetSheetHeightChange() : 0.0f;
3177     sheetHeightUp_ = heightUp;
3178     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet needs to deal with %{public}f height.", heightUp);
3179     auto offset = pageHeight_ - height_ - heightUp;
3180     auto renderContext = host->GetRenderContext();
3181 
3182     // when bindSheet height exceed the max height, lift it up to the maxHeight,
3183     // otherwise, lift it up to show input area
3184     if (isScrolling_) {
3185         if (NearZero(heightUp)) {
3186             // scroll needs to reset first when keyboard is down.
3187             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3188         } else {
3189             sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
3190             // sheet is raised to the top first
3191             renderContext->UpdateTransformTranslate(
3192                 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
3193         }
3194     } else {
3195         // offset: translate endpoint, calculated from top
3196         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3197     }
3198 
3199     // 3.deal with left height, scroll or resize
3200     if (isScrolling_) {
3201         AvoidKeyboardAfterTranslate(heightUp);
3202     }
3203 
3204     if (IsSheetBottomStyle()) {
3205         OnHeightDidChange(height_ + sheetHeightUp_);
3206     }
3207 }
3208 
3209 bool SheetPresentationPattern::AvoidKeyboardBeforeTranslate()
3210 {
3211     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY) {
3212         // resize bindSheet need to keep safe distance from keyboard
3213         auto distanceFromBottom = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
3214         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : keyboardHeight_ - distanceFromBottom);
3215         return true;
3216     }
3217     return false;
3218 }
3219 
3220 void SheetPresentationPattern::AvoidKeyboardAfterTranslate(float height)
3221 {
3222     switch (keyboardAvoidMode_) {
3223     case SheetKeyboardAvoidMode::NONE:
3224     case SheetKeyboardAvoidMode::RESIZE_ONLY:
3225         break;
3226     case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE:
3227         // resize bindSheet need to keep safe distance from keyboard
3228         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : height);
3229         break;
3230     case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL:
3231         ScrollTo(height);
3232         break;
3233     default:
3234         TAG_LOGW(AceLogTag::ACE_SHEET, "Invalid keyboard avoid mode %{public}d", keyboardAvoidMode_);
3235         break;
3236     }
3237 }
3238 
3239 void SheetPresentationPattern::DecreaseScrollHeightInSheet(float decreaseHeight)
3240 {
3241     auto scroll = GetSheetScrollNode();
3242     CHECK_NULL_VOID(scroll);
3243     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3244     CHECK_NULL_VOID(layoutProp);
3245 
3246     // height > 0, Scroll will reduce height, and need to set isScrolling true
3247     isScrolling_ = (decreaseHeight > 0);
3248 
3249     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, Scroll Height reduces by height %{public}f.", decreaseHeight);
3250     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight() - decreaseHeight)));
3251     resizeDecreasedHeight_ = decreaseHeight;
3252     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3253 }
3254 
3255 bool SheetPresentationPattern::IsResizeWhenAvoidKeyboard()
3256 {
3257     return keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE ||
3258         keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY;
3259 }
3260 
3261 void SheetPresentationPattern::ResetClipShape()
3262 {
3263     // need reset clip path,when system clip path change to user defined
3264     auto host = GetHost();
3265     CHECK_NULL_VOID(host);
3266     auto renderContext = host->GetRenderContext();
3267     CHECK_NULL_VOID(renderContext);
3268     renderContext->UpdateClipShape(nullptr);
3269     renderContext->ResetClipShape();
3270 }
3271 
3272 void SheetPresentationPattern::GetCurrentScrollHeight()
3273 {
3274     if (!isScrolling_) {
3275         return;
3276     }
3277     auto host = GetHost();
3278     CHECK_NULL_VOID(host);
3279     auto scrollNode = GetSheetScrollNode();
3280     CHECK_NULL_VOID(scrollNode);
3281     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
3282     CHECK_NULL_VOID(scrollPattern);
3283     auto curOffset = scrollPattern->GetTotalOffset();
3284     if (NearEqual(scrollHeight_, curOffset)) {
3285         return;
3286     }
3287     TAG_LOGD(AceLogTag::ACE_SHEET, "scroll height changed because of user scrolling, %{public}f", curOffset);
3288     scrollHeight_ = curOffset;
3289 }
3290 
3291 void SheetPresentationPattern::UpdateSheetWhenSheetTypeChanged()
3292 {
3293     auto sheetType = GetSheetType();
3294     if (sheetType_ != sheetType) {
3295         // It can only be MarkOuterBorder When the SheetType switches and the sheetType_ was SHEET_POPUP
3296         if (sheetType_ == SheetType::SHEET_POPUP) {
3297             MarkSheetPageNeedRender();
3298         }
3299         sheetType_ = sheetType;
3300         SetSheetBorderWidth();
3301     }
3302 }
3303 
3304 bool SheetPresentationPattern::IsCurSheetNeedHalfFoldHover()
3305 {
3306     auto host = GetHost();
3307     CHECK_NULL_RETURN(host, false);
3308     auto pipeline = host->GetContext();
3309     CHECK_NULL_RETURN(pipeline, false);
3310     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3311     CHECK_NULL_RETURN(sheetTheme, false);
3312     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3313     CHECK_NULL_RETURN(layoutProperty, false);
3314     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3315     auto enableHoverMode = sheetStyle.enableHoverMode.value_or(sheetTheme->IsOuterBorderEnable() ? true : false);
3316     bool isHoverMode = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
3317     return isHoverMode && GetSheetType() == SheetType::SHEET_CENTER;
3318 }
3319 
3320 bool SheetPresentationPattern::IsShowInSubWindowTwoInOne()
3321 {
3322     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3323     CHECK_NULL_RETURN(layoutProperty, false);
3324     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3325     if (!sheetStyle.showInSubWindow.value_or(false)) {
3326         return false;
3327     }
3328     auto host = GetHost();
3329     CHECK_NULL_RETURN(host, false);
3330     auto pipeline = host->GetContext();
3331     CHECK_NULL_RETURN(pipeline, false);
3332     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3333     CHECK_NULL_RETURN(sheetTheme, false);
3334     return sheetTheme->IsOuterBorderEnable();
3335 }
3336 
3337 bool SheetPresentationPattern::IsShowInSubWindow()
3338 {
3339     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3340     CHECK_NULL_RETURN(layoutProperty, false);
3341     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3342     return sheetStyle.showInSubWindow.value_or(false);
3343 }
3344 
3345 void SheetPresentationPattern::InitFoldCreaseRegion()
3346 {
3347     auto host = GetHost();
3348     CHECK_NULL_VOID(host);
3349     auto pipeline = host->GetContext();
3350     CHECK_NULL_VOID(pipeline);
3351     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3352     CHECK_NULL_VOID(sheetTheme);
3353     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3354     CHECK_NULL_VOID(layoutProperty);
3355     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3356     auto enableHoverMode = sheetStyle.enableHoverMode.value_or(sheetTheme->IsOuterBorderEnable() ? true : false);
3357     if (!enableHoverMode || !currentFoldCreaseRegion_.empty()) {
3358         return;
3359     }
3360     auto container = Container::Current();
3361     CHECK_NULL_VOID(container);
3362     auto displayInfo = container->GetDisplayInfo();
3363     CHECK_NULL_VOID(displayInfo);
3364     currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
3365 }
3366 
3367 Rect SheetPresentationPattern::GetFoldScreenRect() const
3368 {
3369     if (currentFoldCreaseRegion_.empty()) {
3370         TAG_LOGW(AceLogTag::ACE_SHEET, "FoldCreaseRegion is invalid.");
3371         return Rect();
3372     }
3373     return currentFoldCreaseRegion_.front();
3374 }
3375 
3376 Shadow SheetPresentationPattern::GetShadowFromTheme(ShadowStyle shadowStyle)
3377 {
3378     if (shadowStyle == ShadowStyle::None) {
3379         return Shadow();
3380     }
3381     auto host = GetHost();
3382     CHECK_NULL_RETURN(host, Shadow());
3383     auto pipelineContext = host->GetContext();
3384     CHECK_NULL_RETURN(pipelineContext, Shadow());
3385     auto colorMode = pipelineContext->GetColorMode();
3386     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
3387     CHECK_NULL_RETURN(shadowTheme, Shadow());
3388     auto shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
3389     return shadow;
3390 }
3391 
3392 void SheetPresentationPattern::FireHoverModeChangeCallback()
3393 {
3394     auto host = GetHost();
3395     CHECK_NULL_VOID(host);
3396     auto pipeline = host->GetContext();
3397     CHECK_NULL_VOID(pipeline);
3398     if (!IsCurSheetNeedHalfFoldHover()) {
3399         TAG_LOGD(AceLogTag::ACE_SHEET, "halfFoldHoverStatus: %{public}d, Sheet is not half folded.",
3400             pipeline->IsHalfFoldHoverStatus());
3401         return;
3402     }
3403     OnHeightDidChange(centerHeight_);
3404 }
3405 
3406 void SheetPresentationPattern::GetArrowOffsetByPlacement(
3407     const RefPtr<SheetPresentationLayoutAlgorithm>& layoutAlgorithm)
3408 {
3409     CHECK_NULL_VOID(layoutAlgorithm);
3410     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3411         return;
3412     }
3413     finalPlacement_ = sheetPopupInfo_.finalPlacement;
3414     showArrow_ = sheetPopupInfo_.showArrow;
3415     arrowPosition_ = sheetPopupInfo_.arrowPosition;
3416     if (!showArrow_ || finalPlacement_ == Placement::NONE) {
3417         arrowOffset_ = OffsetF(0.f, 0.f);
3418         return;
3419     }
3420 
3421     switch (finalPlacement_) {
3422         case Placement::BOTTOM_LEFT:
3423             [[fallthrough]];
3424         case Placement::BOTTOM_RIGHT:
3425             [[fallthrough]];
3426         case Placement::BOTTOM:
3427             [[fallthrough]];
3428         case Placement::TOP_LEFT:
3429             [[fallthrough]];
3430         case Placement::TOP_RIGHT:
3431             [[fallthrough]];
3432         case Placement::TOP: {
3433             arrowOffset_ = OffsetF(sheetPopupInfo_.arrowOffsetX, 0.f);
3434             break;
3435         }
3436         case Placement::RIGHT_TOP:
3437             [[fallthrough]];
3438         case Placement::RIGHT_BOTTOM:
3439             [[fallthrough]];
3440         case Placement::RIGHT:
3441             [[fallthrough]];
3442         case Placement::LEFT_TOP:
3443             [[fallthrough]];
3444         case Placement::LEFT_BOTTOM:
3445             [[fallthrough]];
3446         case Placement::LEFT: {
3447             arrowOffset_ = OffsetF(0.f, sheetPopupInfo_.arrowOffsetY);
3448             break;
3449         }
3450         default:
3451             break;
3452     }
3453 }
3454 
3455 std::string SheetPresentationPattern::GetPopupStyleSheetClipPathNew(
3456     const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
3457 {
3458     std::string drawPath;
3459     switch (finalPlacement_) {
3460         case Placement::BOTTOM_LEFT:
3461             [[fallthrough]];
3462         case Placement::BOTTOM_RIGHT:
3463             [[fallthrough]];
3464         case Placement::BOTTOM: {
3465             drawPath = DrawClipPathBottom(sheetSize, sheetRadius);
3466             break;
3467         }
3468         case Placement::TOP_LEFT:
3469             [[fallthrough]];
3470         case Placement::TOP_RIGHT:
3471             [[fallthrough]];
3472         case Placement::TOP: {
3473             drawPath = DrawClipPathTop(sheetSize, sheetRadius);
3474             break;
3475         }
3476         case Placement::RIGHT_TOP:
3477             [[fallthrough]];
3478         case Placement::RIGHT_BOTTOM:
3479             [[fallthrough]];
3480         case Placement::RIGHT: {
3481             drawPath = DrawClipPathRight(sheetSize, sheetRadius);
3482             break;
3483         }
3484         case Placement::LEFT_TOP:
3485             [[fallthrough]];
3486         case Placement::LEFT_BOTTOM:
3487             [[fallthrough]];
3488         case Placement::LEFT: {
3489             drawPath = DrawClipPathLeft(sheetSize, sheetRadius);
3490             break;
3491         }
3492         default:
3493             break;
3494     }
3495     return drawPath;
3496 }
3497 
3498 std::string SheetPresentationPattern::DrawClipPathBottom(const SizeF& sheetSize,
3499     const BorderRadiusProperty& sheetRadius)
3500 {
3501     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3502     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3503     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3504     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3505     // clip path start from TopLeft, and draw Right-angled arrow first if needed
3506     std::string path;
3507     if (arrowPosition_ == SheetArrowPosition::BOTTOM_LEFT) {
3508         path += MoveTo(0.f, SHEET_ARROW_HEIGHT.ConvertToPx());  // P5
3509         path += LineTo(0.f, (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3510         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3511             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3512             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3513         path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3514     } else {
3515         path += MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
3516         path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft,
3517             SHEET_ARROW_HEIGHT.ConvertToPx());
3518     }
3519     if (arrowPosition_ == SheetArrowPosition::NONE) {
3520         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3521             SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3522         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3523             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx());   // P2
3524         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3525             arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3526             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx());   // P4
3527         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3528             SHEET_ARROW_HEIGHT.ConvertToPx());  // P5
3529     }
3530     if (arrowPosition_ == SheetArrowPosition::BOTTOM_RIGHT) {
3531         path += LineTo(sheetSize.Width() -
3532             SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3533         path += LineTo(sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3534             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3535         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3536             sheetSize.Width(), (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());  // P4
3537         path += LineTo(sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx());    // P5
3538     } else {
3539         path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
3540         path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(),
3541             SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
3542     }
3543     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3544     path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3545         sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3546     path += LineTo(radiusBottomLeft, sheetSize.Height());
3547     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f,
3548         sheetSize.Height() - radiusBottomLeft);
3549     return path + "Z";
3550 }
3551 
3552 std::string SheetPresentationPattern::DrawClipPathTop(const SizeF& sheetSize,
3553     const BorderRadiusProperty& sheetRadius)
3554 {
3555     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3556     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3557     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3558     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3559     // clip path start from TopLeft, and draw sheet radius first
3560     std::string path;
3561     path += MoveTo(0.f, radiusTopLeft);
3562     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3563     path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3564     path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3565         sheetSize.Width(), radiusTopRight);
3566     if (arrowPosition_ == SheetArrowPosition::TOP_RIGHT) {
3567         path += LineTo(sheetSize.Width(),
3568             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());    // P4
3569         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3570             sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3571             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx());    // P2
3572         path += LineTo(sheetSize.Width() - SHEET_ARROW_WIDTH.ConvertToPx(),
3573             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3574     } else {
3575         path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx());
3576         path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3577             sheetSize.Width() - radiusBottomRight, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3578     }
3579     if (arrowPosition_ == SheetArrowPosition::NONE) {
3580         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3581             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3582         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3583             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx());  // P2
3584         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3585             arrowOffset_.GetX() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3586             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx());  // P4
3587         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3588             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3589     }
3590     if (arrowPosition_ == SheetArrowPosition::TOP_LEFT) {
3591         path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(),
3592             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3593         path += LineTo((SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3594             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx());    // P2
3595         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, 0.f,
3596             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());    // P4
3597         path += LineTo(0.f, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3598     } else {
3599         path += LineTo(radiusBottomLeft, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3600         path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3601             0.f, sheetSize.Height() - radiusBottomLeft - SHEET_ARROW_HEIGHT.ConvertToPx());
3602     }
3603     return path + "Z";
3604 }
3605 
3606 std::string SheetPresentationPattern::DrawClipPathLeft(const SizeF& sheetSize,
3607     const BorderRadiusProperty& sheetRadius)
3608 {
3609     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3610     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3611     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3612     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3613     // clip path start from TopLeft, and draw sheet radius first
3614     std::string path;
3615     path += MoveTo(0.f, radiusTopLeft);
3616     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3617     if (arrowPosition_ == SheetArrowPosition::LEFT_TOP) {
3618         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f); // P4
3619         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3620             sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3621             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx());  // P2
3622         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3623             SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3624     } else {
3625         path += LineTo(sheetSize.Width() - radiusTopRight - SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3626         path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3627             sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopRight);
3628     }
3629     if (arrowPosition_ == SheetArrowPosition::NONE) {
3630         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3631             arrowOffset_.GetY() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx());    // P1
3632         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3633             arrowOffset_.GetY() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx());    // P2
3634         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3635             sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3636             arrowOffset_.GetY() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx());    // P4
3637         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3638             arrowOffset_.GetY() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx());    // P5
3639     }
3640     if (arrowPosition_ == SheetArrowPosition::LEFT_BOTTOM) {
3641         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3642             sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3643         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3644             sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3645         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, sheetSize.Width() -
3646             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height()); // P4
3647         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());   // P5
3648     } else {
3649         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3650             sheetSize.Height() - radiusBottomRight);
3651         path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3652             sheetSize.Width() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3653     }
3654     path += LineTo(radiusBottomLeft, sheetSize.Height());
3655     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3656         0.f, sheetSize.Height() - radiusBottomLeft);
3657     return path + "Z";
3658 }
3659 
3660 std::string SheetPresentationPattern::DrawClipPathRight(const SizeF& sheetSize,
3661     const BorderRadiusProperty& sheetRadius)
3662 {
3663     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3664     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3665     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3666     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3667     // clip path start from TopLeft, and if left side need draw left top Right-angled arrow, draw it first
3668     std::string path;
3669     if (arrowPosition_ == SheetArrowPosition::RIGHT_TOP) {
3670         path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3671         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3672             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx());  // P2
3673         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3674             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f);    // P4
3675         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);  // P5
3676     } else {
3677         path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopLeft);
3678         path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0,
3679             radiusTopLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3680     }
3681     path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3682     path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3683         sheetSize.Width(), radiusTopRight);
3684     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3685     path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3686         sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3687     if (arrowPosition_ == SheetArrowPosition::RIGHT_BOTTOM) {
3688         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());   // P5
3689         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height());  // P4
3690         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3691             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3692             sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3693         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3694             sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3695     } else {
3696         path += LineTo(radiusBottomLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3697         path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3698             SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height() - radiusBottomLeft);
3699     }
3700     if (arrowPosition_ == SheetArrowPosition::NONE) {
3701         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3702             arrowOffset_.GetY() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx());    // P1
3703         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3704             arrowOffset_.GetY() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx());    // P2
3705         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3706             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3707             arrowOffset_.GetY() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx());    // P4
3708         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3709             arrowOffset_.GetY() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx());    // P5
3710     }
3711     return path + "Z";
3712 }
3713 
3714 void SheetPresentationPattern::RecoverHalfFoldOrAvoidStatus()
3715 {
3716     TAG_LOGD(AceLogTag::ACE_SHEET, "recover half fold status because of window rotate");
3717     auto host = GetHost();
3718     CHECK_NULL_VOID(host);
3719     auto pipeline = host->GetContext();
3720     CHECK_NULL_VOID(pipeline);
3721     if (IsCurSheetNeedHalfFoldHover()) {
3722         RecoverAvoidKeyboardStatus();
3723     } else {
3724         AvoidSafeArea(true);
3725     }
3726 }
3727 
3728 void SheetPresentationPattern::RecoverAvoidKeyboardStatus()
3729 {
3730     RecoverScrollOrResizeAvoidStatus();
3731     sheetHeightUp_ = 0.f;
3732     OnHeightDidChange(centerHeight_);
3733 }
3734 
3735 void SheetPresentationPattern::RecoverScrollOrResizeAvoidStatus()
3736 {
3737     auto scroll = GetSheetScrollNode();
3738     CHECK_NULL_VOID(scroll);
3739     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3740     CHECK_NULL_VOID(layoutProp);
3741     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight())));
3742     resizeDecreasedHeight_ = 0.f;
3743     scrollHeight_ = 0.f;
3744     ScrollTo(0.f);
3745     isScrolling_ = false;
3746 }
3747 
3748 void SheetPresentationPattern::OnWillDisappear()
3749 {
3750     if (onWillDisappear_) {
3751         TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onWillDisappear state.");
3752         onWillDisappear_();
3753     }
3754     auto hostNode = GetHost();
3755     CHECK_NULL_VOID(hostNode);
3756     auto pipelineContext = hostNode->GetContextRefPtr();
3757     CHECK_NULL_VOID(pipelineContext);
3758     auto navigationManager = pipelineContext->GetNavigationManager();
3759     CHECK_NULL_VOID(navigationManager);
3760     navigationManager->FireOverlayLifecycle(hostNode, static_cast<int32_t>(NavDestinationLifecycle::ON_INACTIVE),
3761         static_cast<int32_t>(NavDestinationActiveReason::SHEET));
3762 }
3763 
3764 void SheetPresentationPattern::OnFontScaleConfigurationUpdate()
3765 {
3766     auto hostNode = GetHost();
3767     CHECK_NULL_VOID(hostNode);
3768     auto pipeline = hostNode->GetContext();
3769     CHECK_NULL_VOID(pipeline);
3770     pipeline->AddAfterReloadAnimationTask([weak = WeakClaim(this)]() {
3771         auto pattern = weak.Upgrade();
3772         CHECK_NULL_VOID(pattern);
3773         pattern->AvoidSafeArea(true);
3774     });
3775 }
3776 
3777 void SheetPresentationPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
3778 {
3779     auto host = GetHost();
3780     CHECK_NULL_VOID(host);
3781     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3782 }
3783 
3784 void SheetPresentationPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3785 {
3786     CHECK_NULL_VOID(hostNode);
3787     auto pipeline = hostNode->GetContext();
3788     CHECK_NULL_VOID(pipeline);
3789     auto mgr = pipeline->GetAvoidInfoManager();
3790     CHECK_NULL_VOID(mgr);
3791     mgr->AddAvoidInfoListener(WeakClaim(this));
3792 }
3793 
3794 void SheetPresentationPattern::UnRegisterAvoidInfoChangeListener(FrameNode* hostNode)
3795 {
3796     CHECK_NULL_VOID(hostNode);
3797     auto pipeline = hostNode->GetContext();
3798     CHECK_NULL_VOID(pipeline);
3799     auto mgr = pipeline->GetAvoidInfoManager();
3800     CHECK_NULL_VOID(mgr);
3801     mgr->RemoveAvoidInfoListener(WeakClaim(this));
3802 }
3803 } // namespace OHOS::Ace::NG
3804