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