From 10a9c538c05db0b7f6ec39c038faa767067d7107 Mon Sep 17 00:00:00 2001 From: chengfeiwang Date: Wed, 25 Jun 2025 14:43:23 +0800 Subject: [PATCH] side sheet supports to avoid keyboard Signed-off-by: chengfeiwang Change-Id: Iadd611344793240fb896b45bf8d6a8896456f1d4 --- .../overlay/sheet_presentation_pattern.cpp | 36 +++--- .../overlay/sheet_presentation_pattern.h | 23 +++- .../pattern/sheet/sheet_object.cpp | 33 +++++ .../pattern/sheet/sheet_object.h | 4 + ...eet_presentation_side_layout_algorithm.cpp | 5 +- .../pattern/sheet/side/sheet_side_object.cpp | 119 ++++++++++++++++-- .../pattern/sheet/side/sheet_side_object.h | 13 +- .../overlay/sheet_showInSubwindow_test_ng.cpp | 114 +++++++++++++++++ 8 files changed, 314 insertions(+), 33 deletions(-) diff --git a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp index e9d50992baa..6c93edf6e04 100644 --- a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp +++ b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp @@ -41,6 +41,7 @@ #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h" #include "core/components_ng/pattern/scroll/scroll_layout_property.h" #include "core/components_ng/pattern/scroll/scroll_pattern.h" +#include "core/components_ng/pattern/stage/content_root_pattern.h" #include "core/components_ng/pattern/stage/page_pattern.h" #include "core/components_ng/pattern/text/text_layout_property.h" #include "core/components_ng/pattern/text_field/text_field_manager.h" @@ -106,9 +107,10 @@ void SheetPresentationPattern::OnModifyDone() } InitPanEvent(); InitPageHeight(); - InitScrollProps(); UpdateSheetType(); UpdateSheetObject(sheetType_); + InitSheetMode(); + InitScrollProps(); InitFoldCreaseRegion(); } @@ -203,7 +205,6 @@ void SheetPresentationPattern::InitPageHeight() if (!NearEqual(currentTopSafeArea, sheetTopSafeArea_)) { topSafeAreaChanged_ = true; } - InitSheetMode(); } void SheetPresentationPattern::InitScrollProps() @@ -240,19 +241,9 @@ bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap( UpdateSheetTitle(); ClipSheetNode(); - auto sheetType = GetSheetType(); - if (sheetType != SheetType::SHEET_POPUP && sheetType != SheetType::SHEET_SIDE) { - if (windowRotate_) { - // When rotating the screen, - // first switch the sheet to the position corresponding to the proportion before rotation - TranslateTo(pageHeight_ - height_); - windowRotate_ = false; - } else { - // After rotation, if need to avoid the keyboard, trigger the avoidance behavior - AvoidSafeArea(); - } - } - if (GetSheetType() == SheetType::SHEET_POPUP) { + sheetObject_->AvoidKeyboardInDirtyLayoutProcess(); + + if (sheetType_ == SheetType::SHEET_POPUP) { MarkSheetPageNeedRender(); } return true; @@ -890,7 +881,19 @@ float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetSty return sheetHeight; } +void SheetPresentationPattern::BeforeCreateLayoutWrapper() +{ + ContentRootPattern::BeforeCreateLayoutWrapper(); + CHECK_NULL_VOID(sheetObject_); + sheetObject_->BeforeCreateLayoutWrapper(); +} + void SheetPresentationPattern::AvoidSafeArea(bool forceAvoid) +{ + sheetObject_->AvoidKeyboard(forceAvoid); +} + +void SheetPresentationPattern::AvoidKeyboard(bool forceAvoid) { auto sheetType = GetSheetType(); if (sheetType == SheetType::SHEET_POPUP || IsCurSheetNeedHalfFoldHover() || @@ -1922,7 +1925,7 @@ void SheetPresentationPattern::InitSheetMode() CHECK_NULL_VOID(layoutProperty); auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle()); scrollSizeMode_ = sheetStyle.scrollSizeMode.value_or(ScrollSizeMode::FOLLOW_DETENT); - keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL); + keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(sheetObject_->GetAvoidKeyboardModeByDefault()); sheetEffectEdge_ = sheetStyle.sheetEffectEdge.value_or(SheetEffectEdge::ALL); } @@ -3864,6 +3867,7 @@ void SheetPresentationPattern::UpdateSheetObject(SheetType type) FireOnTypeDidChange(); // start init new sheet data InitPanEvent(); + InitSheetMode(); isFirstInit_ = false; AvoidAiBar(); } diff --git a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h index fef58fc053e..8bdd6fc699e 100644 --- a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h +++ b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h @@ -298,11 +298,14 @@ public: bool IsScrollable() const; void AvoidAiBar(); + void BeforeCreateLayoutWrapper() override; void AvoidSafeArea(bool forceAvoid = false); + void AvoidKeyboard(bool forceAvoid); void CheckBuilderChange(); float GetSheetHeightChange(); void ScrollTo(float height); bool AdditionalScrollTo(const RefPtr& scroll, float height); + void SetColumnMinSize(bool reset = false); float InitialSingleGearHeight(NG::SheetStyle& sheetStyle); float GetSheetTopSafeArea(); float UpdateSheetTransitionOffset(); @@ -575,6 +578,16 @@ public: sheetOffsetY_ = offsetY; } + bool IsWindowRotate() const + { + return windowRotate_; + } + + void SetWindowRotate(bool windowRotate) + { + windowRotate_ = windowRotate; + } + void SetWindowChanged(bool change) { windowChanged_ = change; @@ -605,6 +618,11 @@ public: isScrolling_ = value; } + SheetKeyboardAvoidMode GetKeyboardAvoidMode() const + { + return keyboardAvoidMode_; + } + float GetScrollHeightNoProcess() const { return scrollHeight_; @@ -1021,6 +1039,7 @@ public: return windowSize_; } + void TranslateTo(float height); void GetArrowOffsetByPlacement(const RefPtr& layoutAlgorithm); void DismissSheetShadow(const RefPtr& context); void ResetClipShape(); @@ -1058,8 +1077,6 @@ private: void RegisterHoverModeChangeCallback(); void InitPageHeight(); - void TranslateTo(float height); - void SetColumnMinSize(bool reset = false); void UpdateCloseIconStatus(); void UpdateTitlePadding(); RefPtr GetTitleNode(); @@ -1140,7 +1157,7 @@ private: float wrapperHeight_ = 0.0f; // sheetWrapper frameSize Height float wrapperWidth_ = 0.0f; // sheetWrapper frameSize Width float pageHeight_ = 0.0f; // root Height, = maxSize.Height() - float scrollHeight_ = 0.0f; + float scrollHeight_ = 0.0f; // not scroll frameHeight, it is scroll Height after ScrollTo. float preWidth_ = 0.0f; int32_t preType_ = -1; float sheetTopSafeArea_ = .0f; diff --git a/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp b/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp index 3b1556e82f2..f96315cf148 100644 --- a/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp +++ b/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp @@ -624,4 +624,37 @@ void SheetObject::CreatePropertyCallback() auto property = AceType::MakeRefPtr(0.0, std::move(propertyCallback)); sheetPattern->SetProperty(property); } + +SheetKeyboardAvoidMode SheetObject::GetAvoidKeyboardModeByDefault() const +{ + if (sheetType_ == SheetType::SHEET_POPUP) { + return SheetKeyboardAvoidMode::NONE; + } + return SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL; +} + +void SheetObject::AvoidKeyboardInDirtyLayoutProcess() +{ + auto sheetPattern = GetPattern(); + CHECK_NULL_VOID(sheetPattern); + if (sheetType_ == SheetType::SHEET_POPUP) { + return; + } + if (sheetPattern->IsWindowRotate()) { + // When rotating the screen, + // first switch the sheet to the position corresponding to the proportion before rotation + sheetPattern->TranslateTo(sheetPattern->GetPageHeightWithoutOffset() - sheetPattern->GetHeight()); + sheetPattern->SetWindowRotate(false); + } else { + // After rotation, if need to avoid the keyboard, trigger the avoidance behavior + AvoidKeyboard(false); + } +} + +void SheetObject::AvoidKeyboard(bool forceAvoid) +{ + auto sheetPattern = GetPattern(); + CHECK_NULL_VOID(sheetPattern); + sheetPattern->AvoidKeyboard(forceAvoid); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/sheet/sheet_object.h b/frameworks/core/components_ng/pattern/sheet/sheet_object.h index 312f24cb4b0..72ba99f6dc3 100644 --- a/frameworks/core/components_ng/pattern/sheet/sheet_object.h +++ b/frameworks/core/components_ng/pattern/sheet/sheet_object.h @@ -52,6 +52,10 @@ public: virtual void HandleDragEnd(float dragVelocity); virtual void ModifyFireSheetTransition(float dragVelocity); virtual void CreatePropertyCallback(); + virtual void BeforeCreateLayoutWrapper() {}; + virtual SheetKeyboardAvoidMode GetAvoidKeyboardModeByDefault() const; + virtual void AvoidKeyboardInDirtyLayoutProcess(); + virtual void AvoidKeyboard(bool forceAvoid); virtual ScrollResult HandleScroll(float scrollOffset, int32_t source, NestedState state, float velocity = 0.f); diff --git a/frameworks/core/components_ng/pattern/sheet/side/sheet_presentation_side_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/sheet/side/sheet_presentation_side_layout_algorithm.cpp index 3132d4e7572..33709d563a9 100644 --- a/frameworks/core/components_ng/pattern/sheet/side/sheet_presentation_side_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/sheet/side/sheet_presentation_side_layout_algorithm.cpp @@ -17,6 +17,7 @@ #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h" #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h" +#include "core/components_ng/pattern/sheet/side/sheet_side_object.h" namespace OHOS::Ace::NG { namespace { @@ -128,6 +129,8 @@ void SheetPresentationSideLayoutAlgorithm::MeasureScrollNode(LayoutWrapper* layo CHECK_NULL_VOID(host); auto sheetPattern = host->GetPattern(); CHECK_NULL_VOID(sheetPattern); + auto sideObject = AceType::DynamicCast(sheetPattern->GetSheetObject()); + CHECK_NULL_VOID(sideObject); auto scrollNode = sheetPattern->GetSheetScrollNode(); CHECK_NULL_VOID(scrollNode); auto index = host->GetChildIndexById(scrollNode->GetId()); @@ -147,7 +150,7 @@ void SheetPresentationSideLayoutAlgorithm::MeasureScrollNode(LayoutWrapper* layo childConstraint.maxSize.SetHeight(childHeight); childConstraint.parentIdealSize = OptionalSizeF(childWidth, childHeight); childConstraint.percentReference = SizeF(childWidth, childHeight); - childConstraint.selfIdealSize = OptionalSizeF(childWidth, childHeight); + childConstraint.selfIdealSize = OptionalSizeF(childWidth, childHeight - sideObject->GetResizeDecreasedHeight()); scrollWrapper->Measure(childConstraint); } diff --git a/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.cpp b/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.cpp index 020b088bac9..ce3ec8b5d7b 100644 --- a/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.cpp +++ b/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.cpp @@ -24,6 +24,8 @@ #include "core/components_ng/pattern/overlay/overlay_manager.h" #include "core/components_ng/pattern/overlay/sheet_manager.h" #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h" +#include "core/components_ng/pattern/scroll/scroll_layout_property.h" +#include "core/components_ng/pattern/scroll/scroll_pattern.h" #include "core/components_ng/pattern/text_field/text_field_manager.h" namespace OHOS::Ace::NG { @@ -199,25 +201,16 @@ void SheetSideObject::InitAnimationForOverlay(bool isTransitionIn, bool isFirstT CHECK_NULL_VOID(sheetPattern); auto sheetNode = sheetPattern->GetHost(); CHECK_NULL_VOID(sheetNode); - auto context = sheetNode->GetRenderContext(); - CHECK_NULL_VOID(context); - context->UpdateRenderGroup(true, false, true); - TAG_LOGD(AceLogTag::ACE_SHEET, "UpdateRenderGroup start"); auto sheetParent = AceType::DynamicCast(sheetNode->GetParent()); CHECK_NULL_VOID(sheetParent); if (isTransitionIn) { if (isFirstTransition) { - sheetNode->OnAccessibilityEvent(AccessibilityEventType::PAGE_OPEN, - WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE); TransformTranslateExit(); + sheetPattern->GetBuilderInitHeight(); } sheetPattern->FireOnTypeDidChange(); - sheetPattern->FireOnWidthDidChange(); + sheetPattern->FireOnHeightDidChange(); ACE_SCOPED_TRACE("Side Sheet starts the entrance animation"); - } else { - sheetNode->OnAccessibilityEvent(AccessibilityEventType::PAGE_CLOSE, - WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE); - sheetParent->GetEventHub()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMTRANSPARENT); } } @@ -236,7 +229,6 @@ void SheetSideObject::SetFinishEventForAnimationOption( auto pattern = sheetNode->GetPattern(); CHECK_NULL_VOID(pattern); pattern->OnAppear(); - pattern->SendMessagesBeforeFirstTransitionIn(true); pattern->AvoidAiBar(); pattern->FireOnWidthDidChange(); }); @@ -566,4 +558,107 @@ void SheetSideObject::CreatePropertyCallback() auto property = AceType::MakeRefPtr(0.0, std::move(propertyCallback)); sheetPattern->SetProperty(property); } + +SheetKeyboardAvoidMode SheetSideObject::GetAvoidKeyboardModeByDefault() const +{ + return SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL; +} + +void SheetSideObject::BeforeCreateLayoutWrapper() +{ + AvoidKeyboard(false); +} + +void SheetSideObject::AvoidKeyboard(bool forceAvoid) +{ + auto sheetPattern = GetPattern(); + CHECK_NULL_VOID(sheetPattern); + auto host = sheetPattern->GetHost(); + CHECK_NULL_VOID(host); + CHECK_NULL_VOID(host->GetFocusHub()); + auto keyboardAvoidMode = sheetPattern->GetKeyboardAvoidMode(); + bool isCurrentFocus = host->GetFocusHub()->IsCurrentFocus(); + if (keyboardAvoidMode == SheetKeyboardAvoidMode::NONE || !isCurrentFocus) { + TAG_LOGD(AceLogTag::ACE_SHEET, + "Sheet will not avoid keyboard.keyboardAvoidMode:%{public}d, isCurrentFocus:%{public}d.", + keyboardAvoidMode, isCurrentFocus); + return; + } + auto pipelineContext = host->GetContext(); + CHECK_NULL_VOID(pipelineContext); + auto manager = pipelineContext->GetSafeAreaManager(); + auto keyboradHeight = manager->GetKeyboardInset().Length(); + if (sheetPattern->GetKeyboardHeight() == keyboradHeight && !forceAvoid) { + return; + } + sheetPattern->SetKeyboardHeight(keyboradHeight); + if (sheetPattern->GetDismissProcess()) { + TAG_LOGD(AceLogTag::ACE_SHEET, + "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here."); + return; + } + // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY or avoidKeyboardMode::TRANSLATE_AND_RESIZE + resizeDecreasedHeight_ = keyboradHeight; + auto heightUp = isCurrentFocus ? GetUpOffsetCaretNeed() : 0.0f; + // 2.Side Sheet is not to handle upward logic + + // 3.deal with left height(heightUp), scroll or resize + // textInput will be lefted, which depends on the ability of the Scroll Components. + // this is different from other sheetType. + switch (keyboardAvoidMode) { + case SheetKeyboardAvoidMode::RESIZE_ONLY: + break; + case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE: + if (NonPositive(heightUp)) { + resizeDecreasedHeight_ = 0.0f; + } + break; + case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL: + default: + if (NonPositive(heightUp)) { + resizeDecreasedHeight_ = 0.0f; + } else { + sheetPattern->SetColumnMinSize(NonPositive(resizeDecreasedHeight_)); + } + break; + } +} + +float SheetSideObject::GetUpOffsetCaretNeed() +{ + // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode + // TextFieldManagerNG::GetHeight: the cursor Height + 24vp + auto sheetPattern = GetPattern(); + CHECK_NULL_RETURN(sheetPattern, 0.0f); + auto host = sheetPattern->GetHost(); + CHECK_NULL_RETURN(host, 0.0f); + auto pipelineContext = host->GetContext(); + CHECK_NULL_RETURN(pipelineContext, 0.0f); + auto manager = pipelineContext->GetSafeAreaManager(); + auto keyboardHeight = manager->GetKeyboardInset().Length(); + if (keyboardHeight == 0) { + return 0.f; + } + auto textFieldManager = DynamicCast(pipelineContext->GetTextFieldManager()); + // inputH : Distance from input component's Caret to bottom of screen + // = caret's offset + caret's height + 24vp + if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() && + !pipelineContext->UsingCaretAvoidMode()) { + TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time"); + return .0f; + } + float inputH = textFieldManager ? (pipelineContext->GetRootHeight() - + textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight()) : 0.f; + // keyboardH : keyboard height + height of the bottom navigation bar + auto keyboardH = keyboardHeight + manager->GetSystemSafeArea().bottom_.Length(); + // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard + auto inputMinH = keyboardH; + if (inputH >= inputMinH) { + // Caret needs not up + TAG_LOGD(AceLogTag::ACE_SHEET, "Caret witch in Sheet needs not up"); + return .0f; + } + // The expected height of the Caret to be lifted + return inputMinH - inputH; +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.h b/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.h index 4c67f81b2c3..a5c7b412d7e 100644 --- a/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.h +++ b/frameworks/core/components_ng/pattern/sheet/side/sheet_side_object.h @@ -43,6 +43,10 @@ public: void HandleDragEnd(float dragVelocity) override; void ModifyFireSheetTransition(float dragVelocity) override; void CreatePropertyCallback() override; + void BeforeCreateLayoutWrapper() override; + SheetKeyboardAvoidMode GetAvoidKeyboardModeByDefault() const override; + void AvoidKeyboardInDirtyLayoutProcess() override {}; + void AvoidKeyboard(bool forceAvoid) override; ScrollResult HandleScroll(float scrollOffset, int32_t source, NestedState state, float velocity = 0.f) override { @@ -60,7 +64,10 @@ public: return PanDirection::HORIZONTAL; } - float GetSheetWidhtBeforeDragUpdate() const; + float GetResizeDecreasedHeight() const + { + return resizeDecreasedHeight_; + } private: void UpdateSidePosition(); @@ -71,6 +78,10 @@ private: void HandleDragUpdateForRTL(const GestureEvent& info); void TransformTranslateEnter(); void TransformTranslateExit(); + void DecreaseScrollHeightInSideSheet(uint32_t decreaseHeight); + float GetUpOffsetCaretNeed(); + + float resizeDecreasedHeight_ = 0.0f; }; } // namespace OHOS::Ace::NG diff --git a/test/unittest/core/pattern/overlay/sheet_showInSubwindow_test_ng.cpp b/test/unittest/core/pattern/overlay/sheet_showInSubwindow_test_ng.cpp index 19f5f467ede..63c5e156676 100644 --- a/test/unittest/core/pattern/overlay/sheet_showInSubwindow_test_ng.cpp +++ b/test/unittest/core/pattern/overlay/sheet_showInSubwindow_test_ng.cpp @@ -44,6 +44,7 @@ #include "core/components_ng/pattern/overlay/sheet_wrapper_layout_algorithm.h" #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h" #include "core/components_ng/pattern/root/root_pattern.h" +#include "core/components_ng/pattern/scroll/scroll_pattern.h" #include "core/components_ng/pattern/sheet/sheet_mask_pattern.h" #include "core/components_ng/pattern/stage/stage_pattern.h" #include "core/components_ng/pattern/text/text_pattern.h" @@ -1492,4 +1493,117 @@ HWTEST_F(SheetShowInSubwindowTestNg, UpdateSheetObject, TestSize.Level1) EXPECT_TRUE(object6->GetSheetType() == SheetType::SHEET_POPUP); EXPECT_FLOAT_EQ(object6->sheetWidth_, 20.0f); } + +/** + * @tc.type: FUNC + * @tc.name: Test BindSheet + * @tc.desc: Test SheetSideObject::AvoidKeyboard. + */ +HWTEST_F(SheetShowInSubwindowTestNg, TestSideSheetAvoidKeyboard1, TestSize.Level1) +{ + /** + * @tc.steps: step1. create sheet node and initialize sheet pattern. + */ + auto callback = [](const std::string&) {}; + auto sheetNode = FrameNode::CreateFrameNode(V2::SHEET_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + AceType::MakeRefPtr(0, "", std::move(callback))); + ASSERT_NE(sheetNode, nullptr); + auto scroll = FrameNode::CreateFrameNode( + V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); + auto builderContent = + FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 0, AceType::MakeRefPtr(false)); + builderContent->MountToParent(scroll); + scroll->MountToParent(sheetNode); + auto sheetPattern = sheetNode->GetPattern(); + ASSERT_NE(sheetPattern, nullptr); + sheetPattern->InitSheetObject(); + sheetPattern->UpdateSheetObject(SheetType::SHEET_SIDE); + sheetPattern->SetScrollNode(WeakPtr(scroll)); + sheetPattern->keyboardAvoidMode_ = SheetKeyboardAvoidMode::NONE; + auto object = AceType::DynamicCast(sheetPattern->GetSheetObject()); + ASSERT_NE(object, nullptr); + EXPECT_TRUE(object->GetSheetType() == SheetType::SHEET_SIDE); + object->AvoidKeyboard(false); + EXPECT_FALSE(sheetNode->GetFocusHub()->currentFocus_); + EXPECT_EQ(sheetPattern->GetKeyboardAvoidMode(), SheetKeyboardAvoidMode::NONE); + /** + * @tc.cases: case1. sheet focuses but keyboard is not up. + */ + sheetNode->GetFocusHub()->currentFocus_ = true; + sheetPattern->keyboardAvoidMode_ = SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL; + object->AvoidKeyboard(false); + EXPECT_EQ(sheetPattern->GetKeyboardHeight(), 0); + object->AvoidKeyboard(true); + EXPECT_EQ(sheetPattern->GetKeyboardHeight(), 0); + /** + * @tc.cases: case2. sheet focuses and keyboard is up. + */ + auto safeAreaManager = AceType::MakeRefPtr(); + SafeAreaInsets::Inset upKeyboard { 0, 200 }; + safeAreaManager->keyboardInset_ = upKeyboard; + MockPipelineContext::GetCurrent()->safeAreaManager_ = safeAreaManager; + object->AvoidKeyboard(false); + EXPECT_EQ(sheetPattern->keyboardHeight_, 200); + /** + * @tc.cases: case3. sheet focuses and keyboard is down. + */ + SafeAreaInsets::Inset downKeyboard { 0, 0 }; + safeAreaManager->keyboardInset_ = downKeyboard; + object->AvoidKeyboard(false); + EXPECT_EQ(sheetPattern->keyboardHeight_, 0); +} + +/** + * @tc.type: FUNC + * @tc.name: Test BindSheet + * @tc.desc: Test SheetSideObject::AvoidKeyboard. + */ +HWTEST_F(SheetShowInSubwindowTestNg, TestSideSheetAvoidKeyboard2, TestSize.Level1) +{ + /** + * @tc.steps: step1. create sheet node and initialize sheet pattern. + */ + auto callback = [](const std::string&) {}; + auto sheetNode = FrameNode::CreateFrameNode(V2::SHEET_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + AceType::MakeRefPtr(0, "", std::move(callback))); + ASSERT_NE(sheetNode, nullptr); + auto scroll = FrameNode::CreateFrameNode( + V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); + auto builderContent = + FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 0, AceType::MakeRefPtr(false)); + builderContent->MountToParent(scroll); + scroll->MountToParent(sheetNode); + auto sheetPattern = sheetNode->GetPattern(); + ASSERT_NE(sheetPattern, nullptr); + sheetPattern->InitSheetObject(); + sheetPattern->UpdateSheetObject(SheetType::SHEET_SIDE); + sheetPattern->SetScrollNode(WeakPtr(scroll)); + sheetPattern->keyboardAvoidMode_ = SheetKeyboardAvoidMode::RESIZE_ONLY; + auto object = AceType::DynamicCast(sheetPattern->GetSheetObject()); + ASSERT_NE(object, nullptr); + EXPECT_TRUE(object->GetSheetType() == SheetType::SHEET_SIDE); + object->AvoidKeyboard(false); + EXPECT_FALSE(sheetNode->GetFocusHub()->currentFocus_); + EXPECT_EQ(sheetPattern->GetKeyboardAvoidMode(), SheetKeyboardAvoidMode::RESIZE_ONLY); + /** + * @tc.cases: case1. sheet focuses and keyboard is up. + */ + sheetNode->GetFocusHub()->currentFocus_ = true; + auto safeAreaManager = AceType::MakeRefPtr(); + SafeAreaInsets::Inset upKeyboard { 0, 200 }; + safeAreaManager->keyboardInset_ = upKeyboard; + MockPipelineContext::GetCurrent()->safeAreaManager_ = safeAreaManager; + MockPipelineContext::GetCurrent()->SetRootSize(800, 2000); + object->AvoidKeyboard(false); + EXPECT_EQ(sheetPattern->keyboardHeight_, 200); + EXPECT_TRUE(NearEqual(object->resizeDecreasedHeight_, 200.0f)); + /** + * @tc.cases: case2. sheet focuses and keyboard is down. + */ + SafeAreaInsets::Inset downKeyboard { 0, 0 }; + safeAreaManager->keyboardInset_ = downKeyboard; + object->AvoidKeyboard(true); + EXPECT_EQ(sheetPattern->keyboardHeight_, 0); + EXPECT_TRUE(NearEqual(object->resizeDecreasedHeight_, 0.0f)); +} } // namespace OHOS::Ace::NG \ No newline at end of file -- Gitee