From f734636ea694321575aab99b7c253e715ef392ff Mon Sep 17 00:00:00 2001 From: zhangrongjie Date: Thu, 30 May 2024 12:21:27 +0000 Subject: [PATCH] add extra offset to scrollToIndex Signed-off-by: zhangrongjie Change-Id: Ibd04953da830b34012eed4596119d4a9b3575425 --- .../jsview/js_scroller.cpp | 27 ++++++++++--- .../jsview/js_view_abstract.cpp | 40 +++++++++---------- .../jsview/js_view_abstract.h | 1 + .../components/indexer/render_indexer.cpp | 2 +- .../scroll/scroll_controller_base.h | 4 +- .../scroll/scroll_position_controller.cpp | 3 +- .../scroll/scroll_position_controller.h | 2 +- .../pattern/grid/grid_layout_info.h | 1 + .../pattern/grid/grid_pattern.cpp | 11 ++++- .../components_ng/pattern/grid/grid_pattern.h | 3 +- .../grid_scroll_layout_algorithm.cpp | 37 +++++++++-------- .../grid_irregular_layout_algorithm.cpp | 4 ++ .../pattern/list/list_pattern.cpp | 11 ++++- .../components_ng/pattern/list/list_pattern.h | 3 +- .../scrollable/scrollable_controller.cpp | 5 ++- .../scrollable/scrollable_controller.h | 2 +- .../pattern/scrollable/scrollable_pattern.h | 20 +++++++++- .../top_down/water_flow_layout_algorithm.cpp | 4 ++ .../top_down/water_flow_layout_info.cpp | 4 ++ .../top_down/water_flow_segmented_layout.cpp | 4 ++ .../layout/water_flow_layout_info_base.h | 1 + .../pattern/waterflow/water_flow_pattern.cpp | 11 ++++- .../pattern/waterflow/water_flow_pattern.h | 3 +- .../grid/grid_position_controller.cpp | 3 +- .../grid/grid_position_controller.h | 3 +- .../list/list_position_controller.cpp | 3 +- .../list/list_position_controller.h | 3 +- .../water_flow_position_controller.cpp | 3 +- .../water_flow_position_controller.h | 2 +- .../native/node/scroller_modifier.cpp | 2 +- .../grid/grid_scroller_event_test_ng.cpp | 8 ++-- .../pattern/grid/grid_scroller_test_ng.cpp | 32 +++++++-------- .../pattern/list/list_scroller_test_ng.cpp | 4 +- .../scroll/scroll_controller_test_ng.cpp | 4 +- .../waterflow/water_flow_scroller_test_ng.cpp | 4 +- 35 files changed, 185 insertions(+), 89 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp b/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp index a1ba3f2a98a..652f6c69d6c 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp @@ -227,16 +227,31 @@ void JSScroller::ScrollToIndex(const JSCallbackInfo& args) if (!scrollController) { return; } - // 2:parameters count, 1: parameter index - if (args.Length() >= 2 && args[1]->IsBoolean()) { - smooth = args[1]->ToBoolean(); + // 2: parameters count, 1: parameter index + auto smoothArg = args[1]; + if (args.Length() >= 2 && smoothArg->IsBoolean()) { + smooth = smoothArg->ToBoolean(); } - // 3:parameters count, 2: parameter index - if (args.Length() == 3) { + // 3: parameters count, 2: parameter index + if (args.Length() >= 3) { ConvertFromJSValue(args[2], ALIGN_TABLE, align); } + + // 4: parameters count, 3: parameter index + std::optional extraOffset = std::nullopt; + auto optionArg = args[3]; + if (args.Length() == 4 && optionArg->IsObject()) { + auto obj = JSRef::Cast(optionArg); + CalcDimension offset; + if (JSViewAbstract::ParseLengthMetricsToDimension(obj->GetProperty("extraOffset"), offset)) { + auto offsetPx = offset.ConvertToPx(); + if (!std::isnan(offsetPx)) { + extraOffset = offsetPx; + } + } + } ContainerScope scope(instanceId_); - scrollController->ScrollToIndex(index, smooth, align); + scrollController->ScrollToIndex(index, smooth, align, extraOffset); } void JSScroller::ScrollPage(const JSCallbackInfo& args) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 6c863ef98b9..b00e48d5cbf 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -1532,26 +1532,6 @@ void ParseCommonEdgeWidthsProps(const JSRef& object, CommonCalcDimensi } ParseEdgeWidthsProps(object, commonCalcDimension); } - -bool ParseLengthMetricsToDimension(const JSRef& jsValue, CalcDimension& result) -{ - if (jsValue->IsNumber()) { - result = CalcDimension(jsValue->ToNumber(), DimensionUnit::FP); - return true; - } - if (jsValue->IsString()) { - auto value = jsValue->ToString(); - return StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::FP); - } - if (jsValue->IsObject()) { - JSRef jsObj = JSRef::Cast(jsValue); - double value = jsObj->GetProperty("value")->ToNumber(); - auto unit = static_cast(jsObj->GetProperty("unit")->ToNumber()); - result = CalcDimension(value, unit); - return true; - } - return false; -} } // namespace RefPtr GetResourceObject(const JSRef& jsObj) @@ -4971,6 +4951,26 @@ bool JSViewAbstract::ParseColorMetricsToColor(const JSRef& jsValue, Color return false; } +bool JSViewAbstract::ParseLengthMetricsToDimension(const JSRef& jsValue, CalcDimension& result) +{ + if (jsValue->IsNumber()) { + result = CalcDimension(jsValue->ToNumber(), DimensionUnit::FP); + return true; + } + if (jsValue->IsString()) { + auto value = jsValue->ToString(); + return StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::FP); + } + if (jsValue->IsObject()) { + JSRef jsObj = JSRef::Cast(jsValue); + double value = jsObj->GetProperty("value")->ToNumber(); + auto unit = static_cast(jsObj->GetProperty("unit")->ToNumber()); + result = CalcDimension(value, unit); + return true; + } + return false; +} + bool JSViewAbstract::ParseLengthMetricsToPositiveDimension(const JSRef& jsValue, CalcDimension& result) { return ParseLengthMetricsToDimension(jsValue, result) ? GreatOrEqual(result.Value(), 0.0f) : false; diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h index 8147d1a40dc..2c23312c97f 100755 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h @@ -284,6 +284,7 @@ public: static bool ParseJsDimensionVp(const JSRef& jsValue, CalcDimension& result); static bool ParseJsDimensionFp(const JSRef& jsValue, CalcDimension& result); static bool ParseJsDimensionPx(const JSRef& jsValue, CalcDimension& result); + static bool ParseLengthMetricsToDimension(const JSRef& jsValue, CalcDimension& result); static bool ParseLengthMetricsToPositiveDimension(const JSRef& jsValue, CalcDimension& result); static bool ParseColorMetricsToColor(const JSRef& jsValue, Color& result); static bool ParseJsDouble(const JSRef& jsValue, double& result); diff --git a/frameworks/core/components/indexer/render_indexer.cpp b/frameworks/core/components/indexer/render_indexer.cpp index b61c95c3294..2855ce69319 100644 --- a/frameworks/core/components/indexer/render_indexer.cpp +++ b/frameworks/core/components/indexer/render_indexer.cpp @@ -557,7 +557,7 @@ void RenderIndexer::MoveList(int32_t index) int32_t indexToJump = circleMode_ ? index : index + 1; lastHeadIndex_ = indexToJump; LOGI("[indexer] MoveList Jump to index[%{public}d], indexToJump[%{public}d]", index, indexToJump); - controller_->ScrollToIndex(indexToJump, false, ScrollAlign::START); + controller_->ScrollToIndex(indexToJump, false, ScrollAlign::START, std::nullopt); } RefPtr RenderIndexer::GetSpecificItem(int32_t index) diff --git a/frameworks/core/components/scroll/scroll_controller_base.h b/frameworks/core/components/scroll/scroll_controller_base.h index 91672da7f5f..1a8a1b3a967 100644 --- a/frameworks/core/components/scroll/scroll_controller_base.h +++ b/frameworks/core/components/scroll/scroll_controller_base.h @@ -67,7 +67,9 @@ public: ScrollControllerBase() = default; ~ScrollControllerBase() override = default; - virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::NONE) {} + virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::NONE, + std::optional extraOffset = std::nullopt) + {} virtual void JumpToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false, ScrollAlign align = ScrollAlign::NONE, int32_t source = 3) {} // 3 is SCROLL_FROM_JUMP diff --git a/frameworks/core/components/scroll/scroll_position_controller.cpp b/frameworks/core/components/scroll/scroll_position_controller.cpp index 1a1c1590df5..f71a2ef2fa9 100644 --- a/frameworks/core/components/scroll/scroll_position_controller.cpp +++ b/frameworks/core/components/scroll/scroll_position_controller.cpp @@ -48,7 +48,8 @@ std::string ScrollEventInfo::ToJSONString() const } } -void ScrollPositionController::ScrollToIndex(int32_t index, bool /* smooth */, ScrollAlign /* align */) +void ScrollPositionController::ScrollToIndex( + int32_t index, bool /* smooth */, ScrollAlign /* align */, std::optional /* extraOffset */) { RefPtr node = scroll_.Upgrade(); if (node) { diff --git a/frameworks/core/components/scroll/scroll_position_controller.h b/frameworks/core/components/scroll/scroll_position_controller.h index f30a2cf7cb6..10d7ad6203d 100644 --- a/frameworks/core/components/scroll/scroll_position_controller.h +++ b/frameworks/core/components/scroll/scroll_position_controller.h @@ -109,7 +109,7 @@ public: double GetCurrentPosition() const; Axis GetScrollDirection() const override; - void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) override; + void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) override; void JumpTo(double position); bool AnimateTo(const Dimension& position, float duration, const RefPtr& curve, bool smooth, bool canOverScroll = false) override; diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h index 8f0d6363eab..f27add0135e 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h @@ -354,6 +354,7 @@ struct GridLayoutInfo { int32_t endMainLineIndex_ = 0; int32_t jumpIndex_ = EMPTY_JUMP_INDEX; + std::optional extraOffset_; int32_t crossCount_ = 0; int32_t childrenCount_ = 0; ScrollAlign scrollAlign_ = ScrollAlign::AUTO; diff --git a/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp index e72cecf6267..4d858b97f22 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp @@ -1826,7 +1826,7 @@ Rect GridPattern::GetItemRect(int32_t index) const itemGeometry->GetFrameRect().Width(), itemGeometry->GetFrameRect().Height()); } -void GridPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) +void GridPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) { SetScrollSource(SCROLL_FROM_JUMP); StopAnimate(); @@ -1835,11 +1835,15 @@ void GridPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) int32_t totalChildCount = host->TotalChildCount(); if (((index >= 0) && (index < totalChildCount)) || (index == LAST_ITEM)) { if (smooth) { + SetExtraOffset(extraOffset); targetIndex_ = index; scrollAlign_ = align; host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); } else { UpdateStartIndex(index, align); + if (extraOffset.has_value()) { + gridLayoutInfo_.extraOffset_ = -extraOffset.value(); + } } } FireAndCleanScrollingListener(); @@ -1891,6 +1895,11 @@ bool GridPattern::AnimateToTargetImp(ScrollAlign align, RefPtr extraOffset = std::nullopt) override; void AnimateToTarget(ScrollAlign align, RefPtr& layoutAlgorithmWrapper); bool AnimateToTargetImp(ScrollAlign align, RefPtr& layoutAlgorithmWrapper); diff --git a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp index 1fdf34453dc..3a300b5e061 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp @@ -494,9 +494,7 @@ void GridScrollLayoutAlgorithm::FillGridViewportAndMeasureChildren( CheckReset(mainSize, crossSize, layoutWrapper); - if (gridLayoutInfo_.scrollAlign_ == ScrollAlign::CENTER || gridLayoutInfo_.scrollAlign_ == ScrollAlign::END) { - UpdateCurrentOffsetForJumpTo(mainSize); - } + UpdateCurrentOffsetForJumpTo(mainSize); gridLayoutInfo_.jumpIndex_ = EMPTY_JUMP_INDEX; gridLayoutInfo_.scrollAlign_ = ScrollAlign::AUTO; @@ -1038,21 +1036,28 @@ void GridScrollLayoutAlgorithm::ScrollToIndexStart(LayoutWrapper* layoutWrapper, void GridScrollLayoutAlgorithm::UpdateCurrentOffsetForJumpTo(float mainSize) { - int32_t startLine = 0; - /* targetIndex is in the matrix */ - if (IsIndexInMatrix(gridLayoutInfo_.jumpIndex_, startLine)) { - // scroll to end of the screen - gridLayoutInfo_.currentOffset_ = - mainSize - gridLayoutInfo_.lineHeightMap_[startLine] - gridLayoutInfo_.contentEndPadding_; - // scroll to center of the screen - if (gridLayoutInfo_.scrollAlign_ == ScrollAlign::CENTER) { - gridLayoutInfo_.currentOffset_ /= 2; + if (gridLayoutInfo_.scrollAlign_ == ScrollAlign::CENTER || gridLayoutInfo_.scrollAlign_ == ScrollAlign::END) { + int32_t startLine = 0; + /* targetIndex is in the matrix */ + if (IsIndexInMatrix(gridLayoutInfo_.jumpIndex_, startLine)) { + // scroll to end of the screen + gridLayoutInfo_.currentOffset_ = + mainSize - gridLayoutInfo_.lineHeightMap_[startLine] - gridLayoutInfo_.contentEndPadding_; + // scroll to center of the screen + if (gridLayoutInfo_.scrollAlign_ == ScrollAlign::CENTER) { + gridLayoutInfo_.currentOffset_ /= 2; + } + gridLayoutInfo_.prevOffset_ = gridLayoutInfo_.currentOffset_; + } else { + /* targetIndex is out of the matrix */ + TAG_LOGW( + AceLogTag::ACE_GRID, "can not find jumpIndex in Grid Matrix :%{public}d", gridLayoutInfo_.jumpIndex_); } - gridLayoutInfo_.prevOffset_ = gridLayoutInfo_.currentOffset_; - return; } - /* targetIndex is out of the matrix */ - TAG_LOGW(AceLogTag::ACE_GRID, "can not find jumpIndex in Grid Matrix :%{public}d", gridLayoutInfo_.jumpIndex_); + if (gridLayoutInfo_.extraOffset_.has_value()) { + gridLayoutInfo_.currentOffset_ += gridLayoutInfo_.extraOffset_.value(); + gridLayoutInfo_.extraOffset_.reset(); + } } float GridScrollLayoutAlgorithm::MeasureRecordedItems(float mainSize, float crossSize, LayoutWrapper* layoutWrapper) diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp index 29c6b548f87..79db62ac5cf 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp @@ -50,6 +50,10 @@ void GridIrregularLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) gridLayoutInfo_.currentOffset_ = postJumpOffset_; MeasureOnOffset(mainSize); } + if (gridLayoutInfo_.extraOffset_.has_value()) { + gridLayoutInfo_.currentOffset_ += gridLayoutInfo_.extraOffset_.value(); + gridLayoutInfo_.extraOffset_.reset(); + } } else { MeasureOnOffset(mainSize); } diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.cpp b/frameworks/core/components_ng/pattern/list/list_pattern.cpp index 028472df86c..aa238f801df 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.cpp +++ b/frameworks/core/components_ng/pattern/list/list_pattern.cpp @@ -1444,7 +1444,7 @@ void ListPattern::ScrollTo(float position) isScrollEnd_ = true; } -void ListPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) +void ListPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) { SetScrollSource(SCROLL_FROM_JUMP); if (!smooth) { @@ -1454,11 +1454,15 @@ void ListPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) currentDelta_ = 0.0f; smooth_ = smooth; if (smooth_) { + SetExtraOffset(extraOffset); if (!AnimateToTarget(index, std::nullopt, align)) { targetIndex_ = index; scrollAlign_ = align; } } else { + if (extraOffset.has_value()) { + currentDelta_ = extraOffset.value(); + } jumpIndex_ = index; scrollAlign_ = align; } @@ -1667,6 +1671,11 @@ bool ListPattern::AnimateToTarget(int32_t index, std::optional indexInG } GetListItemAnimatePos(iter->second.startPos, iter->second.endPos, align, targetPos); } + auto extraOffset = GetExtraOffset(); + if (extraOffset.has_value()) { + targetPos += extraOffset.value(); + ResetExtraOffset(); + } if (!NearZero(targetPos)) { AnimateTo(targetPos + currentOffset_, -1, nullptr, true); if (predictSnapOffset_.has_value() && AnimateRunning()) { diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.h b/frameworks/core/components_ng/pattern/list/list_pattern.h index 95fd2c4c013..1ebde134411 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.h +++ b/frameworks/core/components_ng/pattern/list/list_pattern.h @@ -160,7 +160,8 @@ public: // scroller void ScrollTo(float position) override; - void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) override; + void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, + std::optional extraOffset = std::nullopt) override; void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false, ScrollAlign align = ScrollAlign::START); bool CheckTargetValid(int32_t index, int32_t indexInGroup); diff --git a/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.cpp b/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.cpp index 6c3db2eda16..182f4c06211 100644 --- a/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.cpp +++ b/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.cpp @@ -18,7 +18,8 @@ #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" namespace OHOS::Ace::NG { -void ScrollableController::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) +void ScrollableController::ScrollToIndex( + int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) { auto pattern = scroll_.Upgrade(); CHECK_NULL_VOID(pattern); @@ -30,7 +31,7 @@ void ScrollableController::ScrollToIndex(int32_t index, bool smooth, ScrollAlign CHECK_NULL_VOID(host); ACE_SCOPED_TRACE("ScrollToIndex, index:%d, smooth:%u, align:%d, id:%d, tag:%s", index, smooth, align, static_cast(host->GetAccessibilityId()), host->GetTag().c_str()); - pattern->ScrollToIndex(index, smooth, align); + pattern->ScrollToIndex(index, smooth, align, extraOffset); } bool ScrollableController::AnimateTo( diff --git a/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.h b/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.h index 64ab39b270a..a8e49ef678c 100644 --- a/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.h +++ b/frameworks/core/components_ng/pattern/scrollable/scrollable_controller.h @@ -37,7 +37,7 @@ public: { return scroll_; } - void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) override; + void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) override; bool AnimateTo(const Dimension& position, float duration, const RefPtr& curve, bool smooth, bool canOverScroll = false) override; Offset GetCurrentOffset() const override; diff --git a/frameworks/core/components_ng/pattern/scrollable/scrollable_pattern.h b/frameworks/core/components_ng/pattern/scrollable/scrollable_pattern.h index e2340077249..bb96c0fb7ae 100644 --- a/frameworks/core/components_ng/pattern/scrollable/scrollable_pattern.h +++ b/frameworks/core/components_ng/pattern/scrollable/scrollable_pattern.h @@ -426,7 +426,24 @@ public: return ScrollAlign::START; } - virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) {} + virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, + std::optional extraOffset = std::nullopt) + {} + + void SetExtraOffset(std::optional extraOffset) + { + extraOffset_ = extraOffset; + } + + std::optional GetExtraOffset() const + { + return extraOffset_; + } + + void ResetExtraOffset() + { + extraOffset_.reset(); + } virtual void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth); @@ -820,6 +837,7 @@ private: float currentVelocity_ = 0.0f; float lastPosition_ = 0.0f; float finalPosition_ = 0.0f; + std::optional extraOffset_; RefPtr hotzoneAnimator_; float lastHonezoneOffsetPct_ = 0.0f; diff --git a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_algorithm.cpp index 37eaa1136bd..304487425e4 100644 --- a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_algorithm.cpp @@ -339,6 +339,10 @@ void WaterFlowLayoutAlgorithm::FillViewport(float mainSize, LayoutWrapper* layou layoutInfo_->align_ = ScrollAlign::START; layoutInfo_->jumpIndex_ = EMPTY_JUMP_INDEX; layoutInfo_->itemStart_ = false; + if (layoutInfo_->extraOffset_.has_value()) { + layoutInfo_->currentOffset_ += layoutInfo_->extraOffset_.value(); + layoutInfo_->extraOffset_.reset(); + } } position = GetItemPosition(++currentIndex); fill = true; diff --git a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_info.cpp b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_info.cpp index f97150b944e..ae80ccead6a 100644 --- a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_info.cpp +++ b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_layout_info.cpp @@ -553,6 +553,10 @@ float WaterFlowLayoutInfo::JumpToTargetAlign(const std::pair& item void WaterFlowLayoutInfo::JumpTo(const std::pair& item) { currentOffset_ = JumpToTargetAlign(item); + if (extraOffset_.has_value()) { + currentOffset_ += extraOffset_.value(); + extraOffset_.reset(); + } align_ = ScrollAlign::START; jumpIndex_ = EMPTY_JUMP_INDEX; } diff --git a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_segmented_layout.cpp b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_segmented_layout.cpp index aa72873c842..df05fff2c61 100644 --- a/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_segmented_layout.cpp +++ b/frameworks/core/components_ng/pattern/waterflow/layout/top_down/water_flow_segmented_layout.cpp @@ -336,6 +336,10 @@ void WaterFlowSegmentedLayout::MeasureOnJump(int32_t jumpIdx) info_->align_ = TransformAutoScroll(item); } info_->currentOffset_ = SolveJumpOffset(item) + postJumpOffset_; + if (info_->extraOffset_.has_value()) { + info_->currentOffset_ += info_->extraOffset_.value(); + info_->extraOffset_.reset(); + } Fill(jumpIdx); info_->Sync(mainSize_, false); diff --git a/frameworks/core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h b/frameworks/core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h index 934b76e3009..c294ed27c56 100644 --- a/frameworks/core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h +++ b/frameworks/core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h @@ -155,6 +155,7 @@ public: int32_t jumpIndex_ = EMPTY_JUMP_INDEX; ScrollAlign align_ = ScrollAlign::START; std::optional targetIndex_; + std::optional extraOffset_; int32_t startIndex_ = 0; int32_t endIndex_ = -1; diff --git a/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.cpp b/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.cpp index 61ecf84078e..3ad0448e883 100644 --- a/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.cpp +++ b/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.cpp @@ -283,6 +283,11 @@ bool WaterFlowPattern::ScrollToTargetIndex(int32_t index) return false; } float targetPosition = layoutInfo_->CalcTargetPosition(index, crossIndex); + auto extraOffset = GetExtraOffset(); + if (extraOffset.has_value()) { + targetPosition += extraOffset.value(); + ResetExtraOffset(); + } ScrollablePattern::AnimateTo(targetPosition, -1, nullptr, true); return true; } @@ -496,13 +501,14 @@ void WaterFlowPattern::ResetSections() MarkDirtyNodeSelf(); } -void WaterFlowPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) +void WaterFlowPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) { SetScrollSource(SCROLL_FROM_JUMP); SetScrollAlign(align); StopAnimate(); if ((index >= 0) || (index == LAST_ITEM)) { if (smooth) { + SetExtraOffset(extraOffset); if (!ScrollToTargetIndex(index)) { targetIndex_ = index; auto host = GetHost(); @@ -511,6 +517,9 @@ void WaterFlowPattern::ScrollToIndex(int32_t index, bool smooth, ScrollAlign ali } } else { UpdateStartIndex(index); + if (extraOffset.has_value()) { + layoutInfo_->extraOffset_ = -extraOffset.value(); + } } } FireAndCleanScrollingListener(); diff --git a/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.h b/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.h index 6153fae0210..7b3f5194cb0 100644 --- a/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.h +++ b/frameworks/core/components_ng/pattern/waterflow/water_flow_pattern.h @@ -117,7 +117,8 @@ public: void ScrollPage(bool reverse, bool smooth = false) override; - void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) override; + void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, + std::optional extraOffset = std::nullopt) override; double GetStoredOffset() const { diff --git a/frameworks/core/components_v2/grid/grid_position_controller.cpp b/frameworks/core/components_v2/grid/grid_position_controller.cpp index e80d0f27d81..c9cc82858d8 100644 --- a/frameworks/core/components_v2/grid/grid_position_controller.cpp +++ b/frameworks/core/components_v2/grid/grid_position_controller.cpp @@ -19,7 +19,8 @@ namespace OHOS::Ace::V2 { -void GridPositionController::ScrollToIndex(int32_t index, bool /* smooth */, ScrollAlign /* align */) +void GridPositionController::ScrollToIndex( + int32_t index, bool /* smooth */, ScrollAlign /* align */, std::optional /* extraOffset */) { auto grid = AceType::DynamicCast(scroll_.Upgrade()); if (!grid) { diff --git a/frameworks/core/components_v2/grid/grid_position_controller.h b/frameworks/core/components_v2/grid/grid_position_controller.h index 08b1ebf2fa4..3c3fd5dde0a 100644 --- a/frameworks/core/components_v2/grid/grid_position_controller.h +++ b/frameworks/core/components_v2/grid/grid_position_controller.h @@ -28,7 +28,8 @@ public: ~GridPositionController() override = default; Axis GetScrollDirection() const override; - void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) override; + void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, + std::optional extraOffset = std::nullopt) override; bool AnimateTo(const Dimension& position, float duration, const RefPtr& curve, bool smooth, bool canOverScroll = false) override; void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth) override; diff --git a/frameworks/core/components_v2/list/list_position_controller.cpp b/frameworks/core/components_v2/list/list_position_controller.cpp index 9cdc46403f3..7e9f1d08921 100644 --- a/frameworks/core/components_v2/list/list_position_controller.cpp +++ b/frameworks/core/components_v2/list/list_position_controller.cpp @@ -19,7 +19,8 @@ namespace OHOS::Ace::V2 { -void ListPositionController::ScrollToIndex(int32_t index, bool /* smooth */, ScrollAlign /* align */) +void ListPositionController::ScrollToIndex( + int32_t index, bool /* smooth */, ScrollAlign /* align */, std::optional /* extraOffset */) { auto list = AceType::DynamicCast(scroll_.Upgrade()); if (!list) { diff --git a/frameworks/core/components_v2/list/list_position_controller.h b/frameworks/core/components_v2/list/list_position_controller.h index 58124b9f129..317dcc2a88c 100644 --- a/frameworks/core/components_v2/list/list_position_controller.h +++ b/frameworks/core/components_v2/list/list_position_controller.h @@ -27,7 +27,8 @@ public: ListPositionController() = default; ~ListPositionController() override = default; - void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) override; + void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, + std::optional extraOffset = std::nullopt) override; bool AnimateTo(const Dimension& position, float duration, const RefPtr& curve, bool smooth, bool canOverScroll = false) override; Axis GetScrollDirection() const override; diff --git a/frameworks/core/components_v2/water_flow/water_flow_position_controller.cpp b/frameworks/core/components_v2/water_flow/water_flow_position_controller.cpp index 943fa6b5417..2490dd14ca5 100644 --- a/frameworks/core/components_v2/water_flow/water_flow_position_controller.cpp +++ b/frameworks/core/components_v2/water_flow/water_flow_position_controller.cpp @@ -19,7 +19,8 @@ #include "core/components_v2/water_flow/water_flow_scroll_controller.h" namespace OHOS::Ace::V2 { -void WaterFlowPositionController::ScrollToIndex(int32_t index, bool /* smooth */, ScrollAlign /* align */) +void WaterFlowPositionController::ScrollToIndex( + int32_t index, bool /* smooth */, ScrollAlign /* align */, std::optional /* extraOffset */) { auto waterFlow = AceType::DynamicCast(scroll_.Upgrade()); if (!waterFlow) { diff --git a/frameworks/core/components_v2/water_flow/water_flow_position_controller.h b/frameworks/core/components_v2/water_flow/water_flow_position_controller.h index 85178e17c11..1608e1e59fb 100644 --- a/frameworks/core/components_v2/water_flow/water_flow_position_controller.h +++ b/frameworks/core/components_v2/water_flow/water_flow_position_controller.h @@ -28,7 +28,7 @@ public: ~WaterFlowPositionController() override = default; Axis GetScrollDirection() const override; - void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align) override; + void ScrollToIndex(int32_t index, bool smooth, ScrollAlign align, std::optional extraOffset) override; private: ACE_DISALLOW_COPY_AND_MOVE(WaterFlowPositionController); diff --git a/frameworks/core/interfaces/native/node/scroller_modifier.cpp b/frameworks/core/interfaces/native/node/scroller_modifier.cpp index db78e579c7e..31e281f7c2b 100644 --- a/frameworks/core/interfaces/native/node/scroller_modifier.cpp +++ b/frameworks/core/interfaces/native/node/scroller_modifier.cpp @@ -42,7 +42,7 @@ void SetScrollToIndex(ArkUINodeHandle node, ArkUI_Int32 index, ArkUI_Bool smooth { auto* scrollController = reinterpret_cast(node); CHECK_NULL_VOID(scrollController); - scrollController->ScrollToIndex(index, smooth, static_cast(align)); + scrollController->ScrollToIndex(index, smooth, static_cast(align), std::nullopt); } void ScrollBy(ArkUINodeHandle node, ArkUI_Float32* values, ArkUI_Int32* units) diff --git a/test/unittest/core/pattern/grid/grid_scroller_event_test_ng.cpp b/test/unittest/core/pattern/grid/grid_scroller_event_test_ng.cpp index cc499acec26..df255d0e833 100644 --- a/test/unittest/core/pattern/grid/grid_scroller_event_test_ng.cpp +++ b/test/unittest/core/pattern/grid/grid_scroller_event_test_ng.cpp @@ -1009,7 +1009,7 @@ HWTEST_F(GridScrollerEventTestNg, VerticalGridWithScrollBarWithoutAnimation001, * @tc.expected: Only onScroll call back function should be triggered */ auto controller = pattern_->positionController_; - controller->ScrollToIndex(5, false, ScrollAlign::CENTER); + controller->ScrollToIndex(5, false, ScrollAlign::CENTER, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_TRUE(isOnScrollCallBack); EXPECT_FALSE(isOnScrollStartCallBack); @@ -1066,7 +1066,7 @@ HWTEST_F(GridScrollerEventTestNg, VerticalGridWithScrollBarWithoutAnimation002, * @tc.expected: Only onScroll and onReachEnd should be triggered */ auto controller = pattern_->positionController_; - controller->ScrollToIndex(19, false, ScrollAlign::END); + controller->ScrollToIndex(19, false, ScrollAlign::END, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_TRUE(isOnScrollCallBack); EXPECT_FALSE(isOnScrollStartCallBack); @@ -1247,7 +1247,7 @@ HWTEST_F(GridScrollerEventTestNg, HorizontalGridWithScrollBarWithoutAnimation001 * @tc.expected: Only onScroll call back function should be triggered */ auto controller = pattern_->positionController_; - controller->ScrollToIndex(5, false, ScrollAlign::CENTER); + controller->ScrollToIndex(5, false, ScrollAlign::CENTER, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_TRUE(isOnScrollCallBack); EXPECT_FALSE(isOnScrollStartCallBack); @@ -1303,7 +1303,7 @@ HWTEST_F(GridScrollerEventTestNg, HorizontalGridWithScrollBarWithoutAnimation002 * @tc.expected: Only onScroll and onReachEnd should be triggered */ auto controller = pattern_->positionController_; - controller->ScrollToIndex(19, false, ScrollAlign::END); + controller->ScrollToIndex(19, false, ScrollAlign::END, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_TRUE(isOnScrollCallBack); EXPECT_FALSE(isOnScrollStartCallBack); diff --git a/test/unittest/core/pattern/grid/grid_scroller_test_ng.cpp b/test/unittest/core/pattern/grid/grid_scroller_test_ng.cpp index cbc47128354..7af5b39624f 100644 --- a/test/unittest/core/pattern/grid/grid_scroller_test_ng.cpp +++ b/test/unittest/core/pattern/grid/grid_scroller_test_ng.cpp @@ -607,7 +607,7 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateDone(frameNode_); EXPECT_FALSE(pattern_->isConfigScrollable_); auto controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::START); + controller->ScrollToIndex(1, false, ScrollAlign::START, std::nullopt); EXPECT_EQ(pattern_->GetGridLayoutInfo().jumpIndex_, EMPTY_JUMP_INDEX); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); @@ -621,13 +621,13 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateFixedItems(10); CreateDone(frameNode_); controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::START); + controller->ScrollToIndex(1, false, ScrollAlign::START, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(9, false, ScrollAlign::START); + controller->ScrollToIndex(9, false, ScrollAlign::START, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(5, false, ScrollAlign::START); + controller->ScrollToIndex(5, false, ScrollAlign::START, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); @@ -637,13 +637,13 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateFixedItems(10); CreateDone(frameNode_); controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::CENTER); + controller->ScrollToIndex(1, false, ScrollAlign::CENTER, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(6, false, ScrollAlign::CENTER); + controller->ScrollToIndex(6, false, ScrollAlign::CENTER, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(5, false, ScrollAlign::CENTER); + controller->ScrollToIndex(5, false, ScrollAlign::CENTER, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, -100.f); @@ -653,13 +653,13 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateFixedItems(10); CreateDone(frameNode_); controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::END); + controller->ScrollToIndex(1, false, ScrollAlign::END, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(6, false, ScrollAlign::END); + controller->ScrollToIndex(6, false, ScrollAlign::END, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(5, false, ScrollAlign::END); + controller->ScrollToIndex(5, false, ScrollAlign::END, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); @@ -669,13 +669,13 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateFixedItems(10); CreateDone(frameNode_); controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::AUTO); + controller->ScrollToIndex(1, false, ScrollAlign::AUTO, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(6, false, ScrollAlign::AUTO); + controller->ScrollToIndex(6, false, ScrollAlign::AUTO, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(5, false, ScrollAlign::AUTO); + controller->ScrollToIndex(5, false, ScrollAlign::AUTO, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); @@ -685,13 +685,13 @@ HWTEST_F(GridScrollerTestNg, PositionController001, TestSize.Level1) CreateFixedItems(10); CreateDone(frameNode_); controller = pattern_->positionController_; - controller->ScrollToIndex(1, false, ScrollAlign::NONE); + controller->ScrollToIndex(1, false, ScrollAlign::NONE, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(6, false, ScrollAlign::NONE); + controller->ScrollToIndex(6, false, ScrollAlign::NONE, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); - controller->ScrollToIndex(5, false, ScrollAlign::NONE); + controller->ScrollToIndex(5, false, ScrollAlign::NONE, std::nullopt); FlushLayoutTask(frameNode_); EXPECT_EQ(pattern_->GetGridLayoutInfo().currentOffset_, 0); } diff --git a/test/unittest/core/pattern/list/list_scroller_test_ng.cpp b/test/unittest/core/pattern/list/list_scroller_test_ng.cpp index 1f3cbd25a9b..f3462fe7fc6 100644 --- a/test/unittest/core/pattern/list/list_scroller_test_ng.cpp +++ b/test/unittest/core/pattern/list/list_scroller_test_ng.cpp @@ -1077,9 +1077,9 @@ HWTEST_F(ListScrollerTestNg, PositionController001, TestSize.Level1) /** * @tc.steps: step5. Test JumpTo */ - controller->ScrollToIndex(1, false, ScrollAlign::START); + controller->ScrollToIndex(1, false, ScrollAlign::START, std::nullopt); EXPECT_TRUE(IsEqualTotalOffset(ITEM_HEIGHT)); - controller->ScrollToIndex(0, false, ScrollAlign::NONE); + controller->ScrollToIndex(0, false, ScrollAlign::NONE, std::nullopt); EXPECT_TRUE(IsEqualTotalOffset(0)); /** diff --git a/test/unittest/core/pattern/scroll/scroll_controller_test_ng.cpp b/test/unittest/core/pattern/scroll/scroll_controller_test_ng.cpp index bed72631bd4..cf8bdeeb897 100644 --- a/test/unittest/core/pattern/scroll/scroll_controller_test_ng.cpp +++ b/test/unittest/core/pattern/scroll/scroll_controller_test_ng.cpp @@ -31,7 +31,7 @@ HWTEST_F(ScrolleControllerTestNg, ScrollPositionController001, TestSize.Level1) { CreateWithContent(); auto controller = pattern_->GetScrollPositionController(); - controller->ScrollToIndex(1, false, ScrollAlign::START); + controller->ScrollToIndex(1, false, ScrollAlign::START, std::nullopt); /** * @tc.steps: step1. Test AnimateTo @@ -135,7 +135,7 @@ HWTEST_F(ScrolleControllerTestNg, ScrollPositionController002, TestSize.Level1) { CreateWithContent([](ScrollModelNG model) { model.SetAxis(Axis::HORIZONTAL); }); auto controller = pattern_->GetScrollPositionController(); - controller->ScrollToIndex(1, false, ScrollAlign::START); + controller->ScrollToIndex(1, false, ScrollAlign::START, std::nullopt); /** * @tc.steps: step1. Test AnimateTo diff --git a/test/unittest/core/pattern/waterflow/water_flow_scroller_test_ng.cpp b/test/unittest/core/pattern/waterflow/water_flow_scroller_test_ng.cpp index 6a2ee025714..43308ff0438 100644 --- a/test/unittest/core/pattern/waterflow/water_flow_scroller_test_ng.cpp +++ b/test/unittest/core/pattern/waterflow/water_flow_scroller_test_ng.cpp @@ -156,9 +156,9 @@ HWTEST_F(WaterFlowScrollerTestNg, PositionController001, TestSize.Level1) /** * @tc.steps: step2. Test JumpTo func. */ - controller->ScrollToIndex(2, false, ScrollAlign::START); + controller->ScrollToIndex(2, false, ScrollAlign::START, std::nullopt); EXPECT_EQ(pattern_->layoutInfo_->jumpIndex_, 2); - controller->ScrollToIndex(0, false, ScrollAlign::START); + controller->ScrollToIndex(0, false, ScrollAlign::START, std::nullopt); EXPECT_EQ(pattern_->layoutInfo_->jumpIndex_, 0); } -- Gitee