diff --git a/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.cpp index 75a1f9f4e9c2cbcc85b6d2f5dbd90665ef32d831..2e32bd9ea73b3a582bd42ce2fca2efe483f369ac 100644 --- a/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.cpp @@ -360,7 +360,7 @@ std::pair ListItemGroupLayoutAlgorithm::GetItemGroupPosition(int32 } else if (scrollAlign_ == ScrollAlign::START) { auto pos = itemPosition_.find(index); if (pos != itemPosition_.end()) { - float top = startPos_; + float top = startPos_ + contentStartOffset_; if (sticky == V2::StickyStyle::HEADER || sticky == V2::StickyStyle::BOTH) { top += headerMainSize_; } @@ -371,7 +371,7 @@ std::pair ListItemGroupLayoutAlgorithm::GetItemGroupPosition(int32 } else if (scrollAlign_ == ScrollAlign::END) { auto pos = itemPosition_.find(index); if (pos != itemPosition_.end()) { - float bottom = endPos_; + float bottom = endPos_ - contentEndOffset_; if (sticky == V2::StickyStyle::FOOTER || sticky == V2::StickyStyle::BOTH) { bottom -= footerMainSize_; } @@ -499,10 +499,35 @@ void ListItemGroupLayoutAlgorithm::MeasureCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex) { MeasureALineCenter(layoutWrapper, layoutConstraint, startIndex); + MeasureJumpToItemForward(layoutWrapper, layoutConstraint, GetEndIndex() + 1, GetEndPosition()); + MeasureJumpToItemBackward(layoutWrapper, layoutConstraint, GetStartIndex() - 1, GetStartPosition()); - float currentEndPos = GetEndPosition(); - float currentStartPos = currentEndPos; - int32_t currentIndex = startIndex; + totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; + float currentStartPos = headerMainSize_; + for (auto& pos : itemPosition_) { + float len = pos.second.second - pos.second.first; + pos.second.first = currentStartPos; + pos.second.second = currentStartPos + len; + currentStartPos = pos.second.second + spaceWidth_; + } +} + +void ListItemGroupLayoutAlgorithm::MeasureAuto(LayoutWrapper* layoutWrapper, + const LayoutConstraintF& layoutConstraint, int32_t startIndex) +{ + if (MeasureALineAuto(layoutWrapper, layoutConstraint, startIndex) == 0) { + return; + } + + totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; +} + +void ListItemGroupLayoutAlgorithm::MeasureJumpToItemForward(LayoutWrapper* layoutWrapper, + const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos) +{ + float currentStartPos = startPos; + float currentEndPos = startPos; + int32_t currentIndex = startIndex - 1; while (LessOrEqual(currentEndPos, endPos_)) { currentStartPos = currentEndPos; int32_t count = MeasureALineForward(layoutWrapper, layoutConstraint, currentIndex, @@ -514,10 +539,14 @@ void ListItemGroupLayoutAlgorithm::MeasureCenter(LayoutWrapper* layoutWrapper, currentEndPos += spaceWidth_; } } +} - currentIndex = startIndex; - currentStartPos = GetStartPosition(); - currentEndPos = currentStartPos; +void ListItemGroupLayoutAlgorithm::MeasureJumpToItemBackward(LayoutWrapper* layoutWrapper, + const LayoutConstraintF& layoutConstraint, int32_t endIndex, float endPos) +{ + float currentEndPos = endPos; + float currentStartPos = endPos; + int32_t currentIndex = endIndex + 1; while (GreatOrEqual(currentStartPos, startPos_)) { currentEndPos = currentStartPos; int32_t count = MeasureALineBackward(layoutWrapper, layoutConstraint, currentIndex, @@ -526,51 +555,23 @@ void ListItemGroupLayoutAlgorithm::MeasureCenter(LayoutWrapper* layoutWrapper, break; } if (currentIndex > 0) { - currentStartPos = currentStartPos - spaceWidth_; + currentStartPos -= spaceWidth_; } } - - totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; - currentStartPos = headerMainSize_; - for (auto& pos : itemPosition_) { - float len = pos.second.second - pos.second.first; - pos.second.first = currentStartPos; - pos.second.second = currentStartPos + len; - currentStartPos = pos.second.second + spaceWidth_; - } -} - -void ListItemGroupLayoutAlgorithm::MeasureAuto(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, int32_t startIndex) -{ - if (MeasureALineAuto(layoutWrapper, layoutConstraint, startIndex) == 0) { - return; - } - - totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; } void ListItemGroupLayoutAlgorithm::MeasureStart(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex) { V2::StickyStyle sticky = listLayoutProperty_->GetStickyStyle().value_or(V2::StickyStyle::NONE); - float currentStartPos = startPos_; + float currentStartPos = startPos_ + contentStartOffset_; if (sticky == V2::StickyStyle::HEADER || sticky == V2::StickyStyle::BOTH) { currentStartPos += headerMainSize_; } - float currentEndPos = currentStartPos; - int32_t currentIndex = startIndex - 1; - while (LessOrEqual(currentEndPos, endPos_)) { - currentStartPos = currentEndPos; - int32_t count = MeasureALineForward(layoutWrapper, layoutConstraint, currentIndex, - currentStartPos, currentEndPos); - if (count == 0) { - break; - } - if (currentIndex < (totalItemCount_ - 1)) { - currentEndPos += spaceWidth_; - } + MeasureJumpToItemForward(layoutWrapper, layoutConstraint, startIndex, currentStartPos); + if (Positive(contentStartOffset_)) { + MeasureJumpToItemBackward(layoutWrapper, layoutConstraint, startIndex - 1, currentStartPos); } totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; @@ -587,27 +588,18 @@ void ListItemGroupLayoutAlgorithm::MeasureEnd(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t endIndex) { V2::StickyStyle sticky = listLayoutProperty_->GetStickyStyle().value_or(V2::StickyStyle::NONE); - float currentEndPos = endPos_; + float currentEndPos = endPos_ - contentEndOffset_; if (sticky == V2::StickyStyle::FOOTER || sticky == V2::StickyStyle::BOTH) { currentEndPos -= footerMainSize_; } - float currentStartPos = currentEndPos; - int32_t currentIndex = endIndex + 1; - while (GreatOrEqual(currentStartPos, startPos_)) { - currentEndPos = currentStartPos; - int32_t count = MeasureALineBackward(layoutWrapper, layoutConstraint, currentIndex, - currentEndPos, currentStartPos); - if (count == 0) { - break; - } - if (currentIndex > 0) { - currentStartPos -= spaceWidth_; - } + MeasureJumpToItemBackward(layoutWrapper, layoutConstraint, endIndex, currentEndPos); + if (Positive(contentEndOffset_)) { + MeasureJumpToItemForward(layoutWrapper, layoutConstraint, endIndex + 1, currentEndPos); } totalMainSize_ = GetEndPosition() - GetStartPosition() + headerMainSize_ + footerMainSize_; - currentStartPos = headerMainSize_; + float currentStartPos = headerMainSize_; for (auto& pos : itemPosition_) { float len = pos.second.second - pos.second.first; pos.second.first = currentStartPos; @@ -777,7 +769,7 @@ void ListItemGroupLayoutAlgorithm::LayoutHeaderFooter(LayoutWrapper* layoutWrapp headerMainSize = wrapper->GetGeometryNode()->GetFrameSize().MainSize(axis_); float headerPos = 0.0f; if ((sticky == V2::StickyStyle::BOTH || sticky == V2::StickyStyle::HEADER) && !itemPosition_.empty()) { - float stickyPos = -mainPos; + float stickyPos = contentStartOffset_ - mainPos; if (GetEndIndex() == totalItemCount_ - 1) { stickyPos = std::min(stickyPos, GetEndPosition() - headerMainSize); } @@ -793,7 +785,7 @@ void ListItemGroupLayoutAlgorithm::LayoutHeaderFooter(LayoutWrapper* layoutWrapp float const listMainSize = endPos_ - startPos_; if (Positive(listMainSize) && (sticky == V2::StickyStyle::BOTH || sticky == V2::StickyStyle::FOOTER)) { auto footerMainSize = wrapper->GetGeometryNode()->GetFrameSize().MainSize(axis_); - float stickyPos = listMainSize - mainPos - footerMainSize; + float stickyPos = listMainSize - contentEndOffset_ - mainPos - footerMainSize; if (stickyPos < headerMainSize) { stickyPos = headerMainSize; } diff --git a/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.h b/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.h index dcf73102b4cf6b7f5a7d1667b718f675649f3a51..d61cf37034e921d01054446a1f283ce19cfc94e6 100644 --- a/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/list/list_item_group_layout_algorithm.h @@ -95,6 +95,12 @@ public: forwardLayout_ = forwardLayout; } + void SetContentOffset(float contentStartOffset, float contentEndOffset) + { + contentStartOffset_ = contentStartOffset; + contentEndOffset_ = contentEndOffset; + } + void SetListLayoutProperty(RefPtr layoutProperty) { listLayoutProperty_ = std::move(layoutProperty); @@ -208,6 +214,10 @@ private: int32_t startIndex, float startPos); void MeasureBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t endIndex, float endPos); + void MeasureJumpToItemForward(LayoutWrapper* layoutWrapper, + const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos); + void MeasureJumpToItemBackward(LayoutWrapper* layoutWrapper, + const LayoutConstraintF& layoutConstraint, int32_t endIndex, float endPos); void MeasureCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); void MeasureStart(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); void MeasureEnd(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); @@ -249,6 +259,8 @@ private: float prevEndPos_ = 0.0f; float endPos_ = 0.0f; float referencePos_ = 0.0f; + float contentStartOffset_ = 0.0f; + float contentEndOffset_ = 0.0f; bool forwardLayout_ = true; bool needAllLayout_ = false; }; diff --git a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp index 48af0ced482b7e13c44368b69fd662e9e3e4643e..833b51631be8d0b54ac3001eb343df0c78557444 100644 --- a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp @@ -65,8 +65,10 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) // calculate idealSize and set FrameSize axis_ = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); - contentStartOffset_ = listLayoutProperty->GetContentStartOffset().value_or(0.0f); - contentEndOffset_ = listLayoutProperty->GetContentEndOffset().value_or(0.0f); + auto startOffset = listLayoutProperty->GetContentStartOffset().value_or(0.0f); + contentStartOffset_ = std::max(PipelineBase::Vp2PxWithCurrentDensity(startOffset), 0.0); + auto endOffset = listLayoutProperty->GetContentEndOffset().value_or(0.0f); + contentEndOffset_ = std::max(PipelineBase::Vp2PxWithCurrentDensity(endOffset), 0.0); // calculate main size. auto contentConstraint = listLayoutProperty->GetContentLayoutConstraint().value(); @@ -97,6 +99,10 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) contentMainSize_ = GetMainAxisSize(contentIdealSize.ConvertToSizeT(), axis_); mainSizeIsDefined_ = true; } + if (GreatOrEqual(contentStartOffset_ + contentEndOffset_, contentMainSize_)) { + contentStartOffset_ = 0; + contentEndOffset_ = 0; + } if (totalItemCount_ > 0) { OnSurfaceChanged(layoutWrapper); @@ -203,7 +209,8 @@ void ListLayoutAlgorithm::CalculateEstimateOffset(ScrollAlign align) switch (align) { case ScrollAlign::START: case ScrollAlign::NONE: - estimateOffset_ = averageHeight * static_cast(jumpIndex_.value() / GetLanes()); + estimateOffset_ = averageHeight * static_cast(jumpIndex_.value() / GetLanes()) - + contentStartOffset_; break; case ScrollAlign::CENTER: estimateOffset_ = averageHeight * static_cast(jumpIndex_.value() / GetLanes()) - @@ -211,7 +218,7 @@ void ListLayoutAlgorithm::CalculateEstimateOffset(ScrollAlign align) break; case ScrollAlign::END: estimateOffset_ = averageHeight * static_cast(jumpIndex_.value() / GetLanes() + 1) - - spaceWidth_ - contentMainSize_; + spaceWidth_ - contentMainSize_ + contentEndOffset_; break; case ScrollAlign::AUTO: switch (scrollAutoType_) { @@ -259,11 +266,9 @@ void ListLayoutAlgorithm::ClearAllItemPosition(LayoutWrapper* layoutWrapper) void ListLayoutAlgorithm::BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper) { LayoutForward(layoutWrapper, jumpIndex_.value(), startPos); - if (((jumpIndex_.value() > 0) || (!IsScrollSnapAlignCenter(layoutWrapper) && jumpIndex_.value() == 0)) && - GreatNotEqual(GetStartPosition(), (contentStartOffset_ + startMainPos_))) { - LayoutBackward(layoutWrapper, jumpIndex_.value() - 1, GetStartPosition()); - if (LessNotEqual(GetEndIndex(), totalItemCount_ - 1) && - LessNotEqual(GetEndPosition(), endMainPos_)) { + if ((GetStartIndex() > 0) && GreatNotEqual(GetStartPosition(), startMainPos_)) { + LayoutBackward(layoutWrapper, GetStartIndex() - 1, GetStartPosition()); + if ((GetEndIndex() < totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); } } @@ -272,10 +277,9 @@ void ListLayoutAlgorithm::BeginLayoutForward(float startPos, LayoutWrapper* layo void ListLayoutAlgorithm::BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper) { LayoutBackward(layoutWrapper, jumpIndex_.value(), startPos); - if (LessOrEqual(jumpIndex_.value(), totalItemCount_ - 1) && - LessNotEqual(GetEndPosition(), endMainPos_)) { - LayoutForward(layoutWrapper, jumpIndex_.value() + 1, GetEndPosition()); - if (Positive(GetStartIndex()) && GreatNotEqual(GetStartPosition(), startMainPos_)) { + if (LessOrEqual(GetEndIndex(), totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { + LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); + if ((GetStartIndex() > 0) && GreatNotEqual(GetStartPosition(), startMainPos_)) { LayoutBackward(layoutWrapper, GetStartIndex() - 1, GetStartPosition()); } } @@ -440,7 +444,7 @@ void ListLayoutAlgorithm::HandleJumpEnd(LayoutWrapper* layoutWrapper) LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); } } else { - BeginLayoutBackward(contentMainSize_, layoutWrapper); + BeginLayoutBackward(contentMainSize_ - contentEndOffset_, layoutWrapper); } } @@ -1317,6 +1321,7 @@ void ListLayoutAlgorithm::SetListItemGroupParam(const RefPtr& lay } itemGroup->SetListMainSize(startMainPos_, endMainPos_, referencePos, forwardLayout); itemGroup->SetListLayoutProperty(layoutProperty); + itemGroup->SetContentOffset(contentStartOffset_, contentEndOffset_); if (jumpIndex_.has_value() && (!jumpIndexInGroup_.has_value())) { if (forwardLayout&& (scrollAlign_ == ScrollAlign::START || (scrollAlign_ == ScrollAlign::AUTO && scrollAutoType_ == ScrollAutoType::START))) { @@ -1566,11 +1571,11 @@ float ListLayoutAlgorithm::GetStopOnScreenOffset(V2::ScrollSnapAlign scrollSnapA { float stopOnScreen = 0; if (scrollSnapAlign == V2::ScrollSnapAlign::START) { - stopOnScreen = 0; + stopOnScreen = contentStartOffset_; } else if (scrollSnapAlign == V2::ScrollSnapAlign::CENTER) { stopOnScreen = contentMainSize_ / 2.0f; } else if (scrollSnapAlign == V2::ScrollSnapAlign::END) { - stopOnScreen = contentMainSize_; + stopOnScreen = contentMainSize_ - contentEndOffset_; } return stopOnScreen; } @@ -1641,12 +1646,12 @@ float ListLayoutAlgorithm::CalculatePredictSnapEndPositionByIndex(uint32_t index { float predictSnapEndPos = 0; if (scrollSnapAlign == V2::ScrollSnapAlign::START) { - predictSnapEndPos = totalOffset_ + itemPosition_[index].startPos; + predictSnapEndPos = totalOffset_ + itemPosition_[index].startPos - contentStartOffset_; } else if (scrollSnapAlign == V2::ScrollSnapAlign::CENTER) { float itemHeight = itemPosition_[index].endPos - itemPosition_[index].startPos; predictSnapEndPos = totalOffset_ + itemPosition_[index].startPos + itemHeight / 2.0f - contentMainSize_ / 2.0f; } else if (scrollSnapAlign == V2::ScrollSnapAlign::END) { - predictSnapEndPos = totalOffset_ + itemPosition_[index].endPos - contentMainSize_; + predictSnapEndPos = totalOffset_ + itemPosition_[index].endPos - contentMainSize_ + contentEndOffset_; } return predictSnapEndPos; } diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.cpp b/frameworks/core/components_ng/pattern/list/list_pattern.cpp index fa748f1eae3a64e3da49fe4f26fc6bff6520115f..6045fde6892972637cd72b098fe9a5127f8d0229 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.cpp +++ b/frameworks/core/components_ng/pattern/list/list_pattern.cpp @@ -593,13 +593,13 @@ OverScrollOffset ListPattern::GetOverScrollOffset(double delta) const if (startIndex_ == 0 && groupAtStart) { auto startPos = startMainPos_ + GetChainDelta(0); auto newStartPos = startPos + delta; - if (startPos > 0 && newStartPos > 0) { + if (startPos > contentStartOffset_ && newStartPos > contentStartOffset_) { offset.start = delta; } - if (startPos > 0 && newStartPos <= 0) { + if (startPos > contentStartOffset_ && newStartPos <= contentStartOffset_) { offset.start = -startPos; } - if (startPos <= 0 && newStartPos > 0) { + if (startPos <= contentStartOffset_ && newStartPos > contentStartOffset_) { offset.start = newStartPos; } if (IsScrollSnapAlignCenter() && !itemPosition_.empty()) { @@ -613,18 +613,19 @@ OverScrollOffset ListPattern::GetOverScrollOffset(double delta) const } if (endIndex_ == maxListItemIndex_ && groupAtEnd) { auto endPos = endMainPos_ + GetChainDelta(endIndex_); - if (GreatNotEqual(contentMainSize_, endMainPos_ - startMainPos_)) { - endPos = startMainPos_ + contentMainSize_; + auto contentEndPos = contentMainSize_ - contentEndOffset_; + if (GreatNotEqual(contentEndPos, endMainPos_ - startMainPos_)) { + endPos = startMainPos_ + contentEndPos; } auto newEndPos = endPos + delta; - if (endPos < contentMainSize_ && newEndPos < contentMainSize_) { + if (endPos < contentEndPos && newEndPos < contentEndPos) { offset.end = delta; } - if (endPos < contentMainSize_ && newEndPos >= contentMainSize_) { - offset.end = contentMainSize_ - endPos; + if (endPos < contentEndPos && newEndPos >= contentEndPos) { + offset.end = contentEndPos - endPos; } - if (endPos >= contentMainSize_ && newEndPos < contentMainSize_) { - offset.end = newEndPos - contentMainSize_; + if (endPos >= contentEndPos && newEndPos < contentEndPos) { + offset.end = newEndPos - contentEndPos; } if (IsScrollSnapAlignCenter() && !itemPosition_.empty()) { float endItemHeight = itemPosition_.begin()->second.endPos - itemPosition_.begin()->second.startPos; @@ -726,12 +727,15 @@ bool ListPattern::IsOutOfBoundary(bool useCurrentDelta) if (endIndex_ == maxListItemIndex_) { endPos += GetChainDelta(endIndex_); } - bool outOfStart = (startIndex_ == 0) && Positive(startPos) && GreatNotEqual(endPos, contentMainSize_); + auto contentEndPos = contentMainSize_ - contentEndOffset_; + bool outOfStart = (startIndex_ == 0) && GreatNotEqual(startPos, contentStartOffset_) && + GreatNotEqual(endPos, contentEndPos); if (GetAlwaysEnabled()) { - outOfStart = (startIndex_ == 0) && Positive(startPos); + outOfStart = (startIndex_ == 0) && GreatNotEqual(startPos, contentStartOffset_); } - bool outOfEnd = (endIndex_ == maxListItemIndex_) && LessNotEqual(endPos, contentMainSize_) && Negative(startPos); + bool outOfEnd = (endIndex_ == maxListItemIndex_) && LessNotEqual(endPos, contentEndPos) && + LessNotEqual(startPos, contentStartOffset_); if (IsScrollSnapAlignCenter()) { auto itemHeight = itemPosition_.begin()->second.endPos - itemPosition_.begin()->second.startPos; outOfStart = (startIndex_ == 0) && Positive(startPos + itemHeight / 2.0f - contentMainSize_ / 2.0f); @@ -1247,12 +1251,18 @@ bool ListPattern::GetListItemAnimatePos(float startPos, float endPos, ScrollAlig case ScrollAlign::START: case ScrollAlign::NONE: targetPos = startPos; + if (!IsScrollSnapAlignCenter()) { + targetPos -= contentStartOffset_; + } break; case ScrollAlign::CENTER: targetPos = (endPos + startPos) / 2.0f - contentMainSize_ / 2.0f; break; case ScrollAlign::END: targetPos = endPos - contentMainSize_; + if (!IsScrollSnapAlignCenter()) { + targetPos += contentEndOffset_; + } break; case ScrollAlign::AUTO: targetPos = CalculateTargetPos(startPos, endPos); @@ -1280,6 +1290,9 @@ bool ListPattern::GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, f return false; } targetPos = startPos; + if (!IsScrollSnapAlignCenter()) { + targetPos -= contentStartOffset_; + } break; case ScrollAlign::CENTER: if (!groupPattern->IsDisplayStart() || !groupPattern->IsDisplayEnd()) { @@ -1292,6 +1305,9 @@ bool ListPattern::GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, f return false; } targetPos = endPos - contentMainSize_; + if (!IsScrollSnapAlignCenter()) { + targetPos += contentEndOffset_; + } break; case ScrollAlign::AUTO: if (targetIndex_.has_value()) { @@ -1338,6 +1354,9 @@ bool ListPattern::GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int3 if (stickyStyle == V2::StickyStyle::HEADER || stickyStyle == V2::StickyStyle::BOTH) { targetPos -= groupPattern->GetHeaderMainSize(); } + if (!IsScrollSnapAlignCenter()) { + targetPos -= contentStartOffset_; + } break; case ScrollAlign::CENTER: targetPos = paddingBeforeContent + startPos + @@ -1349,6 +1368,9 @@ bool ListPattern::GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int3 if (stickyStyle == V2::StickyStyle::FOOTER || stickyStyle == V2::StickyStyle::BOTH) { targetPos += groupPattern->GetFooterMainSize(); } + if (!IsScrollSnapAlignCenter()) { + targetPos += contentEndOffset_; + } break; case ScrollAlign::AUTO: float itemStartPos = paddingBeforeContent + startPos + itemPosInGroup.value().first; diff --git a/test/unittest/core/pattern/list/list_test_ng.cpp b/test/unittest/core/pattern/list/list_test_ng.cpp index 9f693f439bb6efce9366976d3f3cf628cb114869..019a2570ee83ef0fc20c0ad64f77188dc3892cfc 100644 --- a/test/unittest/core/pattern/list/list_test_ng.cpp +++ b/test/unittest/core/pattern/list/list_test_ng.cpp @@ -6880,4 +6880,119 @@ HWTEST_F(ListTestNg, ScrollToIndex006, TestSize.Level1) EXPECT_TRUE(ScrollToIndex(itemNumber, false, ScrollAlign::END, 1300.f)); EXPECT_TRUE(ScrollToIndex(itemNumber, false, ScrollAlign::AUTO, 1300.f)); } + +/** + * @tc.name: ContentOffset001 + * @tc.desc: Test top content offset and bottom end offset + * @tc.type: FUNC + */ +HWTEST_F(ListTestNg, ContentOffset001, TestSize.Level1) +{ + /** + * @tc.steps: step1. create List + * @tc.expected: Total Offset is negative contentStartOffset. + */ + const int32_t itemNumber = 20; + const float contentStartOffset = 100; + const float contentEndOffset = 50; + Create([=](ListModelNG model) { + model.SetContentStartOffset(contentStartOffset); + model.SetContentEndOffset(contentEndOffset); + CreateItem(itemNumber); + }); + + for (int32_t index = 0; index < 7; index++) { + EXPECT_EQ(GetChildRect(frameNode_, index).GetY(), contentStartOffset + index * ITEM_HEIGHT); + } + + float offset = pattern_->GetTotalOffset(); + EXPECT_FLOAT_EQ(offset, -contentStartOffset); + + /** + * @tc.steps: step2. scroll to bottom + * @tc.expected: Bottom content offset equal to contentEndOffset. + */ + ScrollToEdge(ScrollEdgeType::SCROLL_BOTTOM); + offset = pattern_->GetTotalOffset(); + EXPECT_FLOAT_EQ(offset, itemNumber * ITEM_HEIGHT - LIST_HEIGHT + contentEndOffset); +} + +/** + * @tc.name: ContentOffset002 + * @tc.desc: Test scroll to Index with content offset + * @tc.type: FUNC + */ +HWTEST_F(ListTestNg, ContentOffset002, TestSize.Level1) +{ + /** + * @tc.steps: step1. create List + */ + const int32_t itemNumber = 20; + const float contentStartOffset = 100; + const float contentEndOffset = 50; + Create([=](ListModelNG model) { + model.SetContentStartOffset(contentStartOffset); + model.SetContentEndOffset(contentEndOffset); + CreateItem(itemNumber); + }); + + /** + * @tc.steps: step2. scroll to target item align start. + * @tc.expected: check whether the offset is correct. + */ + EXPECT_TRUE(ScrollToIndex(0, false, ScrollAlign::START, -contentStartOffset)); + EXPECT_TRUE(ScrollToIndex(1, false, ScrollAlign::START, ITEM_HEIGHT - contentStartOffset)); + EXPECT_TRUE(ScrollToIndex(2, false, ScrollAlign::START, ITEM_HEIGHT * 2 - contentStartOffset)); + + /** + * @tc.steps: step3. scroll to target item align end. + * @tc.expected: check whether the offset is correct. + */ + const float MAX_OFFSET = itemNumber * ITEM_HEIGHT - LIST_HEIGHT + contentEndOffset; + EXPECT_TRUE(ScrollToIndex(itemNumber - 1, false, ScrollAlign::END, MAX_OFFSET)); + EXPECT_TRUE(ScrollToIndex(itemNumber - 2, false, ScrollAlign::END, MAX_OFFSET - ITEM_HEIGHT)); + EXPECT_TRUE(ScrollToIndex(itemNumber - 3, false, ScrollAlign::END, MAX_OFFSET - ITEM_HEIGHT * 2)); +} + +/** + * @tc.name: ContentOffset003 + * @tc.desc: Test scroll to ListItemGroup with content offset + * @tc.type: FUNC + */ +HWTEST_F(ListTestNg, ContentOffset003, TestSize.Level1) +{ + /** + * @tc.steps: step1. create List + */ + const int32_t GroupNumber = 5; + const float contentStartOffset = 100; + const float contentEndOffset = 50; + Create([=](ListModelNG model) { + model.SetContentStartOffset(contentStartOffset); + model.SetContentEndOffset(contentEndOffset); + CreateGroup(GroupNumber); + }); + + /** + * @tc.steps: step2. scroll to target group align start. + * @tc.expected: check whether the offset is correct. + */ + for (int32_t i = 0; i < 3; i++) { + pattern_->ScrollToIndex(i, false, ScrollAlign::START); + FlushLayoutTask(frameNode_); + EXPECT_EQ(GetChildRect(frameNode_, i).GetY(), contentStartOffset); + } + + /** + * @tc.steps: step3. scroll to target group align end. + * @tc.expected: check whether the offset is correct. + */ + for (int32_t i = 0; i < 3; i++) { + int32_t index = GroupNumber - i - 1; + pattern_->ScrollToIndex(index, false, ScrollAlign::END); + FlushLayoutTask(frameNode_); + auto rect = GetChildRect(frameNode_, index); + EXPECT_EQ(rect.Bottom(), LIST_HEIGHT - contentEndOffset); + } +} } // namespace OHOS::Ace::NG