• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/sheet/side/sheet_side_object.h"
17 
18 #include "ui/base/ace_type.h"
19 #include "ui/base/utils/utils.h"
20 
21 #include "base/geometry/dimension.h"
22 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "core/components_ng/pattern/overlay/overlay_manager.h"
25 #include "core/components_ng/pattern/overlay/sheet_manager.h"
26 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
27 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
28 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
29 #include "core/components_ng/pattern/text_field/text_field_manager.h"
30 
31 namespace OHOS::Ace::NG {
32 
PostProcessBorderWidth(const NG::BorderWidthProperty & borderWidth)33 NG::BorderWidthProperty SheetSideObject::PostProcessBorderWidth(const NG::BorderWidthProperty& borderWidth)
34 {
35     NG::BorderWidthProperty result = borderWidth;
36     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
37         result.leftDimen = 0.0_vp;
38     } else {
39         result.rightDimen = 0.0_vp;
40     }
41     return result;
42 }
43 
DirtyLayoutProcess(const RefPtr<LayoutAlgorithmWrapper> & layoutAlgorithmWrapper)44 void SheetSideObject::DirtyLayoutProcess(const RefPtr<LayoutAlgorithmWrapper>& layoutAlgorithmWrapper)
45 {
46     auto pattern = GetPattern();
47     CHECK_NULL_VOID(pattern);
48     auto sideSheetLayoutAlgorithm =
49         AceType::DynamicCast<SheetPresentationSideLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
50     CHECK_NULL_VOID(sideSheetLayoutAlgorithm);
51     if (sideSheetLayoutAlgorithm->GetSideSheetMaxWidth() > 0) {
52         sheetMaxWidth_ = sideSheetLayoutAlgorithm->GetSideSheetMaxWidth();
53         sheetWidth_ = sideSheetLayoutAlgorithm->GetSideSheetWidth();
54         pattern->SetSheetMaxHeight(sideSheetLayoutAlgorithm->GetSideSheetMaxHeight());
55     }
56     if (GreatNotEqual(sideSheetLayoutAlgorithm->GetSheetHeight(), 0.0f)) {
57         SetSheetHeight(sideSheetLayoutAlgorithm->GetSheetHeight());
58     }
59     UpdateDragBarStatus();
60     UpdateSidePosition();
61 }
62 
UpdateDragBarStatus()63 void SheetSideObject::UpdateDragBarStatus()
64 {
65     auto pattern = GetPattern();
66     CHECK_NULL_VOID(pattern);
67     auto host = pattern->GetHost();
68     CHECK_NULL_VOID(host);
69 
70     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
71     CHECK_NULL_VOID(sheetPattern);
72     auto sheetDragBar = sheetPattern->GetDragBarNode();
73     CHECK_NULL_VOID(sheetDragBar);
74     auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
75     CHECK_NULL_VOID(dragBarLayoutProperty);
76 
77     dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
78     sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
79 }
80 
UpdateSidePosition()81 void SheetSideObject::UpdateSidePosition()
82 {
83     auto sheetPattern = GetPattern();
84     CHECK_NULL_VOID(sheetPattern);
85     auto sheetNode = sheetPattern->GetHost();
86     CHECK_NULL_VOID(sheetNode);
87     auto context = sheetNode->GetRenderContext();
88     CHECK_NULL_VOID(context);
89 
90     if (!sheetPattern->IsOnAppearing()
91         && !sheetPattern->IsOnDisappearing() && !sheetPattern->IsDragging()) {
92         sheetPattern->FireOnWidthDidChange();
93         FireHeightDidChange();
94         bool isRTL = AceApplicationInfo::GetInstance().IsRightToLeft();
95         if (!isRTL) {
96             context->UpdateTransformTranslate({ sheetMaxWidth_ - sheetWidth_, 0.0f, 0.0f });
97         } else {
98             context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
99         }
100     }
101 }
102 
GetSheetTransitionCurve(float dragVelocity) const103 RefPtr<InterpolatingSpring> SheetSideObject::GetSheetTransitionCurve(float dragVelocity) const
104 {
105     return AceType::MakeRefPtr<InterpolatingSpring>(
106         0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
107 }
108 
GetSheetTransitionFinishEvent(bool isTransitionIn)109 std::function<void()> SheetSideObject::GetSheetTransitionFinishEvent(bool isTransitionIn)
110 {
111     const std::function<void()> event = [weak = pattern_, isTransitionIn]() {
112         auto pattern = weak.Upgrade();
113         CHECK_NULL_VOID(pattern);
114         if (isTransitionIn) {
115             if (!pattern->GetAnimationBreak()) {
116                 pattern->SetAnimationProcess(false);
117                 pattern->GetSheetObject()->SetCurrentOffset(0.0f);
118             } else {
119                 pattern->SetAnimationBreak(false);
120             }
121             pattern->AvoidAiBar();
122             pattern->SetSpringBack(false);
123         } else {
124             pattern->SetAnimationProcess(false);
125             const auto& overlayManager = pattern->GetOverlayManager();
126             CHECK_NULL_VOID(overlayManager);
127             auto host = pattern->GetHost();
128             CHECK_NULL_VOID(host);
129             overlayManager->FireAutoSave(host);
130             pattern->OnDisappear();
131             overlayManager->RemoveSheet(host);
132             pattern->FireCallback("false");
133         }
134     };
135     return event;
136 }
137 
GetSheetAnimationEvent(bool isTransitionIn,float offset)138 std::function<void()> SheetSideObject::GetSheetAnimationEvent(bool isTransitionIn, float offset)
139 {
140     auto sheetPattern = GetPattern();
141     CHECK_NULL_RETURN(sheetPattern, nullptr);
142     auto sheetNode = sheetPattern->GetHost();
143     CHECK_NULL_RETURN(sheetNode, nullptr);
144     auto context = sheetNode->GetRenderContext();
145     CHECK_NULL_RETURN(context, nullptr);
146 
147     std::function<void()> event;
148     if (isTransitionIn) {
149         event = [weak = WeakClaim(this)]() {
150             auto sheetObject = weak.Upgrade();
151             CHECK_NULL_VOID(sheetObject);
152             sheetObject->TransformTranslateEnter();
153         };
154     } else {
155         event = [context, weak = pattern_, objWeak = WeakClaim(this)]() {
156             auto pattern = weak.Upgrade();
157             CHECK_NULL_VOID(pattern);
158             auto sheetObject = objWeak.Upgrade();
159             CHECK_NULL_VOID(sheetObject);
160             sheetObject->TransformTranslateExit();
161             pattern->DismissSheetShadow(context);
162         };
163     }
164     return event;
165 }
166 
167 
ClipSheetNode()168 void SheetSideObject::ClipSheetNode()
169 {
170     auto pattern = GetPattern();
171     CHECK_NULL_VOID(pattern);
172     auto host = pattern->GetHost();
173     CHECK_NULL_VOID(host);
174     auto geometryNode = host->GetGeometryNode();
175     CHECK_NULL_VOID(geometryNode);
176     auto pipeline = PipelineContext::GetCurrentContext();
177     CHECK_NULL_VOID(pipeline);
178     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
179     CHECK_NULL_VOID(sheetTheme);
180     auto renderContext = host->GetRenderContext();
181     CHECK_NULL_VOID(renderContext);
182     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
183     CHECK_NULL_VOID(layoutProperty);
184     auto sheetStyle = layoutProperty->GetSheetStyleValue();
185     pattern->ResetClipShape();
186     BorderRadiusProperty borderRadius(sheetTheme->GetSheetSideRadius());
187     pattern->CalculateSheetRadius(borderRadius);
188     // set 1px for avoiding doudble radius black lines.
189     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
190         borderRadius.radiusTopLeft = 1.0_px;
191         borderRadius.radiusBottomLeft = 1.0_px;
192     } else {
193         borderRadius.radiusTopRight = 1.0_px;
194         borderRadius.radiusBottomRight = 1.0_px;
195     }
196     renderContext->UpdateBorderRadius(borderRadius);
197     // innerBorder need to adapt
198 }
199 
InitAnimationForOverlay(bool isTransitionIn,bool isFirstTransition)200 void SheetSideObject::InitAnimationForOverlay(bool isTransitionIn, bool isFirstTransition)
201 {
202     auto sheetPattern = GetPattern();
203     CHECK_NULL_VOID(sheetPattern);
204     auto sheetNode = sheetPattern->GetHost();
205     CHECK_NULL_VOID(sheetNode);
206     auto sheetParent = AceType::DynamicCast<FrameNode>(sheetNode->GetParent());
207     CHECK_NULL_VOID(sheetParent);
208     if (isTransitionIn) {
209         if (isFirstTransition) {
210             TransformTranslateExit();
211             sheetPattern->GetBuilderInitHeight();
212         }
213         sheetPattern->FireOnTypeDidChange();
214         FireHeightDidChange();
215         ACE_SCOPED_TRACE("Side Sheet starts the entrance animation");
216     }
217 }
218 
SetFinishEventForAnimationOption(AnimationOption & option,bool isTransitionIn,bool isFirstTransition)219 void SheetSideObject::SetFinishEventForAnimationOption(
220     AnimationOption& option, bool isTransitionIn, bool isFirstTransition)
221 {
222     auto sheetPattern = GetPattern();
223     CHECK_NULL_VOID(sheetPattern);
224     auto sheetNode = sheetPattern->GetHost();
225     CHECK_NULL_VOID(sheetNode);
226     if (isTransitionIn) {
227         option.SetOnFinishEvent(
228             [sheetWK = WeakClaim(RawPtr(sheetNode)), isFirst = isFirstTransition] {
229                 auto sheetNode = sheetWK.Upgrade();
230                 CHECK_NULL_VOID(sheetNode);
231                 auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
232                 CHECK_NULL_VOID(pattern);
233                 pattern->OnAppear();
234                 pattern->AvoidAiBar();
235                 pattern->FireOnWidthDidChange();
236             });
237     } else {
238         option.SetOnFinishEvent(
239             [sheetWK = WeakClaim(RawPtr(sheetNode))] {
240             auto sheet = sheetWK.Upgrade();
241             CHECK_NULL_VOID(sheet);
242             auto pattern = sheet->GetPattern<SheetPresentationPattern>();
243             CHECK_NULL_VOID(pattern);
244             auto overlayManager = pattern->GetOverlayManager();
245             CHECK_NULL_VOID(overlayManager);
246             pattern->OnDisappear();
247             overlayManager->FireAutoSave(sheet);
248             overlayManager->RemoveSheet(sheet);
249         });
250     }
251 }
252 
GetAnimationOptionForOverlay(bool isTransitionIn,bool isFirstTransition)253 AnimationOption SheetSideObject::GetAnimationOptionForOverlay(bool isTransitionIn, bool isFirstTransition)
254 {
255     AnimationOption option;
256     auto sheetPattern = GetPattern();
257     CHECK_NULL_RETURN(sheetPattern, option);
258     const RefPtr<InterpolatingSpring> curve =
259         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
260     option.SetCurve(curve);
261     option.SetFillMode(FillMode::FORWARDS);
262     option.SetDuration(SHEET_ANIMATION_DURATION);
263     SetFinishEventForAnimationOption(option, isTransitionIn, isFirstTransition);
264     return option;
265 }
266 
TransformTranslateEnter()267 void SheetSideObject::TransformTranslateEnter()
268 {
269     auto sheetPattern = GetPattern();
270     CHECK_NULL_VOID(sheetPattern);
271     auto sheetNode = sheetPattern->GetHost();
272     CHECK_NULL_VOID(sheetNode);
273     auto context = sheetNode->GetRenderContext();
274     CHECK_NULL_VOID(context);
275     bool isRTL = AceApplicationInfo::GetInstance().IsRightToLeft();
276     if (isRTL) {
277         context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
278     } else {
279         context->UpdateTransformTranslate({ sheetMaxWidth_ - sheetWidth_, 0.0f, 0.0f });
280     }
281 }
282 
TransformTranslateExit()283 void SheetSideObject::TransformTranslateExit()
284 {
285     auto sheetPattern = GetPattern();
286     CHECK_NULL_VOID(sheetPattern);
287     auto sheetNode = sheetPattern->GetHost();
288     CHECK_NULL_VOID(sheetNode);
289     auto context = sheetNode->GetRenderContext();
290     CHECK_NULL_VOID(context);
291     bool isRTL = AceApplicationInfo::GetInstance().IsRightToLeft();
292     if (isRTL) {
293         context->UpdateTransformTranslate({ -sheetWidth_, 0.0f, 0.0f });
294     } else {
295         context->UpdateTransformTranslate({ sheetMaxWidth_, 0.0f, 0.0f });
296     }
297 }
298 
GetAnimationPropertyCallForOverlay(bool isTransitionIn)299 std::function<void()> SheetSideObject::GetAnimationPropertyCallForOverlay(bool isTransitionIn)
300 {
301     auto sheetPattern = GetPattern();
302     CHECK_NULL_RETURN(sheetPattern, nullptr);
303     auto sheetNode = sheetPattern->GetHost();
304     CHECK_NULL_RETURN(sheetNode, nullptr);
305     auto context = sheetNode->GetRenderContext();
306     CHECK_NULL_RETURN(context, nullptr);
307 
308     std::function<void()> event;
309     if (isTransitionIn) {
310         event = [weak = WeakClaim(this)]() {
311             auto sheetObject = weak.Upgrade();
312             CHECK_NULL_VOID(sheetObject);
313             sheetObject->TransformTranslateEnter();
314         };
315     } else {
316         event = [context, weak = pattern_, objWeak = WeakClaim(this)]() {
317             auto pattern = weak.Upgrade();
318             CHECK_NULL_VOID(pattern);
319             auto sheetObject = objWeak.Upgrade();
320             CHECK_NULL_VOID(sheetObject);
321             sheetObject->TransformTranslateExit();
322             pattern->DismissSheetShadow(context);
323         };
324     }
325     return event;
326 }
327 
OnLanguageConfigurationUpdate()328 void SheetSideObject::OnLanguageConfigurationUpdate()
329 {
330     auto sheetPattern = GetPattern();
331     CHECK_NULL_VOID(sheetPattern);
332     sheetPattern->CheckLocalized();
333     CHECK_NULL_VOID(sheetPattern->GetShowState());
334     CHECK_NULL_VOID(!sheetPattern->GetIsPlayTransition());
335     TransformTranslateEnter();
336 }
337 
GetSheetSafeAreaPadding() const338 PaddingPropertyF SheetSideObject::GetSheetSafeAreaPadding() const
339 {
340     auto pipeline = PipelineContext::GetCurrentContext();
341     CHECK_NULL_RETURN(pipeline, PaddingPropertyF());
342     auto safeArea = pipeline->GetSafeArea();
343     PaddingPropertyF padding;
344     padding.left = 0.0f;
345     padding.right = 0.0f;
346     padding.top = CalcLength(safeArea.top_.Length()).GetDimension().ConvertToPx();
347     padding.bottom = CalcLength(safeArea.bottom_.Length()).GetDimension().ConvertToPx();
348     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
349         padding.left = CalcLength(safeArea.left_.Length()).GetDimension().ConvertToPx();
350     } else {
351         padding.right = CalcLength(safeArea.right_.Length()).GetDimension().ConvertToPx();
352     }
353     return padding;
354 }
355 
HandleDragStart()356 void SheetSideObject::HandleDragStart()
357 {
358     auto sheetPattern = GetPattern();
359     CHECK_NULL_VOID(sheetPattern);
360     InitScrollProps();
361     sheetPattern->SetIsDragging(true);
362     if (sheetPattern->GetAnimation() && sheetPattern->GetAnimationProcess()) {
363         AnimationUtils::StopAnimation(sheetPattern->GetAnimation());
364         sheetPattern->SetAnimationBreak(true);
365     }
366     currentOffset_ = 0.0f;
367 }
368 
HandleDragUpdate(const GestureEvent & info)369 void SheetSideObject::HandleDragUpdate(const GestureEvent& info)
370 {
371     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
372         HandleDragUpdateForRTL(info);
373     } else {
374         HandleDragUpdateForLTR(info);
375     }
376 }
377 
HandleDragUpdateForLTR(const GestureEvent & info)378 void SheetSideObject::HandleDragUpdateForLTR(const GestureEvent& info)
379 {
380     auto sheetPattern = GetPattern();
381     CHECK_NULL_VOID(sheetPattern);
382     auto mainDelta = static_cast<float>(info.GetMainDelta());
383     auto host = sheetPattern->GetHost();
384     CHECK_NULL_VOID(host);
385     auto renderContext = host->GetRenderContext();
386     CHECK_NULL_VOID(renderContext);
387     auto lastOffset = currentOffset_;
388     if (currentOffset_ + mainDelta < 0) {
389         return; // can't drag left
390     }
391     currentOffset_ = currentOffset_ + mainDelta;
392     if (NearEqual(currentOffset_, lastOffset)) {
393         return;
394     }
395     auto offsetX = sheetMaxWidth_ - sheetWidth_ + currentOffset_;
396     renderContext->UpdateTransformTranslate({ offsetX, 0.0f, 0.0f });
397     sheetPattern->onWidthDidChange(sheetWidth_ - currentOffset_);
398 }
399 
HandleDragUpdateForRTL(const GestureEvent & info)400 void SheetSideObject::HandleDragUpdateForRTL(const GestureEvent& info)
401 {
402     auto sheetPattern = GetPattern();
403     CHECK_NULL_VOID(sheetPattern);
404     auto mainDelta = static_cast<float>(info.GetMainDelta());
405     auto host = sheetPattern->GetHost();
406     CHECK_NULL_VOID(host);
407     auto renderContext = host->GetRenderContext();
408     CHECK_NULL_VOID(renderContext);
409     auto lastOffset = currentOffset_;
410     if (currentOffset_ + mainDelta > 0) {
411         return; // can't drag right
412     }
413     currentOffset_ = currentOffset_ + mainDelta;
414     if (NearEqual(currentOffset_, lastOffset)) {
415         return;
416     }
417     auto offsetX = currentOffset_ < 0 ? currentOffset_ : 0.0f;
418     renderContext->UpdateTransformTranslate({ offsetX, 0.0f, 0.0f });
419     sheetPattern->onWidthDidChange(sheetWidth_ + currentOffset_);
420 }
421 
HandleDragEnd(float dragVelocity)422 void SheetSideObject::HandleDragEnd(float dragVelocity)
423 {
424     auto sheetPattern = GetPattern();
425     CHECK_NULL_VOID(sheetPattern);
426     auto host = sheetPattern->GetHost();
427     CHECK_NULL_VOID(host);
428     sheetPattern->SetIsNeedProcessHeight(true);
429     sheetPattern->SetIsDragging(false);
430 
431     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
432         HandleDragEndForRTL(dragVelocity);
433     } else {
434         HandleDragEndForLTR(dragVelocity);
435     }
436 }
437 
HandleDragEndForLTR(float dragVelocity)438 void SheetSideObject::HandleDragEndForLTR(float dragVelocity)
439 {
440     auto sheetPattern = GetPattern();
441     CHECK_NULL_VOID(sheetPattern);
442     auto currentOffset = currentOffset_;
443 
444     if (LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) {
445         if (GreatNotEqual(std::abs(currentOffset), sheetWidth_ - std::abs(currentOffset))) {
446             sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::SLIDE, std::abs(dragVelocity));
447         } else {
448             ModifyFireSheetTransition(std::abs(dragVelocity));
449         }
450     } else {
451         if (LessNotEqual(dragVelocity, 0.0f)) {
452             // return to the original state in the opposite direction.
453             ModifyFireSheetTransition(std::abs(dragVelocity));
454         } else {
455             // when drag velocity is over the threshold.
456             sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::SLIDE, std::abs(dragVelocity));
457         }
458     }
459 }
460 
HandleDragEndForRTL(float dragVelocity)461 void SheetSideObject::HandleDragEndForRTL(float dragVelocity)
462 {
463     auto sheetPattern = GetPattern();
464     CHECK_NULL_VOID(sheetPattern);
465     auto currentOffset = currentOffset_;
466 
467     if (LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) {
468         if (GreatNotEqual(std::abs(currentOffset), sheetWidth_ - std::abs(currentOffset))) {
469             sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::SLIDE, std::abs(dragVelocity));
470         } else {
471             ModifyFireSheetTransition(std::abs(dragVelocity));
472         }
473     } else {
474         if (LessNotEqual(dragVelocity, 0.0f)) {
475             // when drag velocity is over the threshold.
476             sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::SLIDE, std::abs(dragVelocity));
477         } else {
478             // return to the original state in the opposite direction.
479             ModifyFireSheetTransition(std::abs(dragVelocity));
480         }
481     }
482 }
483 
ModifyFireSheetTransition(float dragVelocity)484 void SheetSideObject::ModifyFireSheetTransition(float dragVelocity)
485 {
486     TAG_LOGD(AceLogTag::ACE_SHEET, "SideSheet ModifyFireSheetTransition");
487     auto sheetPattern = GetPattern();
488     CHECK_NULL_VOID(sheetPattern);
489     auto host = sheetPattern->GetHost();
490     CHECK_NULL_VOID(host);
491     auto renderContext = host->GetRenderContext();
492     CHECK_NULL_VOID(renderContext);
493     AnimationOption option;
494     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
495         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
496     option.SetCurve(curve);
497     option.SetFillMode(FillMode::FORWARDS);
498 
499     auto offsetX = 0.0f;
500     auto width = sheetWidth_;
501     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
502         offsetX = 0;
503     } else {
504         offsetX = sheetMaxWidth_ - width;
505     }
506 
507     CreatePropertyCallback();
508     auto property = sheetPattern->GetProperty();
509     CHECK_NULL_VOID(property);
510     renderContext->AttachNodeAnimatableProperty(property);
511     property->SetPropertyUnit(PropertyUnit::PIXEL_POSITION);
512 
513     auto finishCallback = [weak = AceType::WeakClaim(RawPtr(sheetPattern))]() {
514         auto ref = weak.Upgrade();
515         CHECK_NULL_VOID(ref);
516         if (!ref->GetAnimationBreak()) {
517             ref->SetAnimationProcess(false);
518             ref->GetSheetObject()->SetCurrentOffset(0.0f);
519         } else {
520             ref->SetAnimationBreak(false);
521         }
522 
523         ref->AvoidAiBar();
524         ref->SetSpringBack(false);
525     };
526 
527     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
528     CHECK_NULL_VOID(layoutProperty);
529     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
530     auto interactive = sheetStyle.interactive.value_or(false);
531     sheetPattern->SetAnimationProcess(true);
532     property->Set(width - std::abs(currentOffset_));
533     auto pipeline = host->GetContextRefPtr();
534     std::shared_ptr<AnimationUtils::Animation> animation = AnimationUtils::StartAnimation(
535         option,
536         [weak = AceType::WeakClaim(RawPtr(sheetPattern)), renderContext, offsetX, width, interactive]() {
537             auto ref = weak.Upgrade();
538             CHECK_NULL_VOID(ref);
539             if (interactive) {
540                 ref->GetProperty()->Set(width);
541             }
542             if (renderContext) {
543                 renderContext->UpdateTransformTranslate({ offsetX, 0.0, 0.0f });
544             }
545         },
546         finishCallback, nullptr, pipeline);
547     sheetPattern->SetAnimation(animation);
548 }
549 
CreatePropertyCallback()550 void SheetSideObject::CreatePropertyCallback()
551 {
552     auto sheetPattern = GetPattern();
553     CHECK_NULL_VOID(sheetPattern);
554     if (sheetPattern->GetProperty()) {
555         return;
556     }
557     auto propertyCallback = [weak = AceType::WeakClaim(RawPtr(sheetPattern))](float position) {
558         auto ref = weak.Upgrade();
559         CHECK_NULL_VOID(ref);
560         ref->onWidthDidChange(static_cast<int>(position));
561     };
562     auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(0.0, std::move(propertyCallback));
563     sheetPattern->SetProperty(property);
564 }
565 
GetAvoidKeyboardModeByDefault() const566 SheetKeyboardAvoidMode SheetSideObject::GetAvoidKeyboardModeByDefault() const
567 {
568     return SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL;
569 }
570 
BeforeCreateLayoutWrapper()571 void SheetSideObject::BeforeCreateLayoutWrapper()
572 {
573     AvoidKeyboard(false);
574 
575     auto sheetPattern = GetPattern();
576     CHECK_NULL_VOID(sheetPattern);
577     auto scrollNode = sheetPattern->GetSheetScrollNode();
578     CHECK_NULL_VOID(scrollNode);
579     auto scrollablePattern = scrollNode->GetPattern<ScrollablePattern>();
580     CHECK_NULL_VOID(scrollablePattern);
581     scrollablePattern->SetNeedFullSafeArea(false);
582 }
583 
AvoidKeyboard(bool forceAvoid)584 void SheetSideObject::AvoidKeyboard(bool forceAvoid)
585 {
586     auto sheetPattern = GetPattern();
587     CHECK_NULL_VOID(sheetPattern);
588     auto host = sheetPattern->GetHost();
589     CHECK_NULL_VOID(host);
590     CHECK_NULL_VOID(host->GetFocusHub());
591     auto keyboardAvoidMode = sheetPattern->GetKeyboardAvoidMode();
592     bool isCurrentFocus = host->GetFocusHub()->IsCurrentFocus();
593     if (keyboardAvoidMode == SheetKeyboardAvoidMode::NONE || !isCurrentFocus) {
594         TAG_LOGD(AceLogTag::ACE_SHEET,
595             "Sheet will not avoid keyboard.keyboardAvoidMode:%{public}d, isCurrentFocus:%{public}d.",
596             keyboardAvoidMode, isCurrentFocus);
597         return;
598     }
599     auto pipelineContext = host->GetContext();
600     CHECK_NULL_VOID(pipelineContext);
601     auto manager = pipelineContext->GetSafeAreaManager();
602     auto keyboardHeight = manager->GetKeyboardInset().Length();
603     if (sheetPattern->GetKeyboardHeight() == keyboardHeight && !forceAvoid) {
604         return;
605     }
606     sheetPattern->SetKeyboardHeight(keyboardHeight);
607     if (sheetPattern->GetDismissProcess()) {
608         TAG_LOGD(AceLogTag::ACE_SHEET,
609             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
610         return;
611     }
612     // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY or avoidKeyboardMode::TRANSLATE_AND_RESIZE
613     resizeDecreasedHeight_ = keyboardHeight;
614     auto heightUp = isCurrentFocus ? GetUpOffsetCaretNeed() : 0.0f;
615     // 2.Side Sheet is not to handle upward logic
616 
617     // 3.deal with left height(heightUp), scroll or resize
618     // textInput will be lefted, which depends on the ability of the Scroll Components.
619     // this is different from other sheetType.
620     switch (keyboardAvoidMode) {
621         case SheetKeyboardAvoidMode::RESIZE_ONLY:
622             break;
623         case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE:
624             if (NonPositive(heightUp)) {
625                 resizeDecreasedHeight_ = 0.0f;
626             }
627             break;
628         case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL:
629         default:
630             if (NonPositive(heightUp)) {
631                 resizeDecreasedHeight_ = 0.0f;
632             } else {
633                 sheetPattern->SetColumnMinSize(NonPositive(resizeDecreasedHeight_));
634             }
635             break;
636     }
637 }
638 
GetUpOffsetCaretNeed()639 float SheetSideObject::GetUpOffsetCaretNeed()
640 {
641     // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode
642     // TextFieldManagerNG::GetHeight: the cursor Height + 24vp
643     auto sheetPattern = GetPattern();
644     CHECK_NULL_RETURN(sheetPattern, 0.0f);
645     auto host = sheetPattern->GetHost();
646     CHECK_NULL_RETURN(host, 0.0f);
647     auto pipelineContext = host->GetContext();
648     CHECK_NULL_RETURN(pipelineContext, 0.0f);
649     auto manager = pipelineContext->GetSafeAreaManager();
650     auto keyboardHeight = manager->GetKeyboardInset().Length();
651     if (keyboardHeight == 0) {
652         return 0.0f;
653     }
654     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
655     // inputH : Distance from input component's Caret to bottom of screen
656     // = caret's offset + caret's height + 24vp
657     if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() &&
658         !pipelineContext->UsingCaretAvoidMode()) {
659         TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time");
660         return 0.0f;
661     }
662     float inputH = textFieldManager ? (pipelineContext->GetRootHeight() -
663         textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight()) : 0.f;
664     // keyboardH : keyboard height + height of the bottom navigation bar
665     auto keyboardH = keyboardHeight + manager->GetSystemSafeArea().bottom_.Length();
666     // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
667     auto inputMinH = keyboardH;
668     if (inputH >= inputMinH) {
669         // Caret needs not up
670         TAG_LOGD(AceLogTag::ACE_SHEET, "Caret witch in Sheet needs not up");
671         return 0.0f;
672     }
673     // The expected height of the Caret to be lifted
674     return inputMinH - inputH;
675 }
676 
FireHeightDidChange()677 void SheetSideObject::FireHeightDidChange()
678 {
679     auto pattern = GetPattern();
680     CHECK_NULL_VOID(pattern);
681     auto preDidHeight = pattern->GetPreDidHeight();
682     if (NearEqual(preDidHeight, sheetHeight_)) {
683         return;
684     }
685     pattern->OnHeightDidChange(sheetHeight_);
686     pattern->SetPreDidHeight(sheetHeight_);
687 }
688 } // namespace OHOS::Ace::NG
689