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 f1cc7340f3c7a881f600a9485ad7d6e006d91d8f..17fb32b7a0b6a41d353bca3743520b2c4a33d667 100644 --- a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp +++ b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.cpp @@ -1080,10 +1080,8 @@ void SheetPresentationPattern::SetSheetAnimationOption(AnimationOption& option) void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity) { - bool isNeedChangeScrollHeight = sheetObject_->GetSheetType() != SheetType::SHEET_SIDE && - scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDirectionUp_; if ((HasOnHeightDidChange() && IsSheetBottomStyle() && isTransitionIn && isNeedProcessHeight_) - || isNeedChangeScrollHeight) { + || (isTransitionIn && IsNeedChangeScrollHeight(height_))) { ModifyFireSheetTransition(dragVelocity); return; } @@ -2180,6 +2178,7 @@ void SheetPresentationPattern::StartSheetTransitionAnimation( option.GetOnFinishEvent()); SetBottomStyleHotAreaInSubwindow(); } else { + AnimationUtils::StopAnimation(animation_); animation_ = AnimationUtils::StartAnimation( option, sheetObject_->GetSheetAnimationEvent(isTransitionIn, offset), @@ -2716,7 +2715,86 @@ void SheetPresentationPattern::OnScrollStartRecursive( ScrollResult SheetPresentationPattern::HandleScroll(float scrollOffset, int32_t source, NestedState state, float velocity) { - return sheetObject_->HandleScroll(scrollOffset, source, state, velocity); + if (state == NestedState::CHILD_CHECK_OVER_SCROLL) { + return {scrollOffset, true}; + } + ScrollResult result = {0, true}; + if (GreatOrEqual(currentOffset_, 0.0) && (source == SCROLL_FROM_UPDATE) && !isSheetNeedScroll_) { + isSheetNeedScroll_ = true; + } + if (!isSheetNeedScroll_ || IsScrollOutOfBoundary()) { + return {scrollOffset, true}; + } + ScrollState scrollState = source == SCROLL_FROM_ANIMATION ? ScrollState::FLING : ScrollState::SCROLL; + if (state == NestedState::CHILD_SCROLL) { + if (scrollState == ScrollState::SCROLL) { + return HandleScrollWithSheet(scrollOffset); + } + if (isSheetPosChanged_) { + HandleDragEnd(scrollOffset > 0 ? SHEET_VELOCITY_THRESHOLD : -SHEET_VELOCITY_THRESHOLD); + isSheetPosChanged_ = false; + } + } else if (state == NestedState::CHILD_OVER_SCROLL) { + isSheetNeedScroll_ = false; + return {scrollOffset, true}; + } + return result; +} + +ScrollResult SheetPresentationPattern::HandleScrollWithSheet(float scrollOffset) +{ + ScrollResult result = {0, true}; + auto sheetType = GetSheetType(); + auto sheetDetentsSize = sheetDetentHeight_.size(); + if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0) || IsShowInSubWindowTwoInOne()) { + isSheetNeedScroll_ = false; + return {scrollOffset, true}; + } + + auto currentHeightPos = GetSheetHeightBeforeDragUpdate(); + bool isDraggingUp = LessNotEqual(scrollOffset, 0.0f); + bool isReachMaxSheetHeight = GreatOrEqual(currentHeightPos, GetMaxSheetHeightBeforeDragUpdate()); + + // When dragging up the sheet, and sheet height is larger than sheet content height, + // the sheet height should be updated. + // When dragging up the sheet, and sheet height is less than or equal to sheet content height, + // the sheet content should scrolling. + if ((NearZero(currentOffset_)) && isDraggingUp && isReachMaxSheetHeight) { + isSheetNeedScroll_ = false; + return {scrollOffset, true}; + } + + // When dragging up the sheet, and sheet height is larger than max height, + // should set the coefficient of friction. + bool isExceedMaxSheetHeight = + GreatNotEqual((currentHeightPos - currentOffset_), GetMaxSheetHeightBeforeDragUpdate()); + bool isNeedCalculateFriction = isExceedMaxSheetHeight && isDraggingUp; + if (isNeedCalculateFriction && GreatNotEqual(sheetMaxHeight_, 0.0f)) { + auto friction = CalculateFriction((currentHeightPos - currentOffset_) / sheetMaxHeight_, GetRadio()); + scrollOffset = scrollOffset * friction; + } + + auto host = GetHost(); + CHECK_NULL_RETURN(host, result); + currentOffset_ = currentOffset_ + scrollOffset; + auto pageHeight = GetPageHeightWithoutOffset(); + auto sheetOffsetInPage = pageHeight - currentHeightPos + currentOffset_; + if (LessOrEqual(sheetOffsetInPage, pageHeight - sheetMaxHeight_)) { + sheetOffsetInPage = pageHeight - sheetMaxHeight_; + currentOffset_ = currentHeightPos - sheetMaxHeight_; + } + if (IsNeedChangeScrollHeight(currentHeightPos - currentOffset_)) { + ChangeSheetPage(currentHeightPos - currentOffset_); + } + HandleFollowAccessibilityEvent(currentHeightPos - currentOffset_); + auto renderContext = host->GetRenderContext(); + renderContext->UpdateTransformTranslate({ 0.0f, sheetOffsetInPage, 0.0f }); + isSheetPosChanged_ = NearZero(scrollOffset) ? false : true; + if (IsSheetBottomStyle()) { + OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_); + } + isSheetPosChanged_ = true; + return result; } void SheetPresentationPattern::OnScrollEndRecursive(const std::optional& velocity) @@ -3603,6 +3681,18 @@ void SheetPresentationPattern::OnAppear() } } +bool SheetPresentationPattern::IsNeedChangeScrollHeight(float height) +{ + auto it = std::min_element(sheetDetentHeight_.begin(), sheetDetentHeight_.end()); + if (it == sheetDetentHeight_.end()) { + return false; + } + float lowestDetentHeight = *it; + bool isNeedChangeScrollHeight = + scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && GreatOrEqual(height, lowestDetentHeight); + return isNeedChangeScrollHeight; +} + void SheetPresentationPattern::OnWillDisappear() { isOnDisappearing_ = true; 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 9ca406b33b29157c6d89b03d01f57b8a30f94e37..b829fb32d732dcdfdfe93b73e31246a1bd8b3b88 100644 --- a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h +++ b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h @@ -1014,6 +1014,7 @@ public: void HandleFitContontChange(float height); void GetCurrentScrollHeight(); void RecoverScrollOrResizeAvoidStatus(); + bool IsNeedChangeScrollHeight(float height); bool IsResizeWhenAvoidKeyboard(); void InitScrollProps(); uint32_t GetCurrentBroadcastDetentsIndex(); diff --git a/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp b/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp index afcb8ca3a6d237e5fddd70de65787e13b76b007c..ee300cdbdfcd9ceb099a690d8966ef375214d54b 100644 --- a/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp +++ b/frameworks/core/components_ng/pattern/sheet/sheet_object.cpp @@ -319,10 +319,8 @@ void SheetObject::HandleDragUpdate(const GestureEvent& info) offset = pageHeight - sheetPattern->GetSheetMaxHeight(); sheetPattern->SetCurrentOffset(height - sheetPattern->GetSheetMaxHeight()); } - bool isNeedChangeScrollHeight = sheetPattern->GetScrollSizeMode() == ScrollSizeMode::CONTINUOUS && - sheetPattern->GetCurrentOffset() < 0; - if (isNeedChangeScrollHeight) { - sheetPattern->ChangeScrollHeight(height - sheetPattern->GetCurrentOffset()); + if (sheetPattern->IsNeedChangeScrollHeight(height - sheetPattern->GetCurrentOffset())) { + sheetPattern->ChangeSheetPage(height - sheetPattern->GetCurrentOffset()); } sheetPattern->HandleFollowAccessibilityEvent(height - sheetPattern->GetCurrentOffset()); auto renderContext = host->GetRenderContext(); @@ -369,13 +367,11 @@ void SheetObject::HandleDragEnd(float dragVelocity) } else { sheetPattern->SetDetentsIndex(detentsLowerPos); sheetPattern->ChangeSheetHeight(downHeight); - sheetPattern->ChangeSheetPage(height); sheetPattern->SheetTransition(true, std::abs(dragVelocity)); } } else if (LessNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) { sheetPattern->SetDetentsIndex(detentsUpperPos); sheetPattern->ChangeSheetHeight(upHeight); - sheetPattern->ChangeSheetPage(height); sheetPattern->SheetTransition(true, std::abs(dragVelocity)); } } else { @@ -386,13 +382,11 @@ void SheetObject::HandleDragEnd(float dragVelocity) } else { sheetPattern->SetDetentsIndex(detentsLowerPos); sheetPattern->ChangeSheetHeight(downHeight); - sheetPattern->ChangeSheetPage(height); sheetPattern->SheetTransition(true, std::abs(dragVelocity)); } } else { sheetPattern->SetDetentsIndex(detentsUpperPos); sheetPattern->ChangeSheetHeight(upHeight); - sheetPattern->ChangeSheetPage(height); sheetPattern->SheetTransition(true, std::abs(dragVelocity)); } } @@ -578,13 +572,7 @@ void SheetObject::ModifyFireSheetTransition(float dragVelocity) auto ref = weak.Upgrade(); CHECK_NULL_VOID(ref); if (renderContext) { - renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f }); ref->GetProperty()->Set(ref->GetHeight() + ref->GetSheetHeightUp()); - bool isNeedChangeScrollHeight = - ref->GetScrollSizeMode() == ScrollSizeMode::CONTINUOUS && ref->GetIsDirectionUp(); - if (isNeedChangeScrollHeight) { - ref->ChangeScrollHeight(ref->GetHeight()); - } } }, finishCallback); @@ -598,10 +586,29 @@ void SheetObject::CreatePropertyCallback() if (sheetPattern->GetProperty()) { return; } - auto propertyCallback = [weak = AceType::WeakClaim(RawPtr(sheetPattern))](float position) { + auto host = sheetPattern->GetHost(); + CHECK_NULL_VOID(host); + auto renderContext = host->GetRenderContext(); + CHECK_NULL_VOID(renderContext); + auto initialTranslate = renderContext->GetTransformTranslate().value(); + + auto propertyCallback = [weak = AceType::WeakClaim(RawPtr(sheetPattern)), renderContext, initialTranslate]( + float position) { auto ref = weak.Upgrade(); CHECK_NULL_VOID(ref); ref->OnHeightDidChange(static_cast(position)); + + // position = height_ - drag_delta + sheetHeightUp_ + // offset = pageHeight - height + currentOffset_ + // = GetPageHeightWithoutOffset() - GetSheetHeightBeforeDragUpdate() + drag_delta + // = GetPageHeightWithoutOffset() - (height_ + sheetHeightUp_) + drag_delta + // = GetPageHeightWithoutOffset() - (position + drag_delta ) + drag_delta + // offset = GetPageHeightWithoutOffset() - position + float targetTranslateY = ref->GetPageHeightWithoutOffset() - position; + auto targetTranslate = initialTranslate; + targetTranslate.y = CalcDimension(targetTranslateY, DimensionUnit::PX); + renderContext->UpdateTransformTranslate(targetTranslate); + ref->ChangeSheetPage(position); }; auto property = AceType::MakeRefPtr(0.0, std::move(propertyCallback)); sheetPattern->SetProperty(property);