mirror of
https://gitee.com/openharmony/arkui_ace_engine
synced 2024-11-27 17:21:11 +00:00
Swiper: ignoreBlank bugfix
Signed-off-by: huzeqi <huzeqi@huawei.com> Change-Id: Iced28a93e5b8c3cb26319ad0a1f3169a9d45be88
This commit is contained in:
parent
b2fa2d3c12
commit
4810956a76
@ -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<SwiperPattern>();
|
||||
CHECK_NULL_VOID(swiperPattern);
|
||||
auto ignoreBlankOffset = swiperPattern->IgnoreBlankOffset(true);
|
||||
|
||||
// layout items.
|
||||
std::set<int32_t> 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<int32_t, SwiperItemInfo> pos)
|
||||
{
|
||||
pos.second.startPos += ignoreBlankOffset_;
|
||||
pos.second.endPos += ignoreBlankOffset_;
|
||||
|
||||
auto layoutIndex = GetLoopIndex(pos.first);
|
||||
if (swipeByGroup_ && layoutIndex >= realTotalCount_) {
|
||||
return;
|
||||
|
@ -304,6 +304,11 @@ public:
|
||||
nextMarginIgnoreBlank_ = nextMarginIgnoreBlank;
|
||||
}
|
||||
|
||||
void SetIgnoreBlankOffset(float ignoreBlankOffset)
|
||||
{
|
||||
ignoreBlankOffset_ = ignoreBlankOffset;
|
||||
}
|
||||
|
||||
private:
|
||||
void LayoutSwiperIndicator(
|
||||
LayoutWrapper* layoutWrapper, const RefPtr<SwiperLayoutProperty>& swiperLayoutProperty,
|
||||
@ -388,6 +393,7 @@ private:
|
||||
bool isMeasureOneMoreItem_ = false;
|
||||
bool isFrameAnimation_ = false;
|
||||
bool nextMarginIgnoreBlank_ = false;
|
||||
float ignoreBlankOffset_ = 0.0f;
|
||||
std::set<int32_t> measuredItems_;
|
||||
std::set<int32_t> activeItems_;
|
||||
std::set<int32_t> cachedItems_;
|
||||
|
@ -183,6 +183,7 @@ RefPtr<LayoutAlgorithm> 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<LayoutWrapper>& dirty,
|
||||
UpdateTargetCapture(algo->GetIsNeedUpdateCapture());
|
||||
}
|
||||
|
||||
if (jumpIndex_) {
|
||||
ignoreBlankSpringOffset_ = IgnoreBlankOffset(true);
|
||||
}
|
||||
|
||||
if (!targetIndex_) {
|
||||
if (isUserFinish_) {
|
||||
SetIndicatorJumpIndex(jumpIndex_);
|
||||
@ -981,8 +979,7 @@ bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& 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<SwiperLayoutProperty>();
|
||||
bool isNeedForwardTranslate = false;
|
||||
@ -1053,34 +1050,71 @@ bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& 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<int32_t> 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<SpringCurve>(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);
|
||||
}
|
||||
|
@ -431,7 +431,6 @@ public:
|
||||
void OnCustomContentTransition(int32_t toIndex);
|
||||
void OnCustomAnimationFinish(int32_t fromIndex, int32_t toIndex, bool hasOnChanged);
|
||||
void OnSwiperCustomAnimationFinish(std::pair<int32_t, SwiperItemInfo> item);
|
||||
float IgnoreBlankOffset(bool isJump);
|
||||
|
||||
void SetCustomAnimationToIndex(int32_t toIndex)
|
||||
{
|
||||
@ -898,6 +897,11 @@ private:
|
||||
|
||||
void PostIdleTask(const RefPtr<FrameNode>& 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> panEvent_;
|
||||
@ -996,7 +1000,6 @@ private:
|
||||
float contentMainSize_ = 0.0f;
|
||||
float contentCrossSize_ = 0.0f;
|
||||
bool crossMatchChild_ = false;
|
||||
float ignoreBlankSpringOffset_ = 0.0f;
|
||||
|
||||
std::optional<int32_t> uiCastJumpIndex_;
|
||||
std::optional<int32_t> jumpIndex_;
|
||||
@ -1029,6 +1032,7 @@ private:
|
||||
bool isIndicatorInteractive_ = true;
|
||||
bool nextMarginIgnoreBlank_ = false;
|
||||
bool prevMarginIgnoreBlank_ = false;
|
||||
float ignoreBlankOffset_ = 0.0f;
|
||||
|
||||
std::optional<int32_t> cachedCount_;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user