diff --git a/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp b/frameworks/bridge/declarative_frontend/jsview/js_scroller.cpp index a1ba3f2a98ad9c8bf2cd0efc650c44fe295724d7..652f6c69d6c0cd996df49873f89fd5d4be52648a 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 6c863ef98b99514891b03b02fec1543dbcae95cd..b00e48d5cbf1ff2958afacde15f559d09af6259f 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 8147d1a40dc6dee5f9de65a06f551d3eca864507..2c23312c97ff51519eac2c81997233ae0762b50d 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 b61c95c3294e436d3285dc1f1908d571121cb58c..2855ce69319486f0d30efccbb151c5ab0bf8fbb3 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 91672da7f5f25065464d62b68f8c10a2e6aa6d22..1a8a1b3a967b9429c1ee67935da8c4e85e9abc8f 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 1a1c1590df594b35bc271ad234ca479d09c5db57..f71a2ef2fa957232f40ef8c787a44711240b1970 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 f30a2cf7cb67a24fb8b765c4669d671dc4361ef1..10d7ad6203d41a1a73f6c9da2308e3c7e2fb9a8a 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 8f0d6363eab12a742422247c1f9d009e2d2ce887..f27add0135ee8d80d409bb37dbeb00bc2e504034 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 e72cecf6267c9a6c2ecf1af149d919d392c0a878..4d858b97f226b8211f99325db736daeabc52a969 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 1fdf34453dc905574bf98fe47d4b6f400b5e87ea..3a300b5e061e3e539ccc77d03e9adea70bc68574 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 29c6b548f876e3ed4b70a48f1f15cc8a0ad01e35..79db62ac5cf356e84458935746df099d57d927d8 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 028472df86c23dcc61618068ec516301629e7126..aa238f801df42087d0b1bbc439f70136e20d7e09 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 95fd2c4c0132307a3224e1b9e12e403e9d75bb1a..1ebde1344113baee73d051cda2dab537c8c0ffc3 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 6c3db2eda164268ee1a2259cfeb2f04fa6db6685..182f4c062117ed0bf90b13f4b6048fb8f4d7397d 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 64ab39b270a5d1a00bf154dcd0df241f1ba1801a..a8e49ef678c046d273db587fe67eb8c5d021bb2d 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 e2340077249c46d48eaf1b724f9ab034d1e23945..bb96c0fb7aee062311fd2c1782b5cbd8be75a64c 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 37eaa1136bdc7130513848787b795df2b5537e07..304487425e417da9bcc1b91a438392cdb0c2285d 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 f97150b944ee5da4d7c17f1e49bff3a6c4165a0e..ae80ccead6a5b0b51222ba04e103e58b1ec7ba9e 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 aa72873c842da9b881d307305677df430ab90ccf..df05fff2c61764621f554d7bd60b1e989a4b7d88 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 934b76e30096882fb59f77b66625d1358cc0537b..c294ed27c561f26b0d547cd22267e5ea6fefab77 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 61ecf84078e111223cf7b79e6819c100429e35a2..3ad0448e8830ae73b3f3dc7afd656061ddc459ef 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 6153fae0210ec386ecfa6db6cd9dc98a17959855..7b3f5194cb080d35afa388c2719ce235cc9dfda9 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 e80d0f27d811dff95ba481a3b4487603a8428706..c9cc82858d881edb7940c2befc2f422f99f98d73 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 08b1ebf2fa40aad6a50743bca6f559fe6e748014..3c3fd5dde0a0f692372cd95e5b373d7d24042694 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 9cdc46403f348355798c27b9999ff36e0d782de5..7e9f1d08921d7d2d1e77bb37ff976252c4bef679 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 58124b9f129a1512dcf8e6cfd2e385c5c8ccfd68..317dcc2a88c0b62b785e6283af72be500decf49e 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 943fa6b5417205ef24f221a1c1d22d1fec5e2899..2490dd14ca58a56958457028c0df745a5353c9ac 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 85178e17c11f499e656748f016edf9def3c8d923..1608e1e59fbeb479174c1a87509384d45f0560d1 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 db78e579c7e0b1da0dbcc5ece2a77520699de9ab..31e281f7c2b1d5a859cf8bff78a9758135bc6577 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 cc499acec26ab755d7484b0adb99829cd2a0208a..df255d0e833e7cd25ad7c73d053e6055e011a857 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 cbc47128354dfa6066c0343e6ea152baf6c84b70..7af5b39624fa640dc642d48a52ee7bed74d72135 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 1f3cbd25a9b714707e1c3ed401da10c43ecc5071..f3462fe7fc610ae952ff7e7a5bd290a2d2c4eedf 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 bed72631bd48b0a6973f1299eac86af15cf680c5..cf8bdeeb897202f53ddb94e8c6f76ca2724734cc 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 6a2ee02571406329ffc1e531400d3917fbd8deb0..43308ff04384acacb6d59492ff0da878034644bf 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); }