diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp index 6dda551f354..fdcaae8729b 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp @@ -915,18 +915,13 @@ void SwiperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder(); MinusPaddingToSize(padding, size); auto paddingOffset = padding.Offset(); - auto hostNode = layoutWrapper->GetHostNode(); - CHECK_NULL_VOID(hostNode); - auto swiperPattern = hostNode->GetPattern(); - CHECK_NULL_VOID(swiperPattern); - auto ignoreBlankOffset = swiperPattern->IgnoreBlankOffset(true); // layout items. std::set layoutIndexSet; for (auto& pos : itemPosition_) { layoutIndexSet.insert(GetLoopIndex(pos.first)); - pos.second.startPos -= currentOffset_ + ignoreBlankOffset; - pos.second.endPos -= currentOffset_ + ignoreBlankOffset; + pos.second.startPos -= currentOffset_; + pos.second.endPos -= currentOffset_; LayoutItem(layoutWrapper, axis, paddingOffset, pos); } for (auto& pos : itemPositionInAnimation_) { @@ -975,6 +970,9 @@ void SwiperLayoutAlgorithm::LayoutSwiperIndicator( void SwiperLayoutAlgorithm::LayoutItem(LayoutWrapper* layoutWrapper, Axis axis, OffsetF offset, std::pair pos) { + pos.second.startPos += ignoreBlankOffset_; + pos.second.endPos += ignoreBlankOffset_; + auto layoutIndex = GetLoopIndex(pos.first); if (swipeByGroup_ && layoutIndex >= realTotalCount_) { return; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h index fa3e574fc55..c4d3b83097e 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h @@ -304,6 +304,11 @@ public: nextMarginIgnoreBlank_ = nextMarginIgnoreBlank; } + void SetIgnoreBlankOffset(float ignoreBlankOffset) + { + ignoreBlankOffset_ = ignoreBlankOffset; + } + private: void LayoutSwiperIndicator( LayoutWrapper* layoutWrapper, const RefPtr& swiperLayoutProperty, @@ -388,6 +393,7 @@ private: bool isMeasureOneMoreItem_ = false; bool isFrameAnimation_ = false; bool nextMarginIgnoreBlank_ = false; + float ignoreBlankOffset_ = 0.0f; std::set measuredItems_; std::set activeItems_; std::set cachedItems_; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp index d2f5e2448ce..76092e859cc 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp @@ -183,6 +183,7 @@ RefPtr SwiperPattern::CreateLayoutAlgorithm() algo->SetIsCaptureReverse(isCaptureReverse_); algo->SetCachedCount(GetCachedCount()); algo->SetNextMarginIgnoreBlank(nextMarginIgnoreBlank_); + algo->SetIgnoreBlankOffset(ignoreBlankOffset_); return algo; } @@ -513,6 +514,7 @@ void SwiperPattern::BeforeCreateLayoutWrapper() currentIndex_ = GetLoopIndex(currentIndex_); props->UpdateIndexWithoutMeasure(currentIndex_); } + UpdateIgnoreBlankOffsetWithIndex(); } void SwiperPattern::UpdateTargetCapture(bool forceUpdate) @@ -929,10 +931,6 @@ bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, UpdateTargetCapture(algo->GetIsNeedUpdateCapture()); } - if (jumpIndex_) { - ignoreBlankSpringOffset_ = IgnoreBlankOffset(true); - } - if (!targetIndex_) { if (isUserFinish_) { SetIndicatorJumpIndex(jumpIndex_); @@ -981,8 +979,7 @@ bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, auto targetIndexValue = IsLoop() ? targetIndex_.value() : GetLoopIndex(targetIndex_.value()); auto iter = itemPosition_.find(targetIndexValue); if (iter != itemPosition_.end()) { - ignoreBlankSpringOffset_ = IgnoreBlankOffset(false); - float targetPos = iter->second.startPos + IgnoreBlankOffset(false); + float targetPos = iter->second.startPos; auto context = GetContext(); auto props = GetLayoutProperty(); bool isNeedForwardTranslate = false; @@ -1053,34 +1050,71 @@ bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, return GetEdgeEffect() == EdgeEffect::FADE || paddingProperty != nullptr; } -float SwiperPattern::IgnoreBlankOffset(bool isJump) +float SwiperPattern::AdjustIgnoreBlankOverScrollOffSet(bool isStartOverScroll) const { - float result = 0.0f; - if (!isJump && targetIndex_) { - auto targetIndexValue = IsLoop() ? targetIndex_.value() : GetLoopIndex(targetIndex_.value()); - if (!IsLoop()) { - if (targetIndexValue == 0 && prevMarginIgnoreBlank_) { - result += GetPrevMargin() + GetItemSpace(); - } - if (targetIndexValue >= (TotalCount() - GetDisplayCount()) && nextMarginIgnoreBlank_) { - result -= GetNextMargin() + GetItemSpace(); - } + if (isStartOverScroll && NonNegative(ignoreBlankOffset_)) { + return prevMarginIgnoreBlank_ ? GetPrevMargin() + ignoreBlankOffset_ : ignoreBlankOffset_; + } + if (!isStartOverScroll && NonPositive(ignoreBlankOffset_)) { + return nextMarginIgnoreBlank_ ? -GetNextMargin() + ignoreBlankOffset_ : ignoreBlankOffset_; + } + return 0.0f; +} + +void SwiperPattern::UpdateIgnoreBlankOffsetWithIndex() +{ + if (IsLoop() || !(prevMarginIgnoreBlank_ || nextMarginIgnoreBlank_)) { + return; + } + if (jumpIndex_.has_value()) { + if (prevMarginIgnoreBlank_ && jumpIndex_.value() == 0) { + ignoreBlankOffset_ = -GetPrevMargin(); + } else if (nextMarginIgnoreBlank_ && jumpIndex_.value() >= (TotalCount() - GetDisplayCount())) { + ignoreBlankOffset_ = GetNextMargin(); + } else { + ignoreBlankOffset_ = 0.0f; + } + return; + } + if (targetIndex_.has_value()) { + float ignoreBlankOffset = ignoreBlankOffset_; + if (prevMarginIgnoreBlank_ && targetIndex_.value() == 0) { + ignoreBlankOffset_ = -GetPrevMargin(); + } else if (nextMarginIgnoreBlank_ && targetIndex_.value() >= (TotalCount() - GetDisplayCount())) { + ignoreBlankOffset_ = GetNextMargin(); + } else { + ignoreBlankOffset_ = 0.0f; + } + if (NearEqual(ignoreBlankOffset_, ignoreBlankOffset)) { + return; + } + float adjustOffset = ignoreBlankOffset_ - ignoreBlankOffset; + for (auto& item : itemPosition_) { + item.second.startPos -= adjustOffset; + item.second.endPos -= adjustOffset; } } +} - if (jumpIndex_) { - auto targetIndexValue = IsLoop() ? jumpIndex_.value() : GetLoopIndex(jumpIndex_.value()); - if (!IsLoop()) { - if (targetIndexValue == 0 && prevMarginIgnoreBlank_) { - result += GetPrevMargin() + GetItemSpace(); - } - if (targetIndexValue >= (TotalCount() - GetDisplayCount()) && nextMarginIgnoreBlank_) { - result -= GetNextMargin() + GetItemSpace(); - } - } +void SwiperPattern::UpdateIgnoreBlankOffsetWithDrag(bool overScrollDirection) +{ + if (IsLoop() || !(prevMarginIgnoreBlank_ || nextMarginIgnoreBlank_)) { + return; + } + float ignoreBlankOffset = ignoreBlankOffset_; + if (prevMarginIgnoreBlank_ && overScrollDirection) { + ignoreBlankOffset_ = -GetPrevMargin(); + } else if (nextMarginIgnoreBlank_ && !overScrollDirection) { + ignoreBlankOffset_ = GetNextMargin(); + } + if (NearEqual(ignoreBlankOffset_, ignoreBlankOffset)) { + return; + } + float adjustOffset = ignoreBlankOffset_ - ignoreBlankOffset; + for (auto& item : itemPosition_) { + item.second.startPos -= adjustOffset; + item.second.endPos -= adjustOffset; } - - return result; } bool SwiperPattern::IsAutoLinear() const @@ -2324,20 +2358,17 @@ bool SwiperPattern::FadeOverScroll(float offset) return false; } if (IsOutOfBoundary(fadeOffset_ + offset)) { - auto onlyUpdateFadeOffset = (itemPosition_.begin()->first == 0 && offset < 0.0f) || - (itemPosition_.rbegin()->first == TotalCount() - 1 && offset > 0.0f); - if (!IsVisibleChildrenSizeLessThanSwiper() && !onlyUpdateFadeOffset) { + if (!IsVisibleChildrenSizeLessThanSwiper() && NearZero(fadeOffset_)) { + UpdateIgnoreBlankOffsetWithDrag(IsOutOfStart(offset)); auto realOffset = IsOutOfStart(offset) ? -itemPosition_.begin()->second.startPos : CalculateVisibleSize() - itemPosition_.rbegin()->second.endPos; - currentDelta_ = currentDelta_ - realOffset; + currentDelta_ -= realOffset; + offset -= realOffset; HandleSwiperCustomAnimation(realOffset); } + fadeOffset_ += offset; auto host = GetHost(); CHECK_NULL_RETURN(host, false); - if (itemPosition_.begin()->first == 0 || itemPosition_.rbegin()->first == TotalCount() - 1) { - auto remainOffset = GetDistanceToEdge(); - fadeOffset_ += (offset - remainOffset); - } host->MarkDirtyNode(PROPERTY_UPDATE_RENDER); MarkDirtyNodeSelf(); return true; @@ -2376,7 +2407,6 @@ void SwiperPattern::UpdateNextValidIndex() void SwiperPattern::CheckMarkDirtyNodeForRenderIndicator(float additionalOffset, std::optional nextIndex) { - additionalOffset += ignoreBlankSpringOffset_; additionalOffset = IsHorizontalAndRightToLeft() ? -additionalOffset : additionalOffset; if (!indicatorId_.has_value()) { return; @@ -2399,7 +2429,7 @@ void SwiperPattern::CheckMarkDirtyNodeForRenderIndicator(float additionalOffset, currentFirstIndex_ = nextIndex.value_or(currentFirstIndex_); UpdateNextValidIndex(); currentFirstIndex_ = GetLoopIndex(currentFirstIndex_); - CalculateGestureState(additionalOffset - ignoreBlankSpringOffset_, currentTurnPageRate, preFirstIndex); + CalculateGestureState(additionalOffset, currentTurnPageRate, preFirstIndex); turnPageRate_ = (currentTurnPageRate == FLT_MAX ? turnPageRate_ : currentTurnPageRate); touchBottomType_ = TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE; CheckMarkForIndicatorBoundary(); @@ -3449,6 +3479,7 @@ void SwiperPattern::CreateSpringProperty() void SwiperPattern::PlaySpringAnimation(double dragVelocity) { + UpdateIgnoreBlankOffsetWithDrag(IsOutOfStart()); if (springAnimationIsRunning_) { return; } @@ -3468,11 +3499,6 @@ void SwiperPattern::PlaySpringAnimation(double dragVelocity) if (IsVisibleChildrenSizeLessThanSwiper()) { delta = extentPair.Trailing(); } - if (LessNotEqual(currentIndexOffset_, 0.0f) && nextMarginIgnoreBlank_) { - delta += GetNextMargin() + GetItemSpace(); - } else if (GreatNotEqual(currentIndexOffset_, 0.0f) && prevMarginIgnoreBlank_) { - delta -= GetPrevMargin() + GetItemSpace(); - } // spring curve: (velocity: 0.0, mass: 1.0, stiffness: 228.0, damping: 30.0) auto springCurve = MakeRefPtr(0.0f, 1.0f, 228.0f, 30.0f); AnimationOption option; @@ -3517,11 +3543,11 @@ bool SwiperPattern::IsOutOfBoundary(float mainOffset) const return isOutOfStart || isOutOfEnd; } else { - auto startPos = itemPosition_.begin()->second.startPos; + auto startPos = itemPosition_.begin()->second.startPos + AdjustIgnoreBlankOverScrollOffSet(true); startPos = NearZero(startPos, PX_EPSILON) ? 0.0 : startPos; auto isOutOfStart = itemPosition_.begin()->first == 0 && GreatNotEqual(startPos + mainOffset, 0.0); auto visibleWindowSize = CalculateVisibleSize(); - auto endPos = itemPosition_.rbegin()->second.endPos + mainOffset; + auto endPos = itemPosition_.rbegin()->second.endPos + mainOffset + AdjustIgnoreBlankOverScrollOffSet(false); endPos = NearEqual(endPos, visibleWindowSize, PX_EPSILON) ? visibleWindowSize : endPos; auto isOutOfEnd = itemPosition_.rbegin()->first == TotalCount() - 1 && LessNotEqual(endPos, visibleWindowSize); @@ -3535,7 +3561,7 @@ bool SwiperPattern::IsOutOfStart(float mainOffset) const return false; } - auto startPos = itemPosition_.begin()->second.startPos; + auto startPos = itemPosition_.begin()->second.startPos + AdjustIgnoreBlankOverScrollOffSet(true); startPos = NearZero(startPos, PX_EPSILON) ? 0.f : startPos; return itemPosition_.begin()->first == 0 && GreatNotEqual(startPos + mainOffset, 0.f); } @@ -3547,7 +3573,7 @@ bool SwiperPattern::IsOutOfEnd(float mainOffset) const } auto visibleWindowSize = CalculateVisibleSize(); - auto endPos = itemPosition_.rbegin()->second.endPos + mainOffset; + auto endPos = itemPosition_.rbegin()->second.endPos + mainOffset + AdjustIgnoreBlankOverScrollOffSet(false); endPos = NearEqual(endPos, visibleWindowSize, PX_EPSILON) ? visibleWindowSize : endPos; return itemPosition_.rbegin()->first == TotalCount() - 1 && LessNotEqual(endPos, visibleWindowSize); } diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h index 3445815e685..8c7d75d0d86 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h @@ -431,7 +431,6 @@ public: void OnCustomContentTransition(int32_t toIndex); void OnCustomAnimationFinish(int32_t fromIndex, int32_t toIndex, bool hasOnChanged); void OnSwiperCustomAnimationFinish(std::pair item); - float IgnoreBlankOffset(bool isJump); void SetCustomAnimationToIndex(int32_t toIndex) { @@ -898,6 +897,11 @@ private: void PostIdleTask(const RefPtr& frameNode); + float AdjustIgnoreBlankOverScrollOffSet(bool isStartOverScroll) const; + void UpdateIgnoreBlankOffsetWithIndex(); + // overSrollDirection is true means over start boundary, false means over end boundary. + void UpdateIgnoreBlankOffsetWithDrag(bool overSrollDirection); + friend class SwiperHelper; RefPtr panEvent_; @@ -996,7 +1000,6 @@ private: float contentMainSize_ = 0.0f; float contentCrossSize_ = 0.0f; bool crossMatchChild_ = false; - float ignoreBlankSpringOffset_ = 0.0f; std::optional uiCastJumpIndex_; std::optional jumpIndex_; @@ -1029,6 +1032,7 @@ private: bool isIndicatorInteractive_ = true; bool nextMarginIgnoreBlank_ = false; bool prevMarginIgnoreBlank_ = false; + float ignoreBlankOffset_ = 0.0f; std::optional cachedCount_; diff --git a/test/unittest/core/pattern/swiper/swiper_common_test_ng.cpp b/test/unittest/core/pattern/swiper/swiper_common_test_ng.cpp index 4e5c02ecf84..ca30287cf2d 100644 --- a/test/unittest/core/pattern/swiper/swiper_common_test_ng.cpp +++ b/test/unittest/core/pattern/swiper/swiper_common_test_ng.cpp @@ -877,7 +877,7 @@ HWTEST_F(SwiperCommonTestNg, OnKeyEvent005, TestSize.Level1) /** * @tc.name: MarginIgnoreBlankTest001 - * @tc.desc: Test Swiper PrevMargin IgnoreBlank + * @tc.desc: Test Swiper IgnoreBlank in jumpIndex case * @tc.type: FUNC */ HWTEST_F(SwiperCommonTestNg, MarginIgnoreBlankTest001, TestSize.Level1) @@ -902,11 +902,10 @@ HWTEST_F(SwiperCommonTestNg, MarginIgnoreBlankTest001, TestSize.Level1) */ ChangeIndex(0); EXPECT_EQ(pattern_->GetCurrentShownIndex(), 0); - EXPECT_EQ(GetChildX(frameNode_, 0), itemWidth * 0); - EXPECT_EQ(GetChildX(frameNode_, 1), itemWidth * 1); + EXPECT_EQ(GetChildX(frameNode_, 0), 0.f); + EXPECT_EQ(GetChildX(frameNode_, 1), itemWidth); EXPECT_EQ(GetChildX(frameNode_, 2), itemWidth * 2); EXPECT_EQ(GetChildX(frameNode_, 3), itemWidth * 3); - EXPECT_EQ(GetChildX(frameNode_, 4), 0.f); // out of view /** * @tc.steps: step3. ChangeIndex to 1 @@ -916,20 +915,19 @@ HWTEST_F(SwiperCommonTestNg, MarginIgnoreBlankTest001, TestSize.Level1) EXPECT_EQ(pattern_->GetCurrentShownIndex(), 1); EXPECT_EQ(GetChildX(frameNode_, 0), PRE_MARGIN - itemWidth); EXPECT_EQ(GetChildX(frameNode_, 1), PRE_MARGIN); - EXPECT_EQ(GetChildX(frameNode_, 2), PRE_MARGIN + itemWidth * 1); + EXPECT_EQ(GetChildX(frameNode_, 2), PRE_MARGIN + itemWidth); EXPECT_EQ(GetChildX(frameNode_, 3), PRE_MARGIN + itemWidth * 2); EXPECT_EQ(GetChildX(frameNode_, 4), PRE_MARGIN + itemWidth * 3); /** * @tc.steps: step4. ChangeIndex to 2 - * @tc.expected: Verify ignoreBlank is not effective + * @tc.expected: Verify ignoreBlank on the endpage is effective */ ChangeIndex(2); EXPECT_EQ(pattern_->GetCurrentShownIndex(), 2); - EXPECT_EQ(GetChildX(frameNode_, 0), PRE_MARGIN - itemWidth); // out of view EXPECT_EQ(GetChildX(frameNode_, 1), PRE_MARGIN + NEXT_MARGIN - itemWidth); EXPECT_EQ(GetChildX(frameNode_, 2), PRE_MARGIN + NEXT_MARGIN); - EXPECT_EQ(GetChildX(frameNode_, 3), PRE_MARGIN + NEXT_MARGIN + itemWidth * 1); + EXPECT_EQ(GetChildX(frameNode_, 3), PRE_MARGIN + NEXT_MARGIN + itemWidth); EXPECT_EQ(GetChildX(frameNode_, 4), PRE_MARGIN + NEXT_MARGIN + itemWidth * 2); }