diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index 73c184613be78ba3a77d4c22c05092b45a32c2b4..73489cdd765ad923e4e3c80092e52e26cbcbe518 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -125,7 +125,7 @@ public: return allFrameNodeChildren_; } - RefPtr FindFrameNodeByIndex(uint32_t index) + RefPtr FindFrameNodeByIndex(uint32_t index, bool needBuild) { while (cursor_ != children_.end()) { if (cursor_->startIndex > index) { @@ -134,8 +134,8 @@ public: } if (cursor_->startIndex + cursor_->count > index) { - auto frameNode = - AceType::DynamicCast(cursor_->node->GetFrameChildByIndex(index - cursor_->startIndex)); + auto frameNode = AceType::DynamicCast( + cursor_->node->GetFrameChildByIndex(index - cursor_->startIndex, needBuild)); return frameNode; } cursor_++; @@ -147,12 +147,12 @@ public: return nullptr; } - RefPtr GetFrameNodeByIndex(uint32_t index) + RefPtr GetFrameNodeByIndex(uint32_t index, bool needBuild) { auto itor = partFrameNodeChildren_.find(index); if (itor == partFrameNodeChildren_.end()) { Build(); - auto child = FindFrameNodeByIndex(index); + auto child = FindFrameNodeByIndex(index, needBuild); if (child) { partFrameNodeChildren_[index] = child; return child; @@ -2418,13 +2418,18 @@ void FrameNode::SyncGeometryNode() RefPtr FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree) { - auto child = frameProxy_->GetFrameNodeByIndex(index); + auto child = frameProxy_->GetFrameNodeByIndex(index, true); if (addToRenderTree && child) { child->SetActive(true); } return child; } +RefPtr FrameNode::GetChildByIndex(uint32_t index) +{ + return frameProxy_->GetFrameNodeByIndex(index, false); +} + const std::list>& FrameNode::GetAllChildrenWithBuild(bool addToRenderTree) { const auto& children = frameProxy_->GetAllFrameChildren(); @@ -2480,7 +2485,7 @@ void FrameNode::MarkNeedSyncRenderTree(bool needRebuild) needSyncRenderTree_ = true; } -RefPtr FrameNode::GetFrameChildByIndex(uint32_t index) +RefPtr FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild) { if (index != 0) { return nullptr; diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index 66ff40a63fe986958738a907ad01acbec244daf6..c68ecce67e2ad134be943fca61f2c44fe73e2f46 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -474,6 +474,7 @@ public: } RefPtr GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree = true) override; + RefPtr GetChildByIndex(uint32_t index) override; const std::list>& GetAllChildrenWithBuild(bool addToRenderTree = true) override; void RemoveChildInRenderTree(uint32_t index) override; void RemoveAllChildInRenderTree() override; @@ -501,7 +502,7 @@ public: int32_t cacheCount = 0, const std::optional& itemConstraint = std::nullopt) override; void SyncGeometryNode(); - RefPtr GetFrameChildByIndex(uint32_t index) override; + RefPtr GetFrameChildByIndex(uint32_t index, bool needBuild) override; bool CheckNeedForceMeasureAndLayout() override; template diff --git a/frameworks/core/components_ng/base/ui_node.cpp b/frameworks/core/components_ng/base/ui_node.cpp index bc02122b00dab2d6600c6d2a3f86fa6d5f4815a7..d3573498e197306138e654cc0fe37baa518db6a1 100644 --- a/frameworks/core/components_ng/base/ui_node.cpp +++ b/frameworks/core/components_ng/base/ui_node.cpp @@ -796,12 +796,12 @@ RefPtr UINode::GetDisappearingChildById(const std::string& id) const return nullptr; } -RefPtr UINode::GetFrameChildByIndex(uint32_t index) +RefPtr UINode::GetFrameChildByIndex(uint32_t index, bool needBuild) { for (const auto& child : children_) { uint32_t count = static_cast(child->FrameCount()); if (count > index) { - return child->GetFrameChildByIndex(index); + return child->GetFrameChildByIndex(index, needBuild); } index -= count; } diff --git a/frameworks/core/components_ng/base/ui_node.h b/frameworks/core/components_ng/base/ui_node.h index 93bcf241cb76595b1d99fba612a86c486116e487..15c893afc3af1d2bc4b9509a5353d39b4d017879 100644 --- a/frameworks/core/components_ng/base/ui_node.h +++ b/frameworks/core/components_ng/base/ui_node.h @@ -352,7 +352,7 @@ public: newChild->MountToParent(AceType::Claim(this), slot, false); } virtual void FastPreviewUpdateChildDone() {} - virtual RefPtr GetFrameChildByIndex(uint32_t index); + virtual RefPtr GetFrameChildByIndex(uint32_t index, bool needBuild); #ifdef PREVIEW void SetDebugLine(const std::string& line) diff --git a/frameworks/core/components_ng/layout/layout_wrapper.h b/frameworks/core/components_ng/layout/layout_wrapper.h index fe47dde165ed4e20f703bd8f6ffd58687e964e8f..e972593d2bd2e670dda8d64bf48544dc4da06af4 100644 --- a/frameworks/core/components_ng/layout/layout_wrapper.h +++ b/frameworks/core/components_ng/layout/layout_wrapper.h @@ -59,6 +59,7 @@ public: virtual const RefPtr& GetLayoutProperty() const = 0; virtual RefPtr GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree = true) = 0; + virtual RefPtr GetChildByIndex(uint32_t index) = 0; virtual const std::list>& GetAllChildrenWithBuild(bool addToRenderTree = true) = 0; virtual void RemoveChildInRenderTree(uint32_t index) = 0; virtual void RemoveAllChildInRenderTree() = 0; diff --git a/frameworks/core/components_ng/layout/layout_wrapper_node.h b/frameworks/core/components_ng/layout/layout_wrapper_node.h index 9a05a156c4615989ff6a78d853c78a133e72c3e1..f5b37ed320fdef55a28f0b0d2b5db5c64a31813a 100644 --- a/frameworks/core/components_ng/layout/layout_wrapper_node.h +++ b/frameworks/core/components_ng/layout/layout_wrapper_node.h @@ -104,6 +104,10 @@ public: // can call the RemoveChildInRenderTree method to explicitly remove the node from the area to be rendered. RefPtr GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree = true) override; const std::list>& GetAllChildrenWithBuild(bool addToRenderTree = true) override; + RefPtr GetChildByIndex(uint32_t index) override + { + return nullptr; + } int32_t GetTotalChildCount() const override { diff --git a/frameworks/core/components_ng/pattern/custom/custom_node.cpp b/frameworks/core/components_ng/pattern/custom/custom_node.cpp index 652267967adda1f07c0e47d6117c4d9620ce520f..6cea54e3103d626f8ffb11553fd34d08275f455d 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node.cpp +++ b/frameworks/core/components_ng/pattern/custom/custom_node.cpp @@ -134,9 +134,9 @@ void CustomNode::MarkNeedSyncRenderTree(bool needRebuild) } } -RefPtr CustomNode::GetFrameChildByIndex(uint32_t index) +RefPtr CustomNode::GetFrameChildByIndex(uint32_t index, bool needBuild) { Render(); - return UINode::GetFrameChildByIndex(index); + return UINode::GetFrameChildByIndex(index, needBuild); } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/custom/custom_node.h b/frameworks/core/components_ng/pattern/custom/custom_node.h index c5d8a5cac3b73f8e6e2a7baa2b8634cd20bf3815..3c8b4472c05d60d3abd5d5692e38523114d09a9f 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node.h +++ b/frameworks/core/components_ng/pattern/custom/custom_node.h @@ -77,7 +77,7 @@ public: } void MarkNeedSyncRenderTree(bool needRebuild = false) override; - RefPtr GetFrameChildByIndex(uint32_t index) override; + RefPtr GetFrameChildByIndex(uint32_t index, bool needBuild) override; void SetJSViewActive(bool active) override; private: diff --git a/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.cpp index 257d337a6d49cf5da296d1f07834f2f7d728b041..ee4a7d0cec81b06ae1e23ab14689247928afc44f 100644 --- a/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.cpp @@ -16,6 +16,7 @@ #include "core/components_ng/pattern/list/list_lanes_layout_algorithm.h" #include "base/utils/utils.h" +#include "core/components_ng/base/frame_node.h" #include "core/components_v2/inspector/inspector_constants.h" namespace OHOS::Ace::NG { @@ -47,8 +48,7 @@ void ListLanesLayoutAlgorithm::UpdateListItemConstraint( } } -float ListLanesLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t childIndex) +float ListLanesLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, int32_t childIndex) { auto wrapper = layoutWrapper->GetOrCreateChildByIndex(childIndex); CHECK_NULL_RETURN(wrapper, 0.0f); @@ -60,14 +60,14 @@ float ListLanesLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWr SetListItemGroupParam(wrapper, 0.0f, true, listLayoutProperty, true); wrapper->Measure(groupLayoutConstraint_); } else { - wrapper->Measure(layoutConstraint); + wrapper->Measure(childLayoutConstraint_); } - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); return mainLen; } int32_t ListLanesLayoutAlgorithm::LayoutALineForward(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t& currentIndex, float startPos, float& endPos) + int32_t& currentIndex, float startPos, float& endPos) { float mainLen = 0.0f; bool isGroup = false; @@ -93,9 +93,9 @@ int32_t ListLanesLayoutAlgorithm::LayoutALineForward(LayoutWrapper* layoutWrappe wrapper->Measure(groupLayoutConstraint_); } else { ACE_SCOPED_TRACE("ListLayoutAlgorithm::MeasureListItem:%d", currentIndex); - wrapper->Measure(layoutConstraint); + wrapper->Measure(childLayoutConstraint_); } - mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis)); + mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_)); if (isGroup) { break; } @@ -110,7 +110,7 @@ int32_t ListLanesLayoutAlgorithm::LayoutALineForward(LayoutWrapper* layoutWrappe } int32_t ListLanesLayoutAlgorithm::LayoutALineBackward(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t& currentIndex, float endPos, float& startPos) + int32_t& currentIndex, float endPos, float& startPos) { float mainLen = 0.0f; bool isGroup = false; @@ -141,9 +141,9 @@ int32_t ListLanesLayoutAlgorithm::LayoutALineBackward(LayoutWrapper* layoutWrapp wrapper->Measure(groupLayoutConstraint_); } else { ACE_SCOPED_TRACE("ListLayoutAlgorithm::MeasureListItem:%d", currentIndex); - wrapper->Measure(layoutConstraint); + wrapper->Measure(childLayoutConstraint_); } - mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis)); + mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_)); if (isGroup || (currentIndex - FindLanesStartIndex(layoutWrapper, currentIndex)) % lanes == 0) { break; } @@ -319,5 +319,115 @@ int32_t ListLanesLayoutAlgorithm::GetLanesFloor(LayoutWrapper* layoutWrapper, in return index; } -void ListLanesLayoutAlgorithm::SetCacheCount(LayoutWrapper* layoutWrapper, int32_t cachedCount) {} +std::list ListLanesLayoutAlgorithm::LayoutCachedALineForward(LayoutWrapper* layoutWrapper, + int32_t& index, float& startPos, float crossSize) +{ + std::list predictBuildList; + ListLayoutAlgorithm::PositionMap posMap; + float mainLen = 0.0f; + bool isGroup = false; + int32_t cnt = 0; + int32_t lanes = lanes_ > 1 ? lanes_ : 1; + for (int32_t i = 0; i < lanes && index + i <= GetMaxListItemIndex(); i++) { + auto wrapper = layoutWrapper->GetChildByIndex(index + i); + if (!wrapper) { + predictBuildList.emplace_back(index + i); + continue; + } + isGroup = wrapper->GetHostTag() == V2::LIST_ITEM_GROUP_ETS_TAG; + if (isGroup && cnt > 0) { + isGroup = false; + break; + } + cnt++; + mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_)); + if (isGroup) { + break; + } + } + if (cnt > 0) { + auto endPos = startPos + mainLen; + for (int32_t i = 0; i < cnt; i++) { + posMap[index + i] = { startPos, endPos, isGroup }; + } + startPos = endPos + GetSpaceWidth(); + auto startIndex = index; + for (const auto& pos: posMap) { + auto wrapper = layoutWrapper->GetChildByIndex(pos.first); + LayoutItem(wrapper, pos.first, pos.second, startIndex, crossSize); + SyncGeometry(wrapper); + wrapper->SetActive(false); + } + } + index += cnt + static_cast(predictBuildList.size()); + return predictBuildList; +} + +std::list ListLanesLayoutAlgorithm::LayoutCachedALineBackward(LayoutWrapper* layoutWrapper, + int32_t& index, float& endPos, float crossSize) +{ + std::list predictBuildList; + ListLayoutAlgorithm::PositionMap posMap; + float mainLen = 0.0f; + bool isGroup = false; + int32_t cnt = 0; + int32_t lanes = lanes_ > 1 ? lanes_ : 1; + for (int32_t i = 0; i < lanes && index >= 0; i++) { + auto idx = index - i; + auto wrapper = layoutWrapper->GetChildByIndex(idx); + if (!wrapper) { + predictBuildList.emplace_back(idx); + continue; + } + isGroup = wrapper->GetHostTag() == V2::LIST_ITEM_GROUP_ETS_TAG; + if (isGroup && cnt > 0) { + isGroup = false; + break; + } + + cnt++; + mainLen = std::max(mainLen, GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_)); + if (isGroup || (idx - FindLanesStartIndex(layoutWrapper, idx)) % lanes == 0) { + break; + } + } + if (cnt > 0) { + auto startPos = endPos - mainLen; + for (int32_t i = 0; i < cnt; i++) { + posMap[index - i] = { startPos, endPos, isGroup }; + } + endPos = startPos - GetSpaceWidth(); + auto startIndex = index - cnt + 1; + for (const auto& pos: posMap) { + auto wrapper = layoutWrapper->GetChildByIndex(pos.first); + LayoutItem(wrapper, pos.first, pos.second, startIndex, crossSize); + SyncGeometry(wrapper); + wrapper->SetActive(false); + } + } + index -= cnt + static_cast(predictBuildList.size()); + return predictBuildList; +} + +std::list ListLanesLayoutAlgorithm::LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount) +{ + std::list predictBuildList; + auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); + float crossSize = GetCrossAxisSize(size, axis_); + + auto itemPosition = GetItemPosition(); + auto currIndex = itemPosition.rbegin()->first + 1; + auto currPos = itemPosition.rbegin()->second.endPos + GetSpaceWidth(); + for (int32_t i = 0; i < cacheCount && currIndex <= GetMaxListItemIndex(); i++) { + auto tmpList = LayoutCachedALineForward(layoutWrapper, currIndex, currPos, crossSize); + predictBuildList.merge(tmpList); + } + currIndex = itemPosition.begin()->first - 1; + currPos = itemPosition.begin()->second.startPos - GetSpaceWidth(); + for (int32_t i = 0; i < cacheCount && currIndex >= 0; i++) { + auto tmpList = LayoutCachedALineBackward(layoutWrapper, currIndex, currPos, crossSize); + predictBuildList.merge(tmpList); + } + return predictBuildList; +} } // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.h b/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.h index 823c24de52a1a9ac731dc740d4547e7c583debab..cfc3ee8bc6a90332ac5dec39167b1c76229bc93b 100644 --- a/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/list/list_lanes_layout_algorithm.h @@ -37,8 +37,7 @@ public: return lanes_; } - float MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t childIndex) override; + float MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, int32_t childIndex) override; static int32_t CalculateLanesParam(std::optional& minLaneLength, std::optional& maxLaneLength, int32_t lanes, std::optional crossSizeOptional, float laneGutter = 0.0f); @@ -46,20 +45,24 @@ public: protected: void UpdateListItemConstraint(Axis axis, const OptionalSizeF& selfIdealSize, LayoutConstraintF& contentConstraint) override; - int32_t LayoutALineForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t& currentIndex, float startPos, float& endPos) override; - int32_t LayoutALineBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t& currentIndex, float endPos, float& startPos) override; + int32_t LayoutALineForward( + LayoutWrapper* layoutWrapper, int32_t& currentIndex, float startPos, float& endPos) override; + int32_t LayoutALineBackward( + LayoutWrapper* layoutWrapper, int32_t& currentIndex, float endPos, float& startPos) override; float CalculateLaneCrossOffset(float crossSize, float childCrossSize) override; void CalculateLanes(const RefPtr& layoutProperty, const LayoutConstraintF& layoutConstraint, std::optional crossSizeOptional, Axis axis) override; int32_t GetLanesFloor(LayoutWrapper* layoutWrapper, int32_t index) override; - void SetCacheCount(LayoutWrapper* layoutWrapper, int32_t cachedCount) override; private: static void ModifyLaneLength( std::optional& minLaneLength, std::optional& maxLaneLength, float crossSize); int32_t FindLanesStartIndex(LayoutWrapper* layoutWrapper, int32_t index); + std::list LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount) override; + std::list LayoutCachedALineForward( + LayoutWrapper* layoutWrapper, int32_t& index, float& startPos, float crossSize); + std::list LayoutCachedALineBackward( + LayoutWrapper* layoutWrapper, int32_t& index, float& endPos, float crossSize); static int32_t FindLanesStartIndex(LayoutWrapper* layoutWrapper, int32_t startIndex, int32_t index); int32_t lanes_ = 1; 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 49b5bd348e6ad30e6efe51a20d941d695846649b..a08480cc03c7eb0d283a18932d0a48c4c0fbb934 100644 --- a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp @@ -23,6 +23,7 @@ #include "base/geometry/ng/size_t.h" #include "base/log/ace_trace.h" #include "base/memory/ace_type.h" +#include "base/utils/time_util.h" #include "base/utils/utils.h" #include "core/components/common/layout/layout_param.h" #include "core/components_ng/base/frame_node.h" @@ -30,6 +31,7 @@ #include "core/components_ng/pattern/list/list_item_group_pattern.h" #include "core/components_ng/pattern/list/list_item_pattern.h" #include "core/components_ng/pattern/list/list_layout_property.h" +#include "core/components_ng/pattern/list/list_pattern.h" #include "core/components_ng/pattern/text_field/text_field_manager.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/measure_property.h" @@ -61,29 +63,29 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) const auto& layoutConstraint = listLayoutProperty->GetLayoutConstraint().value(); // calculate idealSize and set FrameSize - auto axis = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); + axis_ = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); // calculate main size. auto contentConstraint = listLayoutProperty->GetContentLayoutConstraint().value(); auto contentIdealSize = CreateIdealSize( - contentConstraint, axis, listLayoutProperty->GetMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS)); + contentConstraint, axis_, listLayoutProperty->GetMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS)); const auto& padding = listLayoutProperty->CreatePaddingAndBorder(); - paddingBeforeContent_ = axis == Axis::HORIZONTAL ? padding.left.value_or(0) : padding.top.value_or(0); - paddingAfterContent_ = axis == Axis::HORIZONTAL ? padding.right.value_or(0) : padding.bottom.value_or(0); + paddingBeforeContent_ = axis_ == Axis::HORIZONTAL ? padding.left.value_or(0) : padding.top.value_or(0); + paddingAfterContent_ = axis_ == Axis::HORIZONTAL ? padding.right.value_or(0) : padding.bottom.value_or(0); contentMainSize_ = 0.0f; totalItemCount_ = layoutWrapper->GetTotalChildCount(); - if (!GetMainAxisSize(contentIdealSize, axis)) { + if (!GetMainAxisSize(contentIdealSize, axis_)) { if (totalItemCount_ == 0) { contentMainSize_ = 0.0f; } else { // use parent max size first. auto parentMaxSize = contentConstraint.maxSize; - contentMainSize_ = GetMainAxisSize(parentMaxSize, axis) - paddingBeforeContent_ - paddingAfterContent_; + contentMainSize_ = GetMainAxisSize(parentMaxSize, axis_) - paddingBeforeContent_ - paddingAfterContent_; mainSizeIsDefined_ = false; } } else { - contentMainSize_ = GetMainAxisSize(contentIdealSize.ConvertToSizeT(), axis); + contentMainSize_ = GetMainAxisSize(contentIdealSize.ConvertToSizeT(), axis_); mainSizeIsDefined_ = true; } @@ -93,8 +95,8 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) startMainPos_ = currentOffset_; endMainPos_ = currentOffset_ + contentMainSize_; stickyStyle_ = listLayoutProperty->GetStickyStyle().value_or(V2::StickyStyle::NONE); - auto childLayoutConstraint = listLayoutProperty->CreateChildConstraint(); - auto mainPercentRefer = GetMainAxisSize(childLayoutConstraint.percentReference, axis); + childLayoutConstraint_ = listLayoutProperty->CreateChildConstraint(); + auto mainPercentRefer = GetMainAxisSize(childLayoutConstraint_.percentReference, axis_); auto space = listLayoutProperty->GetSpace().value_or(Dimension(0)); spaceWidth_ = ConvertToPx(space, layoutConstraint.scaleProperty, mainPercentRefer).value_or(0); if (GreatOrEqual(spaceWidth_, contentMainSize_)) { @@ -111,28 +113,28 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) } } spaceWidth_ += chainInterval_; - CalculateLanes(listLayoutProperty, layoutConstraint, contentIdealSize.CrossSize(axis), axis); + CalculateLanes(listLayoutProperty, layoutConstraint, contentIdealSize.CrossSize(axis_), axis_); listItemAlign_ = listLayoutProperty->GetListItemAlign().value_or(V2::ListItemAlign::START); // calculate child layout constraint. - UpdateListItemConstraint(axis, contentIdealSize, childLayoutConstraint); - MeasureList(layoutWrapper, childLayoutConstraint, axis); + UpdateListItemConstraint(axis_, contentIdealSize, childLayoutConstraint_); + MeasureList(layoutWrapper); } else { itemPosition_.clear(); layoutWrapper->RemoveAllChildInRenderTree(); LOGI("child size is empty"); } - auto crossSize = contentIdealSize.CrossSize(axis); + auto crossSize = contentIdealSize.CrossSize(axis_); if (crossSize.has_value() && GreaterOrEqualToInfinity(crossSize.value())) { - contentIdealSize.SetCrossSize(GetChildMaxCrossSize(layoutWrapper, axis), axis); + contentIdealSize.SetCrossSize(GetChildMaxCrossSize(layoutWrapper, axis_), axis_); crossMatchChild_ = true; } - contentIdealSize.SetMainSize(contentMainSize_, axis); + contentIdealSize.SetMainSize(contentMainSize_, axis_); AddPaddingToSize(padding, contentIdealSize); layoutWrapper->GetGeometryNode()->SetFrameSize(contentIdealSize.ConvertToSizeT()); // set list cache info. - SetCacheCount(layoutWrapper, listLayoutProperty->GetCachedCountValue(1)); + layoutWrapper->SetCacheCount(0); LOGD("new start index is %{public}d, new end index is %{public}d, offset is %{public}f, mainSize is %{public}f", GetStartIndex(), GetEndIndex(), currentOffset_, contentMainSize_); @@ -213,35 +215,33 @@ void ListLayoutAlgorithm::CalculateEstimateOffset(ScrollAlign align) } } -void ListLayoutAlgorithm::BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis) +void ListLayoutAlgorithm::BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper) { - LayoutForward(layoutWrapper, layoutConstraint, axis, jumpIndex_.value(), startPos); + LayoutForward(layoutWrapper, jumpIndex_.value(), startPos); if (((jumpIndex_.value() > 0) || (!IsScrollSnapAlignCenter(layoutWrapper) && jumpIndex_.value() == 0)) && GreatNotEqual(GetStartPosition(), startMainPos_)) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, jumpIndex_.value() - 1, GetStartPosition()); + LayoutBackward(layoutWrapper, jumpIndex_.value() - 1, GetStartPosition()); if (LessNotEqual(GetEndIndex(), totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { - LayoutForward(layoutWrapper, layoutConstraint, axis, GetEndIndex() + 1, GetEndPosition()); + LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); } } } -void ListLayoutAlgorithm::BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis) +void ListLayoutAlgorithm::BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, jumpIndex_.value(), startPos); + LayoutBackward(layoutWrapper, jumpIndex_.value(), startPos); if (LessOrEqual(jumpIndex_.value(), totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { - LayoutForward(layoutWrapper, layoutConstraint, axis, jumpIndex_.value() + 1, GetEndPosition()); + LayoutForward(layoutWrapper, jumpIndex_.value() + 1, GetEndPosition()); if (Positive(GetStartIndex()) && GreatNotEqual(GetStartPosition(), startMainPos_)) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, GetStartIndex() - 1, GetStartPosition()); + LayoutBackward(layoutWrapper, GetStartIndex() - 1, GetStartPosition()); } } } -void ListLayoutAlgorithm::HandleJumpAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t& startIndex, int32_t& endIndex, float& startPos, float& endPos) +void ListLayoutAlgorithm::HandleJumpAuto(LayoutWrapper* layoutWrapper, + int32_t& startIndex, int32_t& endIndex, float& startPos, float& endPos) { bool isSmoothJump = false; int32_t jumpIndex = 0; @@ -267,57 +267,56 @@ void ListLayoutAlgorithm::HandleJumpAuto(LayoutWrapper* layoutWrapper, const Lay if (!isSmoothJump) { jumpIndex_ = GetLanesFloor(layoutWrapper, jumpIndex_.value()) + GetLanes() - 1; startPos = contentMainSize_; - BeginLayoutBackward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutBackward(startPos, layoutWrapper); } } else if (jumpIndex <= tempStartIndex) { scrollAutoType_ = ScrollAutoType::START; if (!isSmoothJump) { jumpIndex_ = GetLanesFloor(layoutWrapper, jumpIndex_.value()); startPos = 0.0f; - BeginLayoutForward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutForward(startPos, layoutWrapper); } } } else if (jumpIndex <= tempStartIndex) { auto listLayoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); SetListItemGroupParam(wrapper, contentMainSize_, false, listLayoutProperty, false); - wrapper->Measure(layoutConstraint); - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + wrapper->Measure(childLayoutConstraint_); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); if (GreatNotEqual(contentMainSize_, mainLen)) { scrollAutoType_ = ScrollAutoType::START; if (!isSmoothJump) { startPos = 0.0f; - BeginLayoutForward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutForward(startPos, layoutWrapper); } } else { scrollAutoType_ = ScrollAutoType::END; if (!isSmoothJump) { startPos = contentMainSize_; - BeginLayoutBackward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutBackward(startPos, layoutWrapper); } } } else if (jumpIndex >= tempEndIndex) { auto listLayoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); SetListItemGroupParam(wrapper, 0.0f, false, listLayoutProperty, false); - wrapper->Measure(layoutConstraint); - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + wrapper->Measure(childLayoutConstraint_); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); if (GreatOrEqual(mainLen, contentMainSize_)) { scrollAutoType_ = ScrollAutoType::START; if (!isSmoothJump) { startPos = 0.0f; - BeginLayoutForward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutForward(startPos, layoutWrapper); } } else { scrollAutoType_ = ScrollAutoType::END; if (!isSmoothJump) { startPos = contentMainSize_; - BeginLayoutBackward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutBackward(startPos, layoutWrapper); } } } } -void ListLayoutAlgorithm::HandleJumpEnd(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis) +void ListLayoutAlgorithm::HandleJumpEnd(LayoutWrapper* layoutWrapper) { auto wrapper = layoutWrapper->GetOrCreateChildByIndex(jumpIndex_.value()); CHECK_NULL_VOID(wrapper); @@ -325,7 +324,7 @@ void ListLayoutAlgorithm::HandleJumpEnd(LayoutWrapper* layoutWrapper, if (!isGroup) { jumpIndex_ = GetLanesFloor(layoutWrapper, jumpIndex_.value()) + GetLanes() - 1; } - BeginLayoutBackward(contentMainSize_, layoutWrapper, layoutConstraint, axis); + BeginLayoutBackward(contentMainSize_, layoutWrapper); } bool ListLayoutAlgorithm::NoNeedJump(LayoutWrapper* layoutWrapper, float startPos, float endPos, @@ -360,8 +359,7 @@ bool ListLayoutAlgorithm::NoNeedJump(LayoutWrapper* layoutWrapper, float startPo return false; } -float ListLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t childIndex) +float ListLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, int32_t childIndex) { auto wrapper = layoutWrapper->GetOrCreateChildByIndex(childIndex); CHECK_NULL_RETURN(wrapper, 0.0f); @@ -372,13 +370,12 @@ float ListLayoutAlgorithm::MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper // true: layout forward, true: layout all group items. SetListItemGroupParam(wrapper, 0.0f, true, listLayoutProperty, true); } - wrapper->Measure(layoutConstraint); - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + wrapper->Measure(childLayoutConstraint_); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); return mainLen; } -void ListLayoutAlgorithm::MeasureList( - LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis) +void ListLayoutAlgorithm::MeasureList(LayoutWrapper* layoutWrapper) { int32_t startIndex = 0; int32_t endIndex = 0; @@ -419,33 +416,32 @@ void ListLayoutAlgorithm::MeasureList( if (scrollAlign_ == ScrollAlign::START) { startPos = 0.0f; } else { - float mainLen = - MeasureAndGetChildHeight(layoutWrapper, layoutConstraint, axis, jumpIndex_.value()); + float mainLen = MeasureAndGetChildHeight(layoutWrapper, jumpIndex_.value()); startPos = (contentMainSize_ - mainLen) / 2.0f; } - BeginLayoutForward(startPos, layoutWrapper, layoutConstraint, axis); + BeginLayoutForward(startPos, layoutWrapper); break; case ScrollAlign::END: - HandleJumpEnd(layoutWrapper, layoutConstraint, axis); + HandleJumpEnd(layoutWrapper); break; case ScrollAlign::AUTO: - HandleJumpAuto(layoutWrapper, layoutConstraint, axis, startIndex, endIndex, startPos, endPos); + HandleJumpAuto(layoutWrapper, startIndex, endIndex, startPos, endPos); break; } CalculateEstimateOffset(scrollAlign_); } else if (targetIndex_.has_value()) { if (scrollAlign_ == ScrollAlign::AUTO) { - HandleJumpAuto(layoutWrapper, layoutConstraint, axis, startIndex, endIndex, startPos, endPos); + HandleJumpAuto(layoutWrapper, startIndex, endIndex, startPos, endPos); } if (LessOrEqual(startIndex, targetIndex_.value())) { - LayoutForward(layoutWrapper, layoutConstraint, axis, startIndex, startPos); + LayoutForward(layoutWrapper, startIndex, startPos); if (GetStartIndex() > 0 && GreatNotEqual(GetStartPosition(), startMainPos_)) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, GetStartIndex() - 1, GetStartPosition()); + LayoutBackward(layoutWrapper, GetStartIndex() - 1, GetStartPosition()); } } else if (GreatNotEqual(startIndex, targetIndex_.value())) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, endIndex, endPos); + LayoutBackward(layoutWrapper, endIndex, endPos); if (GetEndIndex() < (totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { - LayoutForward(layoutWrapper, layoutConstraint, axis, GetEndIndex() + 1, GetEndPosition()); + LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); } } } else { @@ -456,24 +452,24 @@ void ListLayoutAlgorithm::MeasureList( if ((!overScrollFeature_ && NonNegative(currentOffset_)) || (overScrollFeature_ && overScrollTop)) { startIndex = GetLanesFloor(layoutWrapper, startIndex); - LayoutForward(layoutWrapper, layoutConstraint, axis, startIndex, startPos); + LayoutForward(layoutWrapper, startIndex, startPos); if (GetStartIndex() > 0 && GreatNotEqual(GetStartPosition(), startMainPos_)) { - LayoutBackward(layoutWrapper, layoutConstraint, axis, GetStartIndex() - 1, GetStartPosition()); + LayoutBackward(layoutWrapper, GetStartIndex() - 1, GetStartPosition()); } } else { if (overScrollFeature_ && !overScrollTop && !NearZero(prevContentMainSize_)) { endPos += contentMainSize_ - prevContentMainSize_; } - LayoutBackward(layoutWrapper, layoutConstraint, axis, endIndex, endPos); + LayoutBackward(layoutWrapper, endIndex, endPos); if (GetEndIndex() < (totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) { - LayoutForward(layoutWrapper, layoutConstraint, axis, GetEndIndex() + 1, GetEndPosition()); + LayoutForward(layoutWrapper, GetEndIndex() + 1, GetEndPosition()); } } } } int32_t ListLayoutAlgorithm::LayoutALineForward(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t& currentIndex, float startPos, float& endPos) + int32_t& currentIndex, float startPos, float& endPos) { if (currentIndex + 1 >= totalItemCount_) { return 0; @@ -488,16 +484,16 @@ int32_t ListLayoutAlgorithm::LayoutALineForward(LayoutWrapper* layoutWrapper, } { ACE_SCOPED_TRACE("ListLayoutAlgorithm::MeasureListItem:%d", currentIndex); - wrapper->Measure(layoutConstraint); + wrapper->Measure(childLayoutConstraint_); } - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); endPos = startPos + mainLen; itemPosition_[currentIndex] = { startPos, endPos, isGroup }; return 1; } int32_t ListLayoutAlgorithm::LayoutALineBackward(LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis, int32_t& currentIndex, float endPos, float& startPos) + int32_t& currentIndex, float endPos, float& startPos) { if (currentIndex - 1 < 0) { return 0; @@ -512,16 +508,15 @@ int32_t ListLayoutAlgorithm::LayoutALineBackward(LayoutWrapper* layoutWrapper, } { ACE_SCOPED_TRACE("ListLayoutAlgorithm::MeasureListItem:%d", currentIndex); - wrapper->Measure(layoutConstraint); + wrapper->Measure(childLayoutConstraint_); } - float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); + float mainLen = GetMainAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); startPos = endPos - mainLen; itemPosition_[currentIndex] = { startPos, endPos, isGroup }; return 1; } -void ListLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t startIndex, float startPos) +void ListLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, int32_t startIndex, float startPos) { float currentEndPos = startPos; float currentStartPos = 0.0f; @@ -534,8 +529,7 @@ void ListLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, const Layo auto chainOffset = 0.0f; do { currentStartPos = currentEndPos; - int32_t count = LayoutALineForward(layoutWrapper, layoutConstraint, axis, currentIndex, - currentStartPos, currentEndPos); + int32_t count = LayoutALineForward(layoutWrapper, currentIndex, currentStartPos, currentEndPos); if (count == 0) { break; } @@ -588,7 +582,7 @@ void ListLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, const Layo endMainPos_ = currentEndPos; } if (Negative(currentOffset_) && itemPosition_.begin()->second.isGroup) { - AdjustPostionForListItemGroup(layoutWrapper, axis, GetStartIndex()); + AdjustPostionForListItemGroup(layoutWrapper, axis_, GetStartIndex()); } } @@ -607,8 +601,7 @@ void ListLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, const Layo } } -void ListLayoutAlgorithm::LayoutBackward( - LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis, int32_t endIndex, float endPos) +void ListLayoutAlgorithm::LayoutBackward(LayoutWrapper* layoutWrapper, int32_t endIndex, float endPos) { float currentStartPos = endPos; float currentEndPos = 0.0f; @@ -620,8 +613,7 @@ void ListLayoutAlgorithm::LayoutBackward( auto chainOffset = 0.0f; do { currentEndPos = currentStartPos; - int32_t count = LayoutALineBackward(layoutWrapper, layoutConstraint, axis, currentIndex, - currentEndPos, currentStartPos); + int32_t count = LayoutALineBackward(layoutWrapper, currentIndex, currentEndPos, currentStartPos); if (count == 0) { break; } @@ -820,16 +812,47 @@ void ListLayoutAlgorithm::FixPredictSnapOffsetAlignEnd() predictSnapOffset_ = totalOffset_ - predictEndPos; } +void ListLayoutAlgorithm::LayoutItem(RefPtr& wrapper, int32_t index, const ListItemInfo& pos, + int32_t& startIndex, float crossSize) +{ + CHECK_NULL_VOID(wrapper); + auto offset = paddingOffset_; + float childCrossSize = GetCrossAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis_); + float crossOffset = 0.0f; + if (GetLanes() > 1) { + int32_t laneIndex = 0; + if (pos.isGroup) { + startIndex = index + 1; + } else { + laneIndex = (index - startIndex) % GetLanes(); + } + + float laneGutter = GetLaneGutter(); + crossOffset = CalculateLaneCrossOffset(crossSize, childCrossSize * GetLanes()); + crossOffset += ((crossSize + laneGutter) / GetLanes() - laneGutter) * laneIndex + laneGutter * laneIndex; + } else { + crossOffset = CalculateLaneCrossOffset(crossSize, childCrossSize); + } + auto chainOffset = chainOffsetFunc_ ? chainOffsetFunc_(index) : 0.0f; + if (axis_ == Axis::VERTICAL) { + offset = offset + OffsetF(crossOffset, pos.startPos + chainOffset); + } else { + offset = offset + OffsetF(pos.startPos + chainOffset, crossOffset); + } + wrapper->GetGeometryNode()->SetMarginFrameOffset(offset); + SetListItemIndex(wrapper, index); +} + void ListLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) { auto listLayoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); CHECK_NULL_VOID(listLayoutProperty); - auto axis = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); + auto axis_ = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); auto padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder(); MinusPaddingToSize(padding, size); - auto paddingOffset = padding.Offset(); - float crossSize = GetCrossAxisSize(size, axis); + paddingOffset_ = padding.Offset(); + float crossSize = GetCrossAxisSize(size, axis_); totalItemCount_ = layoutWrapper->GetTotalChildCount(); listItemAlign_ = listLayoutProperty->GetListItemAlign().value_or(V2::ListItemAlign::START); int32_t startIndex = GetStartIndex(); @@ -838,41 +861,23 @@ void ListLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) FixPredictSnapOffset(listLayoutProperty); // layout items. for (auto& pos : itemPosition_) { - int32_t index = pos.first; - auto offset = paddingOffset; - auto wrapper = layoutWrapper->GetOrCreateChildByIndex(index); + auto wrapper = layoutWrapper->GetOrCreateChildByIndex(pos.first); if (!wrapper) { LOGI("wrapper is out of boundary"); continue; } - float childCrossSize = GetCrossAxisSize(wrapper->GetGeometryNode()->GetMarginFrameSize(), axis); - float crossOffset = 0.0f; pos.second.startPos -= currentOffset_; pos.second.endPos -= currentOffset_; - if (GetLanes() > 1) { - int32_t laneIndex = 0; - if (pos.second.isGroup) { - startIndex = index + 1; - } else { - laneIndex = (index - startIndex) % GetLanes(); - } - - float laneGutter = GetLaneGutter(); - crossOffset = CalculateLaneCrossOffset(crossSize, childCrossSize * GetLanes()); - crossOffset += ((crossSize + laneGutter) / GetLanes() - laneGutter) * laneIndex + laneGutter * laneIndex; - } else { - crossOffset = CalculateLaneCrossOffset(crossSize, childCrossSize); - } - auto chainOffset = chainOffsetFunc_ ? chainOffsetFunc_(index) : 0.0f; - if (axis == Axis::VERTICAL) { - offset = offset + OffsetF(crossOffset, pos.second.startPos + chainOffset); - } else { - offset = offset + OffsetF(pos.second.startPos + chainOffset, crossOffset); - } - wrapper->GetGeometryNode()->SetMarginFrameOffset(offset); - SetListItemIndex(wrapper, index); + LayoutItem(wrapper, pos.first, pos.second, startIndex, crossSize); wrapper->Layout(); } + auto cacheCount = listLayoutProperty->GetCachedCountValue(1); + if (!itemPosition_.empty() && cacheCount > 0) { + auto items = LayoutCachedItem(layoutWrapper, cacheCount); + if (!items.empty()) { + PostIdleTask(layoutWrapper->GetHostNode(), { items, childLayoutConstraint_ }); + } + } } float ListLayoutAlgorithm::CalculateLaneCrossOffset(float crossSize, float childCrossSize) @@ -926,11 +931,6 @@ void ListLayoutAlgorithm::OnSurfaceChanged(LayoutWrapper* layoutWrapper) } } -void ListLayoutAlgorithm::SetCacheCount(LayoutWrapper* layoutWrapper, int32_t cachedCount) -{ - layoutWrapper->SetCacheCount(cachedCount); -} - void ListLayoutAlgorithm::SetListItemGroupParam(const RefPtr& layoutWrapper, float referencePos, bool forwardLayout, const RefPtr& layoutProperty, bool groupNeedAllLayout) { @@ -1044,4 +1044,112 @@ int32_t ListLayoutAlgorithm::GetMidIndex() } return totalItemCount_ - 1; } + +void ListLayoutAlgorithm::SyncGeometry(RefPtr& wrapper) +{ + CHECK_NULL_VOID(wrapper); + auto host = wrapper->GetHostNode(); + CHECK_NULL_VOID(host); + auto context = host->GetRenderContext(); + CHECK_NULL_VOID(context); + context->SyncGeometryProperties(AceType::RawPtr(wrapper->GetGeometryNode())); +} + +std::list ListLayoutAlgorithm::LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount) +{ + std::list predictBuildList; + auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); + float crossSize = GetCrossAxisSize(size, axis_); + + auto currIndex = itemPosition_.rbegin()->first + 1; + auto currPos = itemPosition_.rbegin()->second.endPos + spaceWidth_; + for (int32_t i = 0; i < cacheCount && currIndex + i < totalItemCount_; i++) { + int32_t index = currIndex + i; + auto wrapper = layoutWrapper->GetChildByIndex(index); + if (!wrapper) { + predictBuildList.emplace_back(index); + continue; + } + bool isGroup = wrapper->GetHostTag() == V2::LIST_ITEM_GROUP_ETS_TAG; + auto childSize = wrapper->GetGeometryNode()->GetMarginFrameSize(); + auto endPos = currPos + GetMainAxisSize(childSize, axis_); + ListItemInfo pos = { currPos, endPos, isGroup }; + currPos = endPos + spaceWidth_; + auto startIndex = index; + LayoutItem(wrapper, index, pos, startIndex, crossSize); + SyncGeometry(wrapper); + wrapper->SetActive(false); + } + + currIndex = itemPosition_.begin()->first - 1; + currPos = itemPosition_.begin()->second.startPos - spaceWidth_; + for (int32_t i = 0; i < cacheCount && currIndex - i >= 0; i++) { + int32_t index = currIndex - i; + auto wrapper = layoutWrapper->GetChildByIndex(index); + if (!wrapper) { + predictBuildList.emplace_back(index); + continue; + } + bool isGroup = wrapper->GetHostTag() == V2::LIST_ITEM_GROUP_ETS_TAG; + auto childSize = wrapper->GetGeometryNode()->GetMarginFrameSize(); + auto startPos = currPos - GetMainAxisSize(childSize, axis_); + ListItemInfo pos = { startPos, currPos, isGroup }; + currPos = startPos - spaceWidth_; + auto startIndex = index; + LayoutItem(wrapper, index, pos, startIndex, crossSize); + SyncGeometry(wrapper); + wrapper->SetActive(false); + } + return predictBuildList; +} + +void ListLayoutAlgorithm::PredictBuildItem(RefPtr wrapper, const LayoutConstraintF& constraint) +{ + CHECK_NULL_VOID(wrapper); + wrapper->SetActive(false); + bool isGroup = wrapper->GetHostTag() == V2::LIST_ITEM_GROUP_ETS_TAG; + if (!isGroup) { + auto frameNode = wrapper->GetHostNode(); + CHECK_NULL_VOID(frameNode); + frameNode->GetGeometryNode()->SetParentLayoutConstraint(constraint); + FrameNode::ProcessOffscreenNode(frameNode); + } +} + +void ListLayoutAlgorithm::PostIdleTask(RefPtr frameNode, const ListPredictLayoutParam& param) +{ + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + if (pattern->GetPredictLayoutParam()) { + pattern->SetPredictLayoutParam(param); + return; + } + pattern->SetPredictLayoutParam(param); + auto context = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(context); + context->AddPredictTask([frameNode](int64_t deadline, bool canUseLongPredictTask) { + ACE_SCOPED_TRACE("List predict"); + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + if (!pattern->GetPredictLayoutParam().has_value()) { + return; + } + auto param = pattern->GetPredictLayoutParam().value(); + for (auto it = param.items.begin(); it != param.items.end();) { + if (GetSysTimestamp() > deadline) { + break; + } + auto wrapper = frameNode->GetOrCreateChildByIndex(*it, false); + PredictBuildItem(wrapper, param.layoutConstraint); + param.items.erase(it++); + } + pattern->SetPredictLayoutParam(std::nullopt); + if (!param.items.empty()) { + ListLayoutAlgorithm::PostIdleTask(frameNode, param); + pattern->SetPredictLayoutParam(param); + } + }); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.h b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.h index 67f48b2e28935693a008d7ec80799554332efa8c..32fc7acf948e991b781b2dab1aff394462f3f073 100644 --- a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.h @@ -36,6 +36,11 @@ struct ListItemInfo { bool isGroup; }; +struct ListPredictLayoutParam { + std::list items; + LayoutConstraintF layoutConstraint; +}; + enum class ScrollAutoType { NOT_CHANGE = 0, START, @@ -212,27 +217,22 @@ public: void Layout(LayoutWrapper* layoutWrapper) override; - void LayoutForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis, - int32_t startIndex, float startPos); - void LayoutBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis, - int32_t endIndex, float endPos); + void LayoutForward(LayoutWrapper* layoutWrapper, int32_t startIndex, float startPos); + void LayoutBackward(LayoutWrapper* layoutWrapper, int32_t endIndex, float endPos); - void BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis); + void BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper); - void BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper, - const LayoutConstraintF& layoutConstraint, Axis axis); + void BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper); - void HandleJumpAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis, + void HandleJumpAuto(LayoutWrapper* layoutWrapper, int32_t& startIndex, int32_t& endIndex, float& startPos, float& endPos); - void HandleJumpEnd(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis); + void HandleJumpEnd(LayoutWrapper* layoutWrapper); bool NoNeedJump(LayoutWrapper* layoutWrapper, float startPos, float endPos, int32_t startIndex, int32_t endIndex); - virtual float MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t childIndex); + virtual float MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, int32_t childIndex); bool GroupNeedAllLayout() { @@ -263,10 +263,10 @@ public: protected: virtual void UpdateListItemConstraint( Axis axis, const OptionalSizeF& selfIdealSize, LayoutConstraintF& contentConstraint); - virtual int32_t LayoutALineForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t& currentIndex, float startPos, float& endPos); - virtual int32_t LayoutALineBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, - Axis axis, int32_t& currentIndex, float endPos, float& startPos); + virtual int32_t LayoutALineForward( + LayoutWrapper* layoutWrapper, int32_t& currentIndex, float startPos, float& endPos); + virtual int32_t LayoutALineBackward( + LayoutWrapper* layoutWrapper, int32_t& currentIndex, float endPos, float& startPos); virtual float CalculateLaneCrossOffset(float crossSize, float childCrossSize); virtual void CalculateLanes(const RefPtr& layoutProperty, const LayoutConstraintF& layoutConstraint, std::optional crossSizeOptional, Axis axis) {}; @@ -275,7 +275,6 @@ protected: return index; } - virtual void SetCacheCount(LayoutWrapper* layoutWrapper, int32_t cachedCount); void SetListItemGroupParam(const RefPtr& layoutWrapper, float referencePos, bool forwardLayout, const RefPtr& layoutProperty, bool groupNeedAllLayout); static void SetListItemIndex(const RefPtr& layoutWrapper, int32_t index); @@ -286,15 +285,17 @@ protected: { itemPosition_[index] = info; } + void LayoutItem(RefPtr& layoutWrapper, int32_t index, const ListItemInfo& pos, + int32_t& startIndex, float crossSize); + static void SyncGeometry(RefPtr& wrapper); + Axis axis_ = Axis::VERTICAL; + LayoutConstraintF childLayoutConstraint_; private: - void MeasureList(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis); + void MeasureList(LayoutWrapper* layoutWrapper); void CalculateEstimateOffset(ScrollAlign align); - std::pair LayoutOrRecycleCachedItems( - LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, Axis axis); - std::pair RequestNewItemsForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos, Axis axis); @@ -309,6 +310,9 @@ private: void FixPredictSnapOffsetAlignCenter(); void FixPredictSnapOffsetAlignEnd(); bool IsScrollSnapAlignCenter(LayoutWrapper* layoutWrapper); + virtual std::list LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount); + static void PostIdleTask(RefPtr frameNode, const ListPredictLayoutParam& param); + static void PredictBuildItem(RefPtr wrapper, const LayoutConstraintF& constraint); std::optional jumpIndex_; std::optional jumpIndexInGroup_; @@ -344,6 +348,7 @@ private: float paddingBeforeContent_ = 0.0f; float paddingAfterContent_ = 0.0f; float laneGutter_ = 0.0f; + OffsetF paddingOffset_; V2::StickyStyle stickyStyle_ = V2::StickyStyle::NONE; diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.cpp b/frameworks/core/components_ng/pattern/list/list_pattern.cpp index 0480782f934daca7d497ce075142f75952a292b2..357c01cb0ee7415633a04650d09424c8d365b8d4 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.cpp +++ b/frameworks/core/components_ng/pattern/list/list_pattern.cpp @@ -436,9 +436,8 @@ RefPtr ListPattern::CreateLayoutAlgorithm() if (listLayoutProperty->HasLanes() || listLayoutProperty->HasLaneMinLength() || listLayoutProperty->HasLaneMaxLength()) { auto lanesLayoutAlgorithm = MakeRefPtr(); - if ((listLayoutProperty->GetPropertyChangeFlag() & PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT) == 0) { - lanesLayoutAlgorithm->SwapLanesItemRange(lanesItemRange_); - } + RefreshLanesItemRange(); + lanesLayoutAlgorithm->SwapLanesItemRange(lanesItemRange_); lanesLayoutAlgorithm->SetLanes(lanes_); listLayoutAlgorithm.Swap(lanesLayoutAlgorithm); } else { @@ -1692,4 +1691,28 @@ bool ListPattern::IsListItemGroup(int32_t listIndex, RefPtr& node) } return false; } + +void ListPattern::RefreshLanesItemRange() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto updatePos = host->GetChildrenUpdated(); + if (updatePos == -1) { + return; + } + if (updatePos == 0) { + lanesItemRange_.clear(); + return; + } + for (auto it = lanesItemRange_.begin(); it != lanesItemRange_.end();) { + if (it->second < updatePos) { + it++; + } else if (it->first >= updatePos) { + lanesItemRange_.erase(it++); + } else { + it->second = updatePos - 1; + it++; + } + } +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.h b/frameworks/core/components_ng/pattern/list/list_pattern.h index 84338cfe491483861d553a46e1b9fab819273d0c..c855ae8dfcb86d82e524a497fd227b7cee86a51f 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.h +++ b/frameworks/core/components_ng/pattern/list/list_pattern.h @@ -208,6 +208,14 @@ public: int32_t GetItemIndexByPosition(float xOffset, float yOffset); + void SetPredictLayoutParam(std::optional param) + { + predictLayoutParam_ = param; + } + std::optional GetPredictLayoutParam() const + { + return predictLayoutParam_; + } private: void OnScrollEndCallback() override; @@ -257,6 +265,7 @@ private: ListItemGroupPara GetListItemGroupParameter(const RefPtr& node); bool IsListItemGroup(int32_t listIndex, RefPtr& node); void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const; + void RefreshLanesItemRange(); RefPtr listContentModifier_; @@ -308,6 +317,7 @@ private: RefPtr scrollableTouchEvent_; bool isScrollEnd_ = false; + std::optional predictLayoutParam_; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h index 36fb28cd8608da0dc8238a1709c614b0038f1c93..4c39e1d3b68065966a50ac5ef0c2b169f4a52c24 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h +++ b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h @@ -46,7 +46,7 @@ public: return OnGetTotalCount(); } - std::pair> CreateChildByIndex(int32_t index) + std::pair> GetChildByIndex(int32_t index, bool needBuild) { auto keyIter = cachedItems_.find(index); if (keyIter != cachedItems_.end()) { @@ -64,18 +64,20 @@ public: } } } - - ACE_SCOPED_TRACE("Builder:BuildLazyItem [%d]", index); - auto itemInfo = OnGetChildByIndex(index, expiringItem_); - CHECK_NULL_RETURN(itemInfo.second, itemInfo); - { - auto result = generatedItem_.try_emplace(itemInfo.first, itemInfo.second); - if (!result.second) { - LOGD("already has same key %{private}s child", itemInfo.first.c_str()); + if (needBuild) { + ACE_SCOPED_TRACE("Builder:BuildLazyItem [%d]", index); + auto itemInfo = OnGetChildByIndex(index, expiringItem_); + CHECK_NULL_RETURN(itemInfo.second, itemInfo); + { + auto result = generatedItem_.try_emplace(itemInfo.first, itemInfo.second); + if (!result.second) { + LOGD("already has same key %{private}s child", itemInfo.first.c_str()); + } } + cachedItems_[index] = itemInfo.first; + return std::pair>(itemInfo.first, itemInfo.second); } - cachedItems_[index] = itemInfo.first; - return std::pair>(itemInfo.first, itemInfo.second); + return {}; } RefPtr GetChildByKey(const std::string& key) diff --git a/frameworks/core/components_ng/syntax/lazy_for_each_node.cpp b/frameworks/core/components_ng/syntax/lazy_for_each_node.cpp index 050abf256f7aba61a9ab809fe842de4299bb7088..27dacb3fd93025b4776069705b7794b8df9f3dcc 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each_node.cpp +++ b/frameworks/core/components_ng/syntax/lazy_for_each_node.cpp @@ -61,7 +61,7 @@ void LazyForEachNode::AdjustLayoutWrapperTree( void LazyForEachNode::BuildAllChildren() { for (int i = 0; i < FrameCount(); i++) { - GetFrameChildByIndex(i); + GetFrameChildByIndex(i, true); } } @@ -217,10 +217,10 @@ void LazyForEachNode::MarkNeedSyncRenderTree(bool needRebuild) } } -RefPtr LazyForEachNode::GetFrameChildByIndex(uint32_t index) +RefPtr LazyForEachNode::GetFrameChildByIndex(uint32_t index, bool needBuild) { if (index < static_cast(FrameCount())) { - auto child = builder_->CreateChildByIndex(index); + auto child = builder_->GetChildByIndex(index, needBuild); if (child.second) { child.second->SetJSViewActive(true); if (child.second->GetDepth() != GetDepth() + 1) { @@ -233,7 +233,7 @@ RefPtr LazyForEachNode::GetFrameChildByIndex(uint32_t index) child.second->AttachToMainTree(); } PostIdleTask(); - return child.second->GetFrameChildByIndex(0); + return child.second->GetFrameChildByIndex(0, needBuild); } } return nullptr; diff --git a/frameworks/core/components_ng/syntax/lazy_for_each_node.h b/frameworks/core/components_ng/syntax/lazy_for_each_node.h index 83d6b93e6c0749f07ccc5387b005a6814e17237e..c6aa9d6d1374a7c6137843a7c3c1c5621ae842cf 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each_node.h +++ b/frameworks/core/components_ng/syntax/lazy_for_each_node.h @@ -92,7 +92,7 @@ public: void MarkNeedSyncRenderTree(bool needRebuild = false) override; void BuildAllChildren(); - RefPtr GetFrameChildByIndex(uint32_t index) override; + RefPtr GetFrameChildByIndex(uint32_t index, bool needBuild) override; void DoRemoveChildInRenderTree(uint32_t index, bool isAll) override; const std::list>& GetChildren() const override; diff --git a/frameworks/core/components_ng/syntax/lazy_layout_wrapper_builder.cpp b/frameworks/core/components_ng/syntax/lazy_layout_wrapper_builder.cpp index 3734cf61982b532b35fad9b237d3e1cc394870b4..5e09ca1d163bc156de665392e2e3cb80e0e286d0 100644 --- a/frameworks/core/components_ng/syntax/lazy_layout_wrapper_builder.cpp +++ b/frameworks/core/components_ng/syntax/lazy_layout_wrapper_builder.cpp @@ -119,7 +119,7 @@ RefPtr LazyLayoutWrapperBuilder::OnGetOrCreateWrapperByIndexLegac } } // create frame node. - auto itemInfo = builder_->CreateChildByIndex(realIndex); + auto itemInfo = builder_->GetChildByIndex(realIndex, true); id = itemInfo.first; uiNode = itemInfo.second; } @@ -165,7 +165,7 @@ const std::list>& LazyLayoutWrapperBuilder::OnExpandChildL CHECK_NULL_RETURN(builder_, childWrappers_); for (int32_t index = 0; index < total; ++index) { - auto itemInfo = builder_->CreateChildByIndex(index); + auto itemInfo = builder_->GetChildByIndex(index, true); RefPtr wrapper; auto frameNode = DynamicCast(itemInfo.second); auto uiNode = itemInfo.second; diff --git a/frameworks/core/components_ng/test/mock/base/mock_frame_node.cpp b/frameworks/core/components_ng/test/mock/base/mock_frame_node.cpp index 9c0f84cf90936c1c4374fd43bd3d914cd06cf9eb..64f325d4432756349aef7e512e6e7db163c62317 100644 --- a/frameworks/core/components_ng/test/mock/base/mock_frame_node.cpp +++ b/frameworks/core/components_ng/test/mock/base/mock_frame_node.cpp @@ -86,7 +86,7 @@ void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeF void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag) {} void FrameNode::MarkResponseRegion(bool isResponseRegion) {} void FrameNode::MarkNeedSyncRenderTree(bool) {} -RefPtr FrameNode::GetFrameChildByIndex(uint32_t index) +RefPtr FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild) { return nullptr; } @@ -104,6 +104,11 @@ RefPtr FrameNode::GetOrCreateChildByIndex(uint32_t index, bool ad return nullptr; } +RefPtr FrameNode::GetChildByIndex(uint32_t index) +{ + return nullptr; +} + const std::list>& FrameNode::GetAllChildrenWithBuild(bool addToRenderTree) { static std::list> list; diff --git a/frameworks/core/components_ng/test/mock/base/mock_ui_node.cpp b/frameworks/core/components_ng/test/mock/base/mock_ui_node.cpp index 6cfb4fe3fdb46a8f23b9c7820e6f122742f6abcd..c9bd632688042778d06b08a8964b25f8f17ad59f 100644 --- a/frameworks/core/components_ng/test/mock/base/mock_ui_node.cpp +++ b/frameworks/core/components_ng/test/mock/base/mock_ui_node.cpp @@ -159,7 +159,7 @@ RefPtr UINode::GetDisappearingChildById(const std::string& id) const return nullptr; } -RefPtr UINode::GetFrameChildByIndex(uint32_t index) +RefPtr UINode::GetFrameChildByIndex(uint32_t index, bool needBuild) { return nullptr; } diff --git a/frameworks/core/components_ng/test/syntax/lazy_for_each/lazy_for_each_syntax_test_ng.cpp b/frameworks/core/components_ng/test/syntax/lazy_for_each/lazy_for_each_syntax_test_ng.cpp index ece18083bc5ffa1fdeb6f93a391eea0dcacd796e..31e0161ba921e821560cc61ccb9b31aa3a71bbec 100644 --- a/frameworks/core/components_ng/test/syntax/lazy_for_each/lazy_for_each_syntax_test_ng.cpp +++ b/frameworks/core/components_ng/test/syntax/lazy_for_each/lazy_for_each_syntax_test_ng.cpp @@ -80,7 +80,7 @@ public: auto ids = LAZY_FOR_EACH_NODE_IDS; auto builder = AceType::DynamicCast(mockLazyForEachActuator); for (auto iter : LAZY_FOR_EACH_NODE_IDS_INT) { - builder->CreateChildByIndex(iter.value_or(0)); + builder->GetChildByIndex(iter.value_or(0), true); } /**