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