From 1039c545d21882690067fab0e4431ffc2dfa8d5b Mon Sep 17 00:00:00 2001 From: openharmony_ci <120357966@qq.com> Date: Mon, 12 Jun 2023 09:28:41 +0000 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E9=80=80=20'Pull=20Request=20!14524?= =?UTF-8?q?=20:=20=E3=80=90=E5=8A=9F=E8=83=BD=E5=A2=9E=E5=BC=BA=E3=80=91?= =?UTF-8?q?=E5=8F=AF=E6=BB=9A=E5=8A=A8Grid=E6=94=AF=E6=8C=81=E8=B7=A8?= =?UTF-8?q?=E4=B8=BB=E8=BD=B4=E6=96=B9=E5=90=91=E5=B8=83=E5=B1=80'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pattern/grid/grid_layout_info.h | 1 - .../pattern/grid/grid_pattern.cpp | 20 +- .../components_ng/pattern/grid/grid_pattern.h | 3 +- .../grid_scroll_layout_algorithm.cpp | 347 ++++++------------ .../grid_scroll_layout_algorithm.h | 19 +- 5 files changed, 132 insertions(+), 258 deletions(-) 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 2577ad8a80d..4b9c6a49b5a 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h @@ -106,7 +106,6 @@ struct GridLayoutInfo { bool reachStart_ = false; bool offsetEnd_ = false; - int32_t zeroEndLine_ = 0; // Map structure: [mainIndex, [crossIndex, index]], // when vertical, mainIndex is rowIndex and crossIndex is columnIndex. diff --git a/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp index 49f5e29dd27..97c3ce79501 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp @@ -431,9 +431,9 @@ bool GridPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, c const auto& gridLayoutInfo = gridLayoutAlgorithm->GetGridLayoutInfo(); auto eventhub = GetEventHub(); CHECK_NULL_RETURN(eventhub, false); - scrollbarInfo_ = eventhub->FireOnScrollBarUpdate(gridLayoutInfo.startIndex_, gridLayoutInfo.currentOffset_); if (gridLayoutInfo_.startMainLineIndex_ != gridLayoutInfo.startMainLineIndex_) { eventhub->FireOnScrollToIndex(gridLayoutInfo.startIndex_); + scrollbarInfo_ = eventhub->FireOnScrollBarUpdate(gridLayoutInfo.startIndex_, gridLayoutInfo.currentOffset_); FlushFocusOnScroll(gridLayoutInfo); } gridLayoutInfo_ = gridLayoutInfo; @@ -453,11 +453,7 @@ void GridPattern::CheckScrollable() (gridLayoutInfo_.GetTotalHeightOfItemsInView(GetMainGap()) > GetMainContentSize())) { scrollable_ = true; } else { - if (gridLayoutInfo_.startMainLineIndex_ != 0) { - scrollable_ = true; - } else { - scrollable_ = false; - } + scrollable_ = false; } SetScrollEnable(scrollable_); @@ -1026,7 +1022,10 @@ void GridPattern::UpdateScrollBarOffset() auto mainGap = GridUtils::GetMainGap(layoutProperty, viewScopeSize, info.axis_); for (const auto& item : info.lineHeightMap_) { auto line = info.gridMatrix_.find(item.first); - if ((line == info.gridMatrix_.end()) || (line->second.empty())) { + if (line == info.gridMatrix_.end()) { + continue; + } + if (line->second.empty()) { continue; } auto lineStart = line->second.begin()->second; @@ -1045,13 +1044,6 @@ void GridPattern::UpdateScrollBarOffset() } } auto viewSize = geometryNode->GetFrameSize(); - float lineHeight = 0; - if (info.startMainLineIndex_ != 0 && info.startIndex_ == 0) { - for (int32_t lineIndex = info.startMainLineIndex_ - 1; lineIndex >= 0; lineIndex--) { - lineHeight += info.lineHeightMap_.find(lineIndex)->second; - } - offset = lineHeight - info.currentOffset_; - } Size mainSize = { viewSize.Width(), viewSize.Height() }; UpdateScrollBarRegion(offset, estimatedHeight, mainSize, Offset(0.0, 0.0)); } diff --git a/frameworks/core/components_ng/pattern/grid/grid_pattern.h b/frameworks/core/components_ng/pattern/grid/grid_pattern.h index 89d2c9c0fc2..48ec279e95f 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_pattern.h +++ b/frameworks/core/components_ng/pattern/grid/grid_pattern.h @@ -188,7 +188,8 @@ private: void FlushCurrentFocus(); void FlushFocusOnScroll(const GridLayoutInfo& gridLayoutInfo); std::pair IsFirstOrLastFocusableChild(int32_t curMainIndex, int32_t curCrossIndex); - std::pair GetFocusSteps(int32_t curMainIndex, int32_t curCrossIndex, FocusStep step); + std::pair GetFocusSteps( + int32_t curMainIndex, int32_t curCrossIndex, FocusStep step); void InitOnKeyEvent(const RefPtr& focusHub); bool OnKeyEvent(const KeyEvent& event); bool HandleDirectionKey(KeyCode code); 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 feca56387f3..62b98e03ad7 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 @@ -166,6 +166,7 @@ void GridScrollLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) } auto prevLineOffset = axis_ == Axis::VERTICAL ? OffsetF(0.0, prevLineHeight) : OffsetF(prevLineHeight, 0.0); + auto offset = childFrameOffset + prevLineOffset; if (line->second.empty()) { LOGE("line %{public}d should not be empty, please check.", line->first); break; @@ -178,16 +179,12 @@ void GridScrollLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) continue; } itemIdex = iter->second; - auto offset = childFrameOffset + prevLineOffset; - auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(itemIdex); - AdjustRowColSpan(itemWrapper); auto crossIter = itemsCrossPosition_.find(itemIdex); if (crossIter == itemsCrossPosition_.end()) { LOGI("item %{public}d not in cross position", itemIdex); continue; } auto crossOffset = crossIter->second; - offset = CalculateLargeItemOffset(offset, itemIdex, i, iter->first); if (axis_ == Axis::VERTICAL) { offset.SetX(crossOffset); } else { @@ -201,7 +198,7 @@ void GridScrollLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto frSize = itemsCrossSize_.at(iter->first); SizeF blockSize = gridLayoutProperty->IsVertical() ? SizeF(frSize, lineHeight) : SizeF(lineHeight, frSize); auto translate = Alignment::GetAlignPosition( - blockSize, wrapper->GetGeometryNode()->GetMarginFrameSize(), Alignment::TOP_CENTER); + blockSize, wrapper->GetGeometryNode()->GetMarginFrameSize(), Alignment::CENTER); wrapper->GetGeometryNode()->SetMarginFrameOffset(offset + translate); wrapper->Layout(); auto layoutProperty = wrapper->GetLayoutProperty(); @@ -230,7 +227,7 @@ void GridScrollLayoutAlgorithm::InitialItemsCrossSize( crossGap_ = axis_ == Axis::VERTICAL ? columnsGap : rowsGap; auto padding = layoutProperty->CreatePaddingAndBorder(); crossPaddingOffset_ = axis_ == Axis::HORIZONTAL ? padding.top.value_or(0) : padding.left.value_or(0); - + auto crossSize = frameSize.CrossSize(axis_); std::vector crossLens; if (!rowsTemplate.empty()) { @@ -333,7 +330,7 @@ bool GridScrollLayoutAlgorithm::FillBlankAtStart(float mainSize, float crossSize auto blankAtStart = gridLayoutInfo_.currentOffset_; while (GreatNotEqual(blankAtStart, 0.0)) { float lineHeight = FillNewLineForward(crossSize, mainSize, layoutWrapper); - if (GreatOrEqual(lineHeight, 0.0)) { + if (GreatNotEqual(lineHeight, 0.0)) { gridLayoutInfo_.lineHeightMap_[gridLayoutInfo_.startMainLineIndex_] = lineHeight; blankAtStart -= (lineHeight + mainGap_); fillNewLine = true; @@ -401,14 +398,9 @@ void GridScrollLayoutAlgorithm::FillBlankAtEnd( if (mainIter != gridLayoutInfo_.gridMatrix_.end() && mainIter->second.size() < crossCount_ && nextMain == gridLayoutInfo_.gridMatrix_.end()) { auto currentIndex = gridLayoutInfo_.endIndex_ + 1; - cellAveLength_ = -1.0f; - bool hasNormalItem = false; - lastCross_ = 0; + float secondLineHeight = -1.0f; for (uint32_t i = (mainIter->second.empty() ? 0 : mainIter->second.rbegin()->first); i < crossCount_; i++) { // Step1. Get wrapper of [GridItem] - if (currentIndex == 0 && gridLayoutInfo_.startMainLineIndex_ > gridLayoutInfo_.zeroEndLine_) { - continue; - } auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); if (!itemWrapper) { LOGE("GridItem wrapper of index %{public}u null", currentIndex); @@ -416,18 +408,17 @@ void GridScrollLayoutAlgorithm::FillBlankAtEnd( } // Step2. Measure child auto frameSize = axis_ == Axis::VERTICAL ? SizeF(crossSize, mainSize) : SizeF(mainSize, crossSize); - auto childState = MeasureChild(frameSize, currentIndex, layoutWrapper, itemWrapper, false); - if (childState == -1) { - gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = - LessNotEqual(cellAveLength_, 0.0) ? gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_ - 1] - : cellAveLength_; - --currentIndex; - break; - } - i += childState - 1; + i += MeasureChild(frameSize, currentIndex, layoutWrapper, itemWrapper, false); // Step3. Measure [GridItem] - LargeItemLineHeight(itemWrapper, hasNormalItem); - gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = cellAveLength_; + auto itemSize = itemWrapper->GetGeometryNode()->GetMarginFrameSize(); + if (i >= crossCount_) { + secondLineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), secondLineHeight); + mainLength += secondLineHeight; + currentMainLineIndex_++; + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = secondLineHeight; + gridLayoutInfo_.endMainLineIndex_ = currentMainLineIndex_; + } + gridLayoutInfo_.endIndex_ = currentIndex; currentIndex++; } @@ -448,92 +439,6 @@ void GridScrollLayoutAlgorithm::FillBlankAtEnd( gridLayoutInfo_.reachEnd_ = gridLayoutInfo_.endIndex_ == layoutWrapper->GetTotalChildCount() - 1; } -OffsetF GridScrollLayoutAlgorithm::CalculateLargeItemOffset( - OffsetF currOffset, int32_t itemIndex, int32_t currLineIndex, int32_t currentCrossIndex) -{ - OffsetF offset = currOffset; - if (itemIndex == 0) { - for (int32_t lastCrossIndex = currLineIndex; lastCrossIndex > 0; lastCrossIndex--) { - offset -= axis_ == Axis::VERTICAL - ? OffsetF(0, gridLayoutInfo_.lineHeightMap_[lastCrossIndex - 1] + mainGap_) - : OffsetF(gridLayoutInfo_.lineHeightMap_[lastCrossIndex - 1] + mainGap_, 0.0); - } - } else { - for (int32_t lastCrossIndex = currLineIndex; lastCrossIndex > 0; lastCrossIndex--) { - auto lastCrossItem = gridLayoutInfo_.gridMatrix_[lastCrossIndex - 1][currentCrossIndex]; - if (lastCrossItem == itemIndex) { - offset -= axis_ == Axis::VERTICAL - ? OffsetF(0, gridLayoutInfo_.lineHeightMap_[lastCrossIndex - 1] + mainGap_) - : OffsetF(gridLayoutInfo_.lineHeightMap_[lastCrossIndex - 1] + mainGap_, 0.0); - } else { - break; - } - } - } - return offset; -} - -void GridScrollLayoutAlgorithm::AdjustRowColSpan(const RefPtr& itemLayoutWrapper) -{ - auto itemLayoutProperty = DynamicCast(itemLayoutWrapper->GetLayoutProperty()); - bool needAdjust = false; - - currentItemRowSpan_ = 1; - currentItemColSpan_ = 1; - currentItemRowStart_ = -1; - currentItemColStart_ = -1; - currentItemColEnd_ = -1; - currentItemRowEnd_ = -1; - - if (itemLayoutProperty->GetRowStart().has_value()) { - currentItemRowStart_ = itemLayoutProperty->GetRowStart().value_or(-1); - if ((currentItemRowStart_ < 0) || (currentItemRowStart_ >= static_cast(mainCount_))) { - needAdjust = true; - } - } - - if (itemLayoutProperty->GetColumnStart().has_value()) { - currentItemColStart_ = itemLayoutProperty->GetColumnStart().value_or(-1); - if ((currentItemColStart_ < 0) || (currentItemColStart_ >= static_cast(crossCount_))) { - needAdjust = true; - } - } - - if (itemLayoutProperty->GetRowEnd().has_value()) { - currentItemRowEnd_ = itemLayoutProperty->GetRowEnd().value_or(-1); - if ((currentItemRowEnd_ < 0) || (currentItemRowEnd_ >= static_cast(mainCount_))) { - needAdjust = true; - } - } - - if (itemLayoutProperty->GetColumnEnd().has_value()) { - currentItemColEnd_ = itemLayoutProperty->GetColumnEnd().value_or(-1); - if ((currentItemColEnd_ < 0) || (currentItemColEnd_ >= static_cast(crossCount_))) { - needAdjust = true; - } - } - - if (!needAdjust) { - currentItemRowSpan_ = std::max(currentItemRowEnd_ - currentItemRowStart_ + 1, 1); - currentItemColSpan_ = std::max(currentItemColEnd_ - currentItemColStart_ + 1, 1); - } -} - -void GridScrollLayoutAlgorithm::LargeItemLineHeight(const RefPtr& itemWrapper, bool& hasNormalItem) -{ - AdjustRowColSpan(itemWrapper); - auto mainSpan = axis_ == Axis::VERTICAL ? currentItemRowSpan_ : currentItemColSpan_; - auto itemSize = itemWrapper->GetGeometryNode()->GetMarginFrameSize(); - if (mainSpan == 1) { - cellAveLength_ = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), cellAveLength_); - hasNormalItem = true; - } - - if ((mainSpan > 1) && !hasNormalItem) { - cellAveLength_ = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_) / mainSpan, cellAveLength_); - } -} - bool GridScrollLayoutAlgorithm::IsIndexInMatrix(int32_t index, int32_t& startLine) { auto iter = std::find_if(gridLayoutInfo_.gridMatrix_.begin(), gridLayoutInfo_.gridMatrix_.end(), @@ -551,7 +456,7 @@ bool GridScrollLayoutAlgorithm::IsIndexInMatrix(int32_t index, int32_t& startLin void GridScrollLayoutAlgorithm::GetTargetIndexInfoWithBenchMark(LayoutWrapper* layoutWrapper, int32_t targetIndex) { - gridLayoutInfo_.startIndex_ = targetIndex; + gridLayoutInfo_.startIndex_ = GetStartingItem(layoutWrapper, targetIndex); currentMainLineIndex_ = (gridLayoutInfo_.startIndex_ == 0 ? 0 : gridLayoutInfo_.startMainLineIndex_) - 1; gridLayoutInfo_.endIndex_ = gridLayoutInfo_.startIndex_ - 1; gridLayoutInfo_.prevOffset_ = 0; @@ -614,9 +519,6 @@ void GridScrollLayoutAlgorithm::UpdateGridLayoutInfo(LayoutWrapper* layoutWrappe } else { return; } - auto grid = layoutWrapper->GetHostNode(); - CHECK_NULL_VOID(grid); - grid->ChildrenUpdatedFrom(0); GetTargetIndexInfoWithBenchMark(layoutWrapper, targetIndex); moveToEndLineIndex_ = isTargetBackward ? targetIndex : moveToEndLineIndex_; } @@ -642,22 +544,18 @@ bool GridScrollLayoutAlgorithm::UseCurrentLines( while (LessNotEqual(mainLength, mainSize)) { // If [gridMatrix_] does not contain record of line [currentMainLineIndex_], do [FillNewLineBackward] auto gridMatrixIter = gridLayoutInfo_.gridMatrix_.find(++currentMainLineIndex_); - if ((gridMatrixIter == gridLayoutInfo_.gridMatrix_.end()) || - (gridLayoutInfo_.lineHeightMap_.find(currentMainLineIndex_) == gridLayoutInfo_.lineHeightMap_.end())) { + if (gridMatrixIter == gridLayoutInfo_.gridMatrix_.end()) { runOutOfRecord = true; break; } + float lineHeight = -1.0f; int32_t currentIndex = -1; - bool hasNormalItem = false; - cellAveLength_ = -1.0f; for (const auto& gridItemRecord : gridMatrixIter->second) { if (currentIndex == gridItemRecord.second) { continue; } currentIndex = gridItemRecord.second; - if (currentIndex == 0 && gridLayoutInfo_.startMainLineIndex_ > gridLayoutInfo_.zeroEndLine_) { - continue; - } else if (currentIndex == -1) { + if (currentIndex == -1) { // move from another grid continue; } @@ -667,22 +565,17 @@ bool GridScrollLayoutAlgorithm::UseCurrentLines( break; } auto frameSize = axis_ == Axis::VERTICAL ? SizeF(crossSize, mainSize) : SizeF(mainSize, crossSize); - AdjustRowColSpan(itemWrapper); - auto crossStart = axis_ == Axis::VERTICAL ? currentItemColStart_ : currentItemRowStart_; - if (crossStart == -1) { - MeasureChildPlaced(frameSize, currentIndex, gridItemRecord.first, layoutWrapper, itemWrapper); - } else { - MeasureChildPlaced(frameSize, currentIndex, crossStart, layoutWrapper, itemWrapper); - } + MeasureChildPlaced(frameSize, currentIndex, gridItemRecord.first, layoutWrapper, itemWrapper); + auto itemSize = itemWrapper->GetGeometryNode()->GetMarginFrameSize(); + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); // Record end index. When fill new line, the [endIndex_] will be the first item index to request - LargeItemLineHeight(itemWrapper, hasNormalItem); tempEndIndex = std::max(currentIndex, tempEndIndex); gridLayoutInfo_.endIndex_ = tempEndIndex; } - if (GreatOrEqual(cellAveLength_, 0.0)) { // Means at least one item has been measured - gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = cellAveLength_; - mainLength += (gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] + mainGap_); + if (GreatOrEqual(lineHeight, 0.0)) { // Means at least one item has been measured + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = lineHeight; + mainLength += (lineHeight + mainGap_); } // If a line moves up out of viewport, update [startIndex_], [currentOffset_] and [startMainLineIndex_] if (LessNotEqual(mainLength, 0.0)) { @@ -783,8 +676,8 @@ void GridScrollLayoutAlgorithm::SkipBackwardLines(float mainSize, LayoutWrapper* } auto averageHeight = estimatedHeight / gridLayoutInfo_.childrenCount_; int32_t estimatedIndex = (gridLayoutInfo_.currentOffset_) / averageHeight; - gridLayoutInfo_.startIndex_ = - std::min(gridLayoutInfo_.startIndex_ - estimatedIndex, gridLayoutInfo_.childrenCount_); + gridLayoutInfo_.startIndex_ = std::min( + gridLayoutInfo_.startIndex_ - estimatedIndex, gridLayoutInfo_.childrenCount_); gridLayoutInfo_.currentOffset_ = gridLayoutInfo_.prevOffset_; LOGI("estimatedIndex:%{public}d, currentOffset_:%{public}f", gridLayoutInfo_.startIndex_, gridLayoutInfo_.currentOffset_); @@ -798,15 +691,14 @@ float GridScrollLayoutAlgorithm::FillNewLineForward(float crossSize, float mainS // 1. [lineHight] means height of a row when the Grid is vertical; // 2. [lineHight] means width of a column when the Grid is horizontal; // Other params are also named according to this principle. - cellAveLength_ = -1.0f; + float lineHeight = -1.0f; auto currentIndex = gridLayoutInfo_.startIndex_; - bool hasNormalItem = false; // TODO: shoule we use policy of adaptive layout according to size of [GridItem] ? if (gridLayoutInfo_.startMainLineIndex_ - 1 < 0) { if (currentIndex == 0) { LOGI("startMainLineIndex: %{public}d is already the first line, no forward line to make", gridLayoutInfo_.startMainLineIndex_); - return cellAveLength_; + return lineHeight; } // add more than one line UpdateMatrixForAddedItems(); @@ -819,15 +711,12 @@ float GridScrollLayoutAlgorithm::FillNewLineForward(float crossSize, float mainS } gridMatrixIter = gridLayoutInfo_.gridMatrix_.find(gridLayoutInfo_.startMainLineIndex_); if (gridMatrixIter == gridLayoutInfo_.gridMatrix_.end()) { - return cellAveLength_; + return lineHeight; } // need to obtain the item node in order and by step one in LazyLayoutWrapperBuilder::OnGetOrCreateWrapperByIndex for (auto itemIter = gridMatrixIter->second.rbegin(); itemIter != gridMatrixIter->second.rend(); ++itemIter) { currentIndex = itemIter->second; - if (currentIndex == 0 && gridLayoutInfo_.startMainLineIndex_ > gridLayoutInfo_.zeroEndLine_) { - continue; - } // Step1. Get wrapper of [GridItem] auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); @@ -838,23 +727,18 @@ float GridScrollLayoutAlgorithm::FillNewLineForward(float crossSize, float mainS // Step2. Measure child // TODO: need to use [isScrollable_] auto frameSize = axis_ == Axis::VERTICAL ? SizeF(crossSize, mainSize) : SizeF(mainSize, crossSize); - AdjustRowColSpan(itemWrapper); - auto crossStart = axis_ == Axis::VERTICAL ? currentItemColStart_ : currentItemRowStart_; - if (crossStart == -1) { - MeasureChildPlaced(frameSize, currentIndex, itemIter->first, layoutWrapper, itemWrapper); - } else { - MeasureChildPlaced(frameSize, currentIndex, crossStart, layoutWrapper, itemWrapper); - } // Step3. Measure [GridItem] - LargeItemLineHeight(itemWrapper, hasNormalItem); + MeasureChildPlaced(frameSize, currentIndex, itemIter->first, layoutWrapper, itemWrapper); + auto itemSize = itemWrapper->GetGeometryNode()->GetMarginFrameSize(); + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); gridLayoutInfo_.startIndex_ = currentIndex; } - doneCreateNewLine = GreatOrEqual(cellAveLength_, 0.0); + doneCreateNewLine = GreatOrEqual(lineHeight, 0.0); // If it fails to create new line when [FillNewLineForward] is called, it means that it reaches start gridLayoutInfo_.reachStart_ = !doneCreateNewLine; - return cellAveLength_; + return lineHeight; } void GridScrollLayoutAlgorithm::UpdateMatrixForAddedItems() @@ -919,11 +803,12 @@ void GridScrollLayoutAlgorithm::AddForwardLines( gridLayoutInfo_.lineHeightMap_.emplace(forwardLines + i, gridLineHeightMap[i]); } } - gridLayoutInfo_.startMainLineIndex_ = gridLayoutInfo_.startMainLineIndex_ + (forwardLines > 0 ? forwardLines : 0); - gridLayoutInfo_.endMainLineIndex_ = endMainLineIndex + (forwardLines > 0 ? forwardLines : 0); + + gridLayoutInfo_.startMainLineIndex_ = gridLayoutInfo_.endMainLineIndex_ - (forwardLines > 0 ? forwardLines : 0); + gridLayoutInfo_.endMainLineIndex_ = endMainLineIndex + (forwardLines < 0 ? forwardLines : 0); gridLayoutInfo_.endIndex_ = endIndex; - LOGI("after load forward:start main line %{public}d end main line %{public}d, endIndex:%{public}d", - gridLayoutInfo_.startMainLineIndex_, gridLayoutInfo_.endMainLineIndex_, endIndex); + LOGI("after load forward:start main line %{public}d end main line %{public}d", gridLayoutInfo_.startMainLineIndex_, + gridLayoutInfo_.endMainLineIndex_); } float GridScrollLayoutAlgorithm::FillNewLineBackward( @@ -933,17 +818,17 @@ float GridScrollLayoutAlgorithm::FillNewLineBackward( // 1. [lineHight] means height of a row when the Grid is vertical; // 2. [lineHight] means width of a column when the Grid is horizontal; // Other params are also named according to this principle. - cellAveLength_ = -1.0f; + float lineHeight = -1.0f; if (moveToEndLineIndex_ > 0 && gridLayoutInfo_.endIndex_ >= moveToEndLineIndex_) { LOGI("scroll to end line with index:%{public}d", moveToEndLineIndex_); - return cellAveLength_; + return lineHeight; } auto currentIndex = gridLayoutInfo_.endIndex_ + 1; currentMainLineIndex_++; // if it fails to fill a new line backward, do [currentMainLineIndex_--] - lastCross_ = 0; - - bool hasNormalItem = false; // TODO: shoule we use policy of adaptive layout according to size of [GridItem] ? + bool doneFillLine = false; + bool moreThanOneLine = false; + float secondLineHeight = -1.0f; for (uint32_t i = 0; i < crossCount_; i++) { // already finish first line forward @@ -954,45 +839,46 @@ float GridScrollLayoutAlgorithm::FillNewLineBackward( auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); if (!itemWrapper) { LOGE("GridItem wrapper of index %{public}u null", currentIndex); - LargeItemNextLineHeight(currentMainLineIndex_, layoutWrapper); break; } // Step2. Measure child auto frameSize = axis_ == Axis::VERTICAL ? SizeF(crossSize, mainSize) : SizeF(mainSize, crossSize); auto crossSpan = MeasureChild(frameSize, currentIndex, layoutWrapper, itemWrapper, false); - if (crossSpan == -1) { - cellAveLength_ = LessNotEqual(cellAveLength_, 0.0) - ? gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_ - 1] - : cellAveLength_; - --currentIndex; - break; + if (crossSpan < 0) { + // try next item + LOGI("skip item too big to be placed, %{public}u", i); + --i; + ++currentIndex; + continue; + } + i += crossSpan; + // Step3. Measure [GridItem] + auto itemSize = itemWrapper->GetGeometryNode()->GetMarginFrameSize(); + if (i >= crossCount_) { + moreThanOneLine = true; + secondLineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), secondLineHeight); + } else { + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); } - i += crossSpan - 1; - LargeItemLineHeight(itemWrapper, hasNormalItem); + gridLayoutInfo_.endIndex_ = currentIndex; currentIndex++; + doneFillLine = true; } - gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = cellAveLength_; - gridLayoutInfo_.endMainLineIndex_ = currentMainLineIndex_; - return cellAveLength_; -} - -void GridScrollLayoutAlgorithm::LargeItemNextLineHeight(int32_t currentLineIndex, LayoutWrapper* layoutWrapper) -{ - auto gridMatrixIter = gridLayoutInfo_.gridMatrix_.find(currentLineIndex); - bool hasNormalItem = false; - auto currentIndex = 0; - if (gridMatrixIter != gridLayoutInfo_.gridMatrix_.end()) { - for (auto itemIter = gridMatrixIter->second.rbegin(); itemIter != gridMatrixIter->second.rend(); ++itemIter) { - currentIndex = itemIter->second; - auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); - if (!itemWrapper) { - break; - } - LargeItemLineHeight(itemWrapper, hasNormalItem); + if (!doneFillLine) { + // If it fails to fill a new line backward, do [currentMainLineIndex_--] + currentMainLineIndex_--; + } else { + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = lineHeight; + if (moreThanOneLine) { + currentMainLineIndex_ = currentMainLineIndex_ + 1; + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = secondLineHeight; } + + gridLayoutInfo_.endMainLineIndex_ = currentMainLineIndex_; } + return lineHeight; } LayoutConstraintF GridScrollLayoutAlgorithm::CreateChildConstraint(float mainSize, float crossSize, @@ -1035,21 +921,22 @@ LayoutConstraintF GridScrollLayoutAlgorithm::CreateChildConstraint(float mainSiz return itemConstraint; } -bool GridScrollLayoutAlgorithm::GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const +void GridScrollLayoutAlgorithm::GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const { if (!reverse) { ++curCross; if (curCross >= static_cast(crossCount_)) { - return false; + curCross = 0; + ++curMain; } - return true; + return; } --curCross; if (curCross < 0) { - return false; + curCross = static_cast(crossCount_) - 1; + --curMain; } - return true; } int32_t GridScrollLayoutAlgorithm::MeasureChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, @@ -1059,48 +946,50 @@ int32_t GridScrollLayoutAlgorithm::MeasureChild(const SizeF& frameSize, int32_t float crossSize = GetCrossAxisSize(frameSize, gridLayoutInfo_.axis_); auto gridLayoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); CHECK_NULL_RETURN(gridLayoutProperty, 0); + auto childLayoutProperty = DynamicCast(childLayoutWrapper->GetLayoutProperty()); + CHECK_NULL_RETURN(childLayoutProperty, 0); auto mainCount = static_cast(mainCount_); auto crossCount = static_cast(crossCount_); - AdjustRowColSpan(childLayoutWrapper); - if (currentItemRowSpan_ > 1 || currentItemColSpan_ > 1) { + int32_t itemRowStart = childLayoutProperty->GetRowStart().value_or(-1); + int32_t itemColStart = childLayoutProperty->GetColumnStart().value_or(-1); + int32_t itemRowSpan = std::max(childLayoutProperty->GetRowEnd().value_or(-1) - itemRowStart + 1, 1); + int32_t itemColSpan = std::max(childLayoutProperty->GetColumnEnd().value_or(-1) - itemColStart + 1, 1); + if (itemRowSpan > 1 || itemColSpan > 1) { gridLayoutInfo_.hasBigItem_ = true; } - auto crossStart = axis_ == Axis::VERTICAL ? currentItemColStart_ : currentItemRowStart_; - auto mainSpan = axis_ == Axis::VERTICAL ? currentItemRowSpan_ : currentItemColSpan_; - auto crossSpan = axis_ == Axis::VERTICAL ? currentItemColSpan_ : currentItemRowSpan_; + auto mainStart = axis_ == Axis::VERTICAL ? itemRowStart : itemColStart; + auto crossStart = axis_ == Axis::VERTICAL ? itemColStart : itemRowStart; + auto mainSpan = axis_ == Axis::VERTICAL ? itemRowSpan : itemColSpan; + auto crossSpan = axis_ == Axis::VERTICAL ? itemColSpan : itemRowSpan; if (crossSpan > crossCount) { LOGW("item %{public}d can not be placed in grid: cross count:%{public}d, cross span:%{public}d", itemIndex, crossCount, crossSpan); - return crossSpan; + return -1; } - int32_t mainIndex = currentMainLineIndex_; - - if (crossStart >= 0 && crossStart < crossCount) { - if (crossStart < lastCross_) { - return -1; - } else if (CheckGridPlaced(itemIndex, mainIndex, crossStart, mainSpan, crossSpan)) { - childLayoutWrapper->Measure( - CreateChildConstraint(mainSize, crossSize, gridLayoutProperty, crossStart, crossSpan)); - itemsCrossPosition_.try_emplace(itemIndex, ComputeItemCrossPosition(layoutWrapper, crossStart)); - } else { - return -1; - } + if (itemRowStart >= 0 && itemRowStart < mainCount && itemColStart >= 0 && itemColStart < crossCount && + CheckGridPlaced(itemIndex, mainStart, crossStart, mainSpan, crossSpan)) { + childLayoutWrapper->Measure( + CreateChildConstraint(mainSize, crossSize, gridLayoutProperty, crossStart, crossSpan)); + itemsCrossPosition_.try_emplace(itemIndex, ComputeItemCrossPosition(layoutWrapper, crossStart)); } else { - int32_t crossIndex = crossStart >= 0 ? crossStart : lastCross_; + int32_t mainIndex = currentMainLineIndex_; + int32_t crossIndex = 0; while (!CheckGridPlaced(itemIndex, mainIndex, crossIndex, mainSpan, crossSpan)) { - if (GetNextGrid(mainIndex, crossIndex, reverse) == false) { - return -1; - } + GetNextGrid(mainIndex, crossIndex, reverse); if (mainIndex >= mainCount || crossIndex >= crossCount) { break; } } + + if (mainIndex >= mainCount || crossIndex >= crossCount) { + return 0; + } childLayoutWrapper->Measure( CreateChildConstraint(mainSize, crossSize, gridLayoutProperty, crossIndex, crossSpan)); itemsCrossPosition_.try_emplace(itemIndex, ComputeItemCrossPosition(layoutWrapper, crossIndex)); } - return crossSpan; + return crossSpan - 1; } int32_t GridScrollLayoutAlgorithm::MeasureChildPlaced(const SizeF& frameSize, int32_t itemIndex, int32_t crossStart, @@ -1109,11 +998,16 @@ int32_t GridScrollLayoutAlgorithm::MeasureChildPlaced(const SizeF& frameSize, in auto gridLayoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); float mainSize = GetMainAxisSize(frameSize, gridLayoutInfo_.axis_); float crossSize = GetCrossAxisSize(frameSize, gridLayoutInfo_.axis_); - AdjustRowColSpan(childLayoutWrapper); - if (currentItemRowSpan_ > 1 || currentItemColSpan_ > 1) { + auto childLayoutProperty = DynamicCast(childLayoutWrapper->GetLayoutProperty()); + CHECK_NULL_RETURN(childLayoutProperty, 0); + int32_t itemRowStart = childLayoutProperty->GetRowStart().value_or(-1); + int32_t itemColStart = childLayoutProperty->GetColumnStart().value_or(-1); + int32_t itemRowSpan = std::max(childLayoutProperty->GetRowEnd().value_or(-1) - itemRowStart + 1, 1); + int32_t itemColSpan = std::max(childLayoutProperty->GetColumnEnd().value_or(-1) - itemColStart + 1, 1); + if (itemRowSpan > 1 || itemColSpan > 1) { gridLayoutInfo_.hasBigItem_ = true; } - auto crossSpan = axis_ == Axis::VERTICAL ? currentItemColSpan_ : currentItemRowSpan_; + auto crossSpan = axis_ == Axis::VERTICAL ? itemColSpan : itemRowSpan; if (static_cast(crossStart + crossSpan) > crossCount_) { LOGI("item %{public}d cross not enough, start:%{public}d, span:%{public}d", itemIndex, crossStart, crossSpan); return 0; @@ -1156,16 +1050,17 @@ bool GridScrollLayoutAlgorithm::CheckGridPlaced( } // Padding grid matrix for grid item's range. - for (int32_t i = main; i < main + mainSpan; i++) { - for (int32_t j = cross; j < cross + crossSpan; j++) { - gridLayoutInfo_.gridMatrix_[i][j] = index; + for (int32_t i = main; i < main + mainSpan; ++i) { + std::map mainMap; + auto iter = gridLayoutInfo_.gridMatrix_.find(i); + if (iter != gridLayoutInfo_.gridMatrix_.end()) { + mainMap = iter->second; } + for (int32_t j = cross; j < cross + crossSpan; ++j) { + mainMap.emplace(std::make_pair(j, index)); + } + gridLayoutInfo_.gridMatrix_[i] = mainMap; } - if (index == 0) { - gridLayoutInfo_.zeroEndLine_ = main + mainSpan - 1; - } - - lastCross_ = cross + crossSpan; return true; } diff --git a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.h b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.h index 9ce12ed1001..01f9ec87d96 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.h @@ -68,9 +68,8 @@ private: // Compote position of grid item in cross axis. float ComputeItemCrossPosition(LayoutWrapper* layoutWrapper, int32_t crossStart) const; - void LargeItemLineHeight(const RefPtr& itemWrapper, bool& hasNormalItem); // Find next valid cell when current is not valid. - bool GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const; + void GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const; // Find a valid cell to place grid item and save to grid matrix. bool CheckGridPlaced(int32_t index, int32_t main, int32_t cross, int32_t mainSpan, int32_t crossSpan); LayoutConstraintF CreateChildConstraint(float mainSize, float crossSize, @@ -88,20 +87,9 @@ private: int32_t GetStartingItem(LayoutWrapper* layoutWrapper, int32_t currentIndex) const; - OffsetF CalculateLargeItemOffset( - OffsetF currOffset, int32_t itemIndex, int32_t currLineIndex, int32_t currentCrossIndex); - void AdjustRowColSpan(const RefPtr& itemLayoutWrapper); - void LargeItemNextLineHeight(int32_t currentLineIndex, LayoutWrapper* layoutWrapper); - uint32_t crossCount_ = 0; uint32_t mainCount_ = 0; - int32_t currentItemRowSpan_ = 0; - int32_t currentItemColSpan_ = 0; - int32_t currentItemRowStart_ = -1; - int32_t currentItemColStart_ = -1; - int32_t currentItemRowEnd_ = -1; - int32_t currentItemColEnd_ = -1; - int32_t currentMainLineIndex_ = 0; + int32_t currentMainLineIndex_ = 0; // it equals to row index in vertical grid int32_t moveToEndLineIndex_ = -1; // place index in the last line when scroll to index after matrix std::map itemsCrossSize_; // grid item's size in cross axis. Axis axis_ = Axis::VERTICAL; @@ -109,12 +97,11 @@ private: float mainGap_ = 0; float crossGap_ = 0; float crossPaddingOffset_ = 0; - int32_t lastCross_ = 0; // Map structure: [index, crossPosition], store cross position of each item. std::map itemsCrossPosition_; bool canOverScroll_ = false; - float cellAveLength_ = -1.0f; + ACE_DISALLOW_COPY_AND_MOVE(GridScrollLayoutAlgorithm); }; -- Gitee