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