• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/swiper/swiper_layout_algorithm.h"
17 
18 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
19 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_paint_property.h"
20 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
21 
22 namespace OHOS::Ace::NG {
23 
24 namespace {
25 constexpr Dimension INDICATOR_PADDING = 8.0_vp;
26 constexpr uint32_t INDICATOR_HAS_CHILD = 2;
27 constexpr uint32_t SWIPER_HAS_CHILD = 5;
28 constexpr int32_t DEFAULT_DOUBLE = 2;
29 } // namespace
30 
IndicatorAndArrowMeasure(LayoutWrapper * layoutWrapper,const OptionalSizeF & parentIdealSize)31 void SwiperLayoutAlgorithm::IndicatorAndArrowMeasure(LayoutWrapper* layoutWrapper, const OptionalSizeF& parentIdealSize)
32 {
33     auto property = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
34     CHECK_NULL_VOID(property);
35 
36     // Measure swiper indicator
37     if (property->GetShowIndicatorValue(true)) {
38         auto hostNode = layoutWrapper->GetHostNode();
39         CHECK_NULL_VOID(hostNode);
40         auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
41         CHECK_NULL_VOID(swiperPattern);
42         auto indicatorWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_INDICATOR_ETS_TAG);
43         if (indicatorWrapper) {
44             auto indicatorLayoutConstraint = property->CreateChildConstraint();
45             indicatorLayoutConstraint.parentIdealSize = parentIdealSize;
46             indicatorWrapper->Measure(indicatorLayoutConstraint);
47         }
48     }
49 
50     if (property->GetDisplayArrowValue(false)) {
51         auto hostNode = layoutWrapper->GetHostNode();
52         CHECK_NULL_VOID(hostNode);
53         auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
54         CHECK_NULL_VOID(swiperPattern);
55 
56         if (swiperPattern->HasLeftButtonNode() && swiperPattern->HasRightButtonNode()) {
57             auto leftArrowWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_ARROW_ETS_TAG);
58             auto rightArrowWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_ARROW_ETS_TAG);
59             CHECK_NULL_VOID(leftArrowWrapper);
60             CHECK_NULL_VOID(rightArrowWrapper);
61             if (leftArrowWrapper->GetHostTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG &&
62                 rightArrowWrapper->GetHostTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
63                 MeasureArrow(leftArrowWrapper, property);
64                 MeasureArrow(rightArrowWrapper, property);
65             }
66         }
67     }
68 }
69 
UpdateLayoutInfoBeforeMeasureSwiper(const RefPtr<SwiperLayoutProperty> & property,const LayoutConstraintF & layoutConstraint)70 void SwiperLayoutAlgorithm::UpdateLayoutInfoBeforeMeasureSwiper(
71     const RefPtr<SwiperLayoutProperty>& property, const LayoutConstraintF& layoutConstraint)
72 {
73     if (measured_) {
74         // flex property causes Swiper to be measured twice, and itemPosition_ would
75         // reset after the first measure. Restore to that on second measure.
76         itemPosition_ = prevItemPosition_;
77         // targetIndex_ has also been reset during the first measure.
78         targetIndex_ = currentTargetIndex_;
79         if (duringInteraction_ || NearEqual(oldContentMainSize_, contentMainSize_)) {
80             jumpIndex_ = currentJumpIndex_;
81         }
82         ignoreBlankOffset_ = currentIgnoreBlankOffset_;
83     }
84     currentOffset_ = currentDelta_;
85     startMainPos_ = currentOffset_;
86     ACE_SCOPED_TRACE("measure swiper startMainPos_:%f, jumpIndex_:%d, targetIndex_:%d", startMainPos_,
87         jumpIndex_.value_or(-1), targetIndex_.value_or(-1));
88     if (SwiperUtils::IsStretch(property)) {
89         prevMargin_ = property->GetCalculatedPrevMargin();
90         nextMargin_ = property->GetCalculatedNextMargin();
91         placeItemWidth_ = layoutConstraint.selfIdealSize.MainSize(axis_);
92     }
93     auto itemSpace = SwiperUtils::GetItemSpace(property);
94     spaceWidth_ = itemSpace > (contentMainSize_ + paddingBeforeContent_ + paddingAfterContent_) ? 0.0f : itemSpace;
95     auto prevMargin = NearZero(prevMargin_) ? 0.0f : prevMargin_ + spaceWidth_;
96     auto nextMargin = NearZero(nextMargin_) ? 0.0f : nextMargin_ + spaceWidth_;
97     endMainPos_ = currentOffset_ + contentMainSize_ - prevMargin - nextMargin;
98 
99     prevMarginIgnoreBlank_ = property->GetPrevMarginIgnoreBlank().value_or(false);
100     if (!isLoop_ && jumpIndex_.has_value() && totalItemCount_ > property->GetDisplayCount().value_or(1)) {
101         if (prevMarginIgnoreBlank_ && jumpIndex_.value() == 0) {
102             ignoreBlankOffset_ = Positive(prevMargin_) ? -(prevMargin_ + spaceWidth_) : 0.0f;
103         } else if (property->GetNextMarginIgnoreBlank().value_or(false) &&
104                    jumpIndex_.value() >= (totalItemCount_ - property->GetDisplayCount().value_or(1))) {
105             ignoreBlankOffset_ = Positive(nextMargin_) ? nextMargin_ + spaceWidth_ : 0.0f;
106         } else {
107             ignoreBlankOffset_ = 0.0f;
108         }
109     }
110 }
111 
GetLoopIndex(int32_t originalIndex) const112 int32_t SwiperLayoutAlgorithm::GetLoopIndex(int32_t originalIndex) const
113 {
114     if (totalItemCount_ <= 0) {
115         return originalIndex;
116     }
117     auto loopIndex = originalIndex;
118     while (loopIndex < 0) {
119         loopIndex = loopIndex + totalItemCount_;
120     }
121     loopIndex %= totalItemCount_;
122     return loopIndex;
123 }
124 
Measure(LayoutWrapper * layoutWrapper)125 void SwiperLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
126 {
127     std::lock_guard<std::mutex> lock(swiperMutex_);
128     CHECK_NULL_VOID(layoutWrapper);
129     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
130     CHECK_NULL_VOID(swiperLayoutProperty);
131     if (!measured_) {
132         currentTargetIndex_ = targetIndex_;
133         currentJumpIndex_ = jumpIndex_;
134         currentIgnoreBlankOffset_ = ignoreBlankOffset_;
135     }
136     if (swiperLayoutProperty->GetIsCustomAnimation().value_or(false)) {
137         MeasureTabsCustomAnimation(layoutWrapper);
138         return;
139     }
140 
141     axis_ = swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
142     // calculate main size.
143     auto contentConstraint = swiperLayoutProperty->GetContentLayoutConstraint().value();
144     swiperLayoutProperty->ResetIgnorePrevMarginAndNextMargin();
145     auto isSingleCase = SwiperUtils::CheckIsSingleCase(swiperLayoutProperty);
146     OptionalSizeF contentIdealSize;
147     if (isSingleCase) {
148         contentIdealSize = CreateIdealSizeByPercentRef(contentConstraint, axis_, MeasureType::MATCH_CONTENT);
149         if (mainSizeIsMeasured_) {
150             if (!layoutWrapper->ConstraintChanged()) {
151                 contentIdealSize.SetMainSize(contentMainSize_, axis_);
152             } else {
153                 mainSizeIsMeasured_ = false;
154             }
155         }
156     } else {
157         contentIdealSize = CreateIdealSizeByPercentRef(contentConstraint, axis_, MeasureType::MATCH_PARENT_MAIN_AXIS);
158         if (layoutWrapper->ConstraintChanged()) {
159             mainSizeIsMeasured_ = false;
160             jumpIndex_ = jumpIndex_.value_or(currentIndex_);
161         }
162     }
163 
164     auto mainSize = contentIdealSize.MainSize(axis_);
165     if (mainSize.has_value()) {
166         SwiperUtils::CheckAutoFillDisplayCount(swiperLayoutProperty, mainSize.value(), realTotalCount_);
167     }
168     const auto& padding = swiperLayoutProperty->CreatePaddingAndBorder();
169     paddingBeforeContent_ = axis_ == Axis::HORIZONTAL ? padding.left.value_or(0) : padding.top.value_or(0);
170     paddingAfterContent_ = axis_ == Axis::HORIZONTAL ? padding.right.value_or(0) : padding.bottom.value_or(0);
171     contentMainSize_ = 0.0f;
172     if (!GetMainAxisSize(contentIdealSize, axis_) && (!isSingleCase || !mainSizeIsMeasured_)) {
173         if (totalItemCount_ == 0) {
174             contentMainSize_ = 0.0f;
175         } else {
176             // use parent percentReference size first.
177             auto parentPercentReference = contentConstraint.percentReference;
178             contentMainSize_ =
179                 GetMainAxisSize(parentPercentReference, axis_) - paddingBeforeContent_ - paddingAfterContent_;
180             mainSizeIsDefined_ = false;
181         }
182     } else {
183         contentMainSize_ = GetMainAxisSize(contentIdealSize.ConvertToSizeT(), axis_);
184         mainSizeIsDefined_ = true;
185     }
186 
187     auto hostNode = layoutWrapper->GetHostNode();
188     CHECK_NULL_VOID(hostNode);
189     auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
190     CHECK_NULL_VOID(swiperPattern);
191     auto getAutoFill = swiperPattern->IsAutoFill();
192     // calculate child layout constraint and check if need to reset prevMargin,nextMargin,itemspace.
193     auto childLayoutConstraint =
194         SwiperUtils::CreateChildConstraint(swiperLayoutProperty, contentIdealSize, getAutoFill);
195     childLayoutConstraint_ = childLayoutConstraint;
196     if (totalItemCount_ > 0) {
197         UpdateLayoutInfoBeforeMeasureSwiper(swiperLayoutProperty, childLayoutConstraint);
198         MeasureSwiper(layoutWrapper, childLayoutConstraint);
199     } else {
200         itemPosition_.clear();
201     }
202 
203     auto cachedChildIdealSize = contentIdealSize;
204 
205     auto crossSize = contentIdealSize.CrossSize(axis_);
206     if ((crossSize.has_value() && GreaterOrEqualToInfinity(crossSize.value())) || !crossSize.has_value()) {
207         contentCrossSize_ = GetChildMaxSize(layoutWrapper, false);
208         contentIdealSize.SetCrossSize(contentCrossSize_, axis_);
209         crossMatchChild_ = true;
210     } else {
211         contentCrossSize_ = crossSize.value();
212     }
213 
214     if (!mainSizeIsDefined_ && isSingleCase) {
215         auto childMaxMainSize = GetChildMaxSize(layoutWrapper, true);
216         if (childMaxMainSize != contentMainSize_) {
217             contentMainSize_ = childMaxMainSize;
218             // CheckInactive
219             SetInactive(layoutWrapper, 0.0f, contentMainSize_, currentTargetIndex_);
220         }
221     }
222 
223     if (cachedShow_) {
224         cachedChildIdealSize.SetMainSize(contentMainSize_, axis_);
225         auto cachedChildLayoutConstraint =
226             SwiperUtils::CreateChildConstraint(swiperLayoutProperty, cachedChildIdealSize, getAutoFill);
227         LayoutCachedItem(layoutWrapper, cachedChildLayoutConstraint);
228     }
229 
230     MeasureSwiperCustomAnimation(layoutWrapper, childLayoutConstraint);
231     if (itemPosition_.empty()) {
232         layoutWrapper->SetActiveChildRange(-1, -1);
233     } else if (itemPositionInAnimation_.empty()) {
234         AdjustItemPositionOnCachedShow();
235 
236         int32_t startIndex = GetLoopIndex(GetStartIndex());
237         int32_t endIndex = GetLoopIndex(GetEndIndex());
238         CheckCachedItem(startIndex, endIndex, layoutWrapper);
239         // startIndex maybe target to invalid blank items in group mode, need to be adjusted.
240         startIndex = startIndex < realTotalCount_ ? startIndex : 0;
241         endIndex = std::min(endIndex, realTotalCount_ - 1);
242         if (!isLoop_) {
243             layoutWrapper->SetActiveChildRange(startIndex, endIndex, std::min(cachedCount_, startIndex),
244                 std::min(cachedCount_, totalItemCount_ - 1 - endIndex));
245         } else {
246             layoutWrapper->SetActiveChildRange(startIndex, endIndex, cachedCount_, cachedCount_);
247         }
248     } else {
249         AdjustItemPositionOnCachedShow();
250 
251         int32_t startIndex = std::min(GetLoopIndex(itemPositionInAnimation_.begin()->first), realTotalCount_ - 1);
252         int32_t endIndex = std::min(GetLoopIndex(itemPositionInAnimation_.rbegin()->first), realTotalCount_ - 1);
253         while (startIndex + 1 < realTotalCount_ &&
254             itemPositionInAnimation_.find(startIndex + 1) != itemPositionInAnimation_.end()) {
255             startIndex++;
256         }
257         while (endIndex - 1 >= 0 &&
258             itemPositionInAnimation_.find(endIndex - 1) != itemPositionInAnimation_.end()) {
259             endIndex--;
260         }
261         CheckCachedItem(endIndex, startIndex, layoutWrapper);
262         if (!isLoop_) {
263             layoutWrapper->SetActiveChildRange(endIndex, startIndex, std::min(cachedCount_, endIndex),
264                 std::min(cachedCount_, totalItemCount_ - 1 - startIndex));
265         } else {
266             layoutWrapper->SetActiveChildRange(endIndex, startIndex, cachedCount_, cachedCount_);
267         }
268     }
269 
270     contentIdealSize.SetMainSize(contentMainSize_, axis_);
271     AddPaddingToSize(padding, contentIdealSize);
272     auto geometryNode = layoutWrapper->GetGeometryNode();
273     if (geometryNode) {
274         geometryNode->SetFrameSize(contentIdealSize.ConvertToSizeT());
275     }
276     if (!itemPosition_.empty()) {
277         mainSizeIsMeasured_ = true;
278     }
279 
280     // set swiper cache info.
281     auto measuredItemCount = static_cast<int32_t>(measuredItems_.size());
282     auto maxCachedCount =
283         isLoop_ ? static_cast<int32_t>(std::ceil(static_cast<float>(realTotalCount_ - measuredItemCount) / 2))
284                 : realTotalCount_;
285     auto cachedCount = cachedShow_ ? 0 : std::min(swiperPattern->GetCachedCount(), maxCachedCount);
286     layoutWrapper->SetCacheCount(cachedCount, childLayoutConstraint);
287     layoutWrapper->SetLongPredictTask();
288 
289     IndicatorAndArrowMeasure(layoutWrapper, contentIdealSize);
290     CaptureMeasure(layoutWrapper, childLayoutConstraint);
291 
292     measured_ = true;
293 
294     // layout may be skipped, need to update contentMianSize after measure.
295     swiperPattern->SetContentMainSize(contentMainSize_);
296 }
297 
CaptureMeasure(LayoutWrapper * layoutWrapper,LayoutConstraintF & childLayoutConstraint)298 void SwiperLayoutAlgorithm::CaptureMeasure(LayoutWrapper* layoutWrapper, LayoutConstraintF& childLayoutConstraint)
299 {
300     if (!hasCachedCapture_ || itemPosition_.empty()) {
301         return;
302     }
303     auto hostNode = layoutWrapper->GetHostNode();
304     CHECK_NULL_VOID(hostNode);
305     auto leftCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_CAPTURE_ETS_TAG);
306     auto rightCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_CAPTURE_ETS_TAG);
307     if (isCaptureReverse_) {
308         leftCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_CAPTURE_ETS_TAG);
309         rightCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_CAPTURE_ETS_TAG);
310     }
311     CHECK_NULL_VOID(leftCaptureWrapper);
312     CHECK_NULL_VOID(rightCaptureWrapper);
313     auto lastWrapper = layoutWrapper->GetOrCreateChildByIndex(GetLoopIndex(itemPosition_.rbegin()->first));
314     CHECK_NULL_VOID(lastWrapper);
315     auto lastNode = lastWrapper->GetGeometryNode();
316     CHECK_NULL_VOID(lastNode);
317     auto leftCaptureGeometryNode = leftCaptureWrapper->GetGeometryNode();
318     CHECK_NULL_VOID(leftCaptureGeometryNode);
319     if (!leftCaptureSize_.has_value()) {
320         leftCaptureSize_ = leftCaptureGeometryNode->GetFrameSize();
321     }
322     childLayoutConstraint.UpdateSelfMarginSizeWithCheck(OptionalSizeF(lastNode->GetMarginFrameSize()));
323     leftCaptureWrapper->Measure(childLayoutConstraint);
324 
325     auto firstWrapper = layoutWrapper->GetOrCreateChildByIndex(GetLoopIndex(itemPosition_.begin()->first));
326     CHECK_NULL_VOID(firstWrapper);
327     auto firstNode = firstWrapper->GetGeometryNode();
328     CHECK_NULL_VOID(firstNode);
329     auto rightCaptureGeometryNode = rightCaptureWrapper->GetGeometryNode();
330     CHECK_NULL_VOID(rightCaptureGeometryNode);
331     if (!rightCaptureSize_.has_value()) {
332         rightCaptureSize_ = rightCaptureGeometryNode->GetFrameSize();
333     }
334     childLayoutConstraint.UpdateSelfMarginSizeWithCheck(OptionalSizeF(firstNode->GetMarginFrameSize()));
335     rightCaptureWrapper->Measure(childLayoutConstraint);
336 
337     isNeedUpdateCapture_ =
338         leftCaptureSize_ != lastNode->GetFrameSize() || rightCaptureSize_ != firstNode->GetFrameSize();
339 }
340 
MeasureTabsCustomAnimation(LayoutWrapper * layoutWrapper)341 void SwiperLayoutAlgorithm::MeasureTabsCustomAnimation(LayoutWrapper* layoutWrapper)
342 {
343     auto layoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
344     CHECK_NULL_VOID(layoutProperty);
345     auto axis = layoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
346     auto contentConstraint = layoutProperty->GetContentLayoutConstraint().value();
347     auto contentIdealSize = CreateIdealSizeByPercentRef(contentConstraint, axis, MeasureType::MATCH_PARENT_MAIN_AXIS);
348     auto childLayoutConstraint = SwiperUtils::CreateChildConstraint(layoutProperty, contentIdealSize, false);
349     auto childCrossSize = 0.0f;
350 
351     auto currentIndex = layoutProperty->GetIndex().value_or(0);
352     auto currentIndexWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex);
353     CHECK_NULL_VOID(currentIndexWrapper);
354     currentIndexWrapper->Measure(childLayoutConstraint);
355     auto currentIndexGeometryNode = currentIndexWrapper->GetGeometryNode();
356     if (currentIndexGeometryNode) {
357         childCrossSize = std::max(childCrossSize, currentIndexGeometryNode->GetMarginFrameSize().CrossSize(axis));
358     }
359 
360     if (customAnimationToIndex_) {
361         auto toIndexWrapper = layoutWrapper->GetOrCreateChildByIndex(customAnimationToIndex_.value());
362         CHECK_NULL_VOID(toIndexWrapper);
363         toIndexWrapper->Measure(childLayoutConstraint);
364         auto toIndexGeometryNode = toIndexWrapper->GetGeometryNode();
365         if (toIndexGeometryNode) {
366             childCrossSize = std::max(childCrossSize, toIndexGeometryNode->GetMarginFrameSize().CrossSize(axis));
367         }
368     }
369 
370     auto crossSize = contentIdealSize.CrossSize(axis);
371     if ((crossSize.has_value() && GreaterOrEqualToInfinity(crossSize.value())) || !crossSize.has_value()) {
372         contentIdealSize.SetCrossSize(childCrossSize, axis);
373     }
374     auto geometryNode = layoutWrapper->GetGeometryNode();
375     if (geometryNode) {
376         geometryNode->SetFrameSize(contentIdealSize.ConvertToSizeT());
377     }
378 
379     std::set<int32_t> removeIndexs;
380     for (const auto& index : needUnmountIndexs_) {
381         if (indexsInAnimation_.find(index) != indexsInAnimation_.end()) {
382             continue;
383         }
384 
385         layoutWrapper->RemoveChildInRenderTree(index);
386         removeIndexs.insert(index);
387     }
388 
389     for (const auto& index : removeIndexs) {
390         needUnmountIndexs_.erase(index);
391     }
392 }
393 
MeasureSwiperCustomAnimation(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint)394 void SwiperLayoutAlgorithm::MeasureSwiperCustomAnimation(LayoutWrapper* layoutWrapper,
395     const LayoutConstraintF& layoutConstraint)
396 {
397     std::set<int32_t> measureIndexSet;
398     for (const auto& pos : itemPosition_) {
399         measureIndexSet.insert(GetLoopIndex(pos.first));
400     }
401     for (const auto& pos : itemPositionInAnimation_) {
402         if (measureIndexSet.find(pos.first) == measureIndexSet.end()) {
403             auto currentIndexWrapper = layoutWrapper->GetOrCreateChildByIndex(pos.first);
404             CHECK_NULL_VOID(currentIndexWrapper);
405             currentIndexWrapper->Measure(layoutConstraint);
406         }
407     }
408 }
409 
GetChildMaxSize(LayoutWrapper * layoutWrapper,bool isMainAxis) const410 float SwiperLayoutAlgorithm::GetChildMaxSize(LayoutWrapper* layoutWrapper, bool isMainAxis) const
411 {
412     if (itemPosition_.empty()) {
413         return 0.0f;
414     }
415     float maxSize = 0.0f;
416     float size = 0.0f;
417     for (const auto& pos : itemPosition_) {
418         auto wrapper = layoutWrapper->GetOrCreateChildByIndex(GetLoopIndex(pos.first), false);
419         if (!wrapper) {
420             continue;
421         }
422         auto geometryNode = wrapper->GetGeometryNode();
423         if (!geometryNode) {
424             continue;
425         }
426         size = isMainAxis ? geometryNode->GetMarginFrameSize().MainSize(axis_)
427                           : geometryNode->GetMarginFrameSize().CrossSize(axis_);
428         maxSize = std::max(size, maxSize);
429     }
430     return maxSize;
431 }
432 
AdjustStartInfoOnSwipeByGroup(int32_t startIndex,const PositionMap & itemPosition,int32_t & startIndexInVisibleWindow,float & startPos)433 void SwiperLayoutAlgorithm::AdjustStartInfoOnSwipeByGroup(
434     int32_t startIndex, const PositionMap& itemPosition, int32_t& startIndexInVisibleWindow, float& startPos)
435 {
436     if (!swipeByGroup_ || isFrameAnimation_) {
437         return;
438     }
439 
440     startIndexInVisibleWindow = startIndex;
441     auto iter = itemPosition.find(startIndex);
442     if (iter != itemPosition.end()) {
443         startPos = iter->second.startPos;
444     }
445 }
446 
AdjustItemPositionOnCachedShow()447 void SwiperLayoutAlgorithm::AdjustItemPositionOnCachedShow()
448 {
449     if (!cachedShow_) {
450         return;
451     }
452 
453     auto startIndex = GetStartIndex();
454     while (startIndex < cachedStartIndex_) {
455         itemPosition_.erase(startIndex);
456         startIndex++;
457     }
458 
459     auto endIndex = GetEndIndex();
460     while (endIndex > cachedEndIndex_) {
461         itemPosition_.erase(endIndex);
462         endIndex--;
463     }
464 }
465 
GetCurrentFirstIndexInWindow(LayoutWrapper * layoutWrapper) const466 int32_t SwiperLayoutAlgorithm::GetCurrentFirstIndexInWindow(LayoutWrapper* layoutWrapper) const
467 {
468     if (itemPosition_.empty()) {
469         return currentIndex_;
470     }
471 
472     auto property = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
473     CHECK_NULL_RETURN(property, currentIndex_);
474     auto nextMarginIgnoreBlank = property->GetNextMarginIgnoreBlank().value_or(false);
475     for (const auto& item : itemPosition_) {
476         auto windowStartPos = startMainPos_ - (Positive(prevMargin_) ? prevMargin_ + spaceWidth_ : 0.0f);
477         if (!isLoop_ && GetLoopIndex(item.first) == totalItemCount_ - 1 && nextMarginIgnoreBlank &&
478             Positive(nextMargin_)) {
479             windowStartPos -= nextMargin_;
480         }
481 
482         if (LessNotEqual(item.second.startPos, windowStartPos) && LessNotEqual(item.second.endPos, windowStartPos)) {
483             continue;
484         }
485 
486         if (LessOrEqual(item.second.startPos, windowStartPos) && GreatNotEqual(item.second.endPos, windowStartPos)) {
487             return item.first;
488         }
489     }
490 
491     return itemPosition_.begin()->first;
492 }
493 
GetCurrentLastIndexInWindow(LayoutWrapper * layoutWrapper) const494 int32_t SwiperLayoutAlgorithm::GetCurrentLastIndexInWindow(LayoutWrapper* layoutWrapper) const
495 {
496     if (itemPosition_.empty()) {
497         return currentIndex_;
498     }
499 
500     auto property = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
501     CHECK_NULL_RETURN(property, currentIndex_);
502     auto prevMarginIgnoreBlank = property->GetPrevMarginIgnoreBlank().value_or(false);
503     for (const auto& item : itemPosition_) {
504         auto windowEndPos = endMainPos_ + (Positive(nextMargin_) ? nextMargin_ + spaceWidth_ : 0.0f);
505         if (!isLoop_ && GetLoopIndex(item.first) == 0 && prevMarginIgnoreBlank && Positive(prevMargin_)) {
506             windowEndPos += prevMargin_;
507         }
508 
509         if (LessNotEqual(item.second.startPos, windowEndPos) && LessNotEqual(item.second.endPos, windowEndPos)) {
510             continue;
511         }
512 
513         if (LessNotEqual(item.second.startPos, windowEndPos) && GreatOrEqual(item.second.endPos, windowEndPos)) {
514             return item.first;
515         }
516     }
517 
518     return itemPosition_.rbegin()->first;
519 }
520 
CalcCachedItemIndex(LayoutWrapper * layoutWrapper)521 void SwiperLayoutAlgorithm::CalcCachedItemIndex(LayoutWrapper* layoutWrapper)
522 {
523     auto cachedCount = GetUserSetCachedCount(layoutWrapper);
524     auto displayCount = GetDisplayCount(layoutWrapper);
525     auto firstIndexInWindow = GetCurrentFirstIndexInWindow(layoutWrapper);
526     auto lastIndexInWindow = GetCurrentLastIndexInWindow(layoutWrapper);
527     if (swipeByGroup_) {
528         cachedCount *= displayCount;
529         firstIndexInWindow = SwiperUtils::ComputePageIndex(firstIndexInWindow, displayCount);
530         lastIndexInWindow = SwiperUtils::ComputePageEndIndex(lastIndexInWindow, displayCount);
531     }
532 
533     if (!isLoop_) {
534         firstIndexInWindow = GetLoopIndex(firstIndexInWindow);
535         lastIndexInWindow = GetLoopIndex(lastIndexInWindow);
536         cachedStartIndex_ = std::max(firstIndexInWindow - cachedCount, 0);
537         cachedEndIndex_ = std::min(lastIndexInWindow + cachedCount, totalItemCount_ - 1);
538         return;
539     }
540 
541     auto outWindowCount = totalItemCount_ - (lastIndexInWindow - firstIndexInWindow + 1);
542     if (outWindowCount >= cachedCount * DEFAULT_DOUBLE) {
543         cachedStartIndex_ = firstIndexInWindow - cachedCount;
544         cachedEndIndex_ = lastIndexInWindow + cachedCount;
545         return;
546     }
547 
548     cachedStartIndex_ = firstIndexInWindow;
549     cachedEndIndex_ = lastIndexInWindow;
550     auto step = swipeByGroup_ ? displayCount : 1;
551     while (outWindowCount > 0) {
552         cachedEndIndex_ += step;
553         outWindowCount -= step;
554         if (outWindowCount <= 0) {
555             break;
556         }
557 
558         cachedStartIndex_ -= step;
559         outWindowCount -= step;
560     }
561 }
562 
GetUserSetCachedCount(LayoutWrapper * layoutWrapper) const563 int32_t SwiperLayoutAlgorithm::GetUserSetCachedCount(LayoutWrapper* layoutWrapper) const
564 {
565     auto layoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
566     CHECK_NULL_RETURN(layoutProperty, 1);
567     return layoutProperty->GetCachedCount().value_or(1);
568 }
569 
LayoutCachedItem(LayoutWrapper * layoutWrapper,const LayoutConstraintF & constraint)570 void SwiperLayoutAlgorithm::LayoutCachedItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint)
571 {
572     if (!cachedShow_) {
573         return;
574     }
575 
576     CalcCachedItemIndex(layoutWrapper);
577     if (GetStartIndex() > cachedStartIndex_) {
578         LayoutBackward(layoutWrapper, constraint, GetStartIndex() - 1, GetStartPosition(), true);
579     }
580 
581     if (GetEndIndex() < cachedEndIndex_) {
582         LayoutForward(layoutWrapper, constraint, GetEndIndex() + 1, GetEndPosition(), true);
583     }
584 }
585 
MeasureSwiperOnJump(LayoutWrapper * layoutWrapper,const LayoutConstraintF & constraint,int32_t jumpIndex)586 void SwiperLayoutAlgorithm::MeasureSwiperOnJump(
587     LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint, int32_t jumpIndex)
588 {
589     needUnmountIndexs_.clear();
590     itemPositionInAnimation_.clear();
591     auto startPos = (jumpIndex == 0) && Negative(startMainPos_) ? startMainPos_ : 0;
592     LayoutForward(layoutWrapper, constraint, jumpIndex, startPos);
593     auto prevMarginMontage = Positive(prevMargin_) ? prevMargin_ + spaceWidth_ : 0.0f;
594     if (Positive(ignoreBlankOffset_)) {
595         prevMarginMontage += ignoreBlankOffset_;
596     }
597 
598     if ((jumpIndex > 0 && GreatNotEqual(GetStartPosition(), startMainPos_ - prevMarginMontage)) ||
599         (isLoop_ && Positive(prevMargin_))) {
600         LayoutBackward(layoutWrapper, constraint, jumpIndex - 1, GetStartPosition());
601     }
602     currentIndex_ = jumpIndex;
603 }
604 
MeasureSwiper(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint)605 void SwiperLayoutAlgorithm::MeasureSwiper(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint)
606 {
607     int32_t startIndex = 0;
608     int32_t endIndex = 0;
609     float startPos = 0.0f;
610     float endPos = 0.0f;
611     int32_t startIndexInVisibleWindow = 0;
612     prevItemPosition_ = itemPosition_;
613     if (!itemPosition_.empty()) {
614         startPos = itemPosition_.begin()->second.startPos;
615         endPos = itemPosition_.rbegin()->second.endPos;
616         for (const auto& item : itemPosition_) {
617             float itemEndPos =
618                 Positive(prevMargin_) ? item.second.endPos + prevMargin_ + spaceWidth_ : item.second.endPos;
619             if (Positive(itemEndPos)) {
620                 startIndexInVisibleWindow = item.first;
621                 startPos = item.second.startPos;
622                 break;
623             }
624         }
625         if (!isLoop_) {
626             startIndex = std::min(GetLoopIndex(GetStartIndex()), totalItemCount_ - 1);
627             endIndex = std::min(GetLoopIndex(GetEndIndex()), totalItemCount_ - 1);
628             startIndexInVisibleWindow = std::min(GetLoopIndex(startIndexInVisibleWindow), totalItemCount_ - 1);
629             if (targetIndex_.has_value()) {
630                 targetIndex_ = GetLoopIndex(targetIndex_.value());
631             }
632         } else {
633             startIndex = GetStartIndex();
634             endIndex = GetEndIndex();
635         }
636 
637         itemPosition_.clear();
638     }
639 
640     if (jumpIndex_.has_value()) {
641         MeasureSwiperOnJump(layoutWrapper, layoutConstraint, jumpIndex_.value());
642     } else if (hasCachedCapture_) {
643         for (auto it = prevItemPosition_.rbegin(); it != prevItemPosition_.rend(); ++it) {
644             auto pos = Positive(prevMargin_) ? it->second.startPos + prevMargin_ : it->second.startPos;
645             // search for last item in visible window as endIndex
646             if (LessNotEqual(pos, contentMainSize_)) {
647                 endIndex = it->first;
648                 endPos = it->second.endPos;
649                 break;
650             }
651         }
652         if ((targetIndex_.has_value() && targetIndex_.value() >= startIndexInVisibleWindow)
653             || (!targetIndex_.has_value() && Negative(currentOffset_))) {
654             LayoutForward(layoutWrapper, layoutConstraint, startIndexInVisibleWindow, startPos);
655             LayoutBackward(layoutWrapper, layoutConstraint, GetStartIndex() - 1, GetStartPosition());
656         } else {
657             LayoutBackward(layoutWrapper, layoutConstraint, endIndex, endPos);
658             LayoutForward(layoutWrapper, layoutConstraint, GetEndIndex() + 1, GetEndPosition());
659         }
660         // captures need to be updated, swap capture to avoid flickering of disappearing real node's position
661         if (targetIndex_.has_value() && itemPosition_.begin()->first != prevItemPosition_.begin()->first) {
662             isCaptureReverse_ = !isCaptureReverse_;
663         }
664     } else if (targetIndex_.has_value()) {
665         // isMeasureOneMoreItem_ param is used to ensure item continuity when play property animation.
666         if (LessNotEqual(startIndexInVisibleWindow, targetIndex_.value())) {
667             if (isMeasureOneMoreItem_) {
668                 targetIndex_ =
669                     isLoop_ ? targetIndex_.value() + 1 : std::clamp(targetIndex_.value() + 1, 0, realTotalCount_ - 1);
670             }
671             AdjustStartInfoOnSwipeByGroup(startIndex, prevItemPosition_, startIndexInVisibleWindow, startPos);
672             LayoutForward(layoutWrapper, layoutConstraint, startIndexInVisibleWindow, startPos);
673             if (GreatNotEqualCustomPrecision(GetStartPosition(), startMainPos_, 0.01f)) {
674                 LayoutBackward(layoutWrapper, layoutConstraint, GetStartIndex() - 1, GetStartPosition());
675             }
676         } else if (GreatNotEqual(startIndexInVisibleWindow, targetIndex_.value())) {
677             if (isMeasureOneMoreItem_) {
678                 targetIndex_ =
679                     isLoop_ ? targetIndex_.value() - 1 : std::clamp(targetIndex_.value() - 1, 0, realTotalCount_ - 1);
680             }
681             LayoutBackward(layoutWrapper, layoutConstraint, endIndex, endPos);
682             if (LessNotEqualCustomPrecision(GetEndPosition(), endMainPos_, -0.01f)) {
683                 LayoutForward(layoutWrapper, layoutConstraint, GetEndIndex() + 1, GetEndPosition());
684             }
685         } else {
686             targetIsSameWithStartFlag_ = true;
687             AdjustStartInfoOnSwipeByGroup(startIndex, prevItemPosition_, startIndexInVisibleWindow, startPos);
688             LayoutForward(layoutWrapper, layoutConstraint, startIndexInVisibleWindow, startPos);
689             if (isMeasureOneMoreItem_ || Positive(prevMargin_)) {
690                 float startPosition =
691                     itemPosition_.empty() ? 0.0f : itemPosition_.begin()->second.startPos - spaceWidth_;
692                 LayoutBackward(layoutWrapper, layoutConstraint, GetStartIndex() - 1, startPosition);
693             }
694         }
695     } else {
696         AdjustStartInfoOnSwipeByGroup(startIndex, prevItemPosition_, startIndexInVisibleWindow, startPos);
697         bool overScrollTop = startIndexInVisibleWindow == 0 && GreatNotEqual(startPos, startMainPos_);
698         if ((!overScrollFeature_ && NonNegative(currentOffset_)) || (overScrollFeature_ && overScrollTop)) {
699             LayoutForward(layoutWrapper, layoutConstraint, startIndexInVisibleWindow, startPos);
700             auto adjustStartMainPos =
701                 startMainPos_ - prevMargin_ - spaceWidth_ - (Positive(ignoreBlankOffset_) ? ignoreBlankOffset_ : 0.0f);
702             if (GetStartIndex() > 0 && GreatNotEqual(GetStartPosition(), adjustStartMainPos)) {
703                 LayoutBackward(layoutWrapper, layoutConstraint, GetStartIndex() - 1, GetStartPosition());
704             }
705         } else {
706             LayoutBackward(layoutWrapper, layoutConstraint, endIndex, endPos);
707             if (GetEndIndex() < (totalItemCount_ - 1) && LessNotEqual(GetEndPosition(), endMainPos_)) {
708                 LayoutForward(layoutWrapper, layoutConstraint, GetEndIndex() + 1, GetEndPosition());
709             }
710         }
711     }
712 }
713 
LayoutForwardItem(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint,int32_t & currentIndex,float startPos,float & endPos)714 bool SwiperLayoutAlgorithm::LayoutForwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
715     int32_t& currentIndex, float startPos, float& endPos)
716 {
717     if ((currentIndex + 1 >= totalItemCount_ && !isLoop_) ||
718         (static_cast<int32_t>(itemPosition_.size()) >= totalItemCount_)) {
719         return false;
720     }
721 
722     auto measureIndex = GetLoopIndex(currentIndex + 1);
723     if (isMeasureOneMoreItem_ && !itemPosition_.empty() && measureIndex == GetLoopIndex(itemPosition_.begin()->first)) {
724         return false;
725     }
726 
727     if (swipeByGroup_ && measureIndex >= realTotalCount_) {
728         ++currentIndex;
729         endPos = startPos + placeItemWidth_.value_or(0.0f);
730         itemPosition_[currentIndex] = { startPos, endPos, nullptr };
731         return true;
732     }
733 
734     auto wrapper = layoutWrapper->GetOrCreateChildByIndex(measureIndex);
735     if (!IsNormalItem(wrapper)) {
736         return false;
737     }
738     ++currentIndex;
739     wrapper->Measure(layoutConstraint);
740     measuredItems_.insert(measureIndex);
741 
742     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
743     CHECK_NULL_RETURN(swiperLayoutProperty, false);
744 
745     float mainAxisSize = GetChildMainAxisSize(wrapper, swiperLayoutProperty);
746     if (SwiperUtils::IsStretch(swiperLayoutProperty)) {
747         mainAxisSize = placeItemWidth_.value_or(mainAxisSize);
748     }
749     endPos = startPos + mainAxisSize;
750     itemPosition_[currentIndex] = { startPos, endPos, wrapper->GetHostNode() };
751     return true;
752 }
753 
LayoutBackwardItem(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint,int32_t & currentIndex,float endPos,float & startPos)754 bool SwiperLayoutAlgorithm::LayoutBackwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
755     int32_t& currentIndex, float endPos, float& startPos)
756 {
757     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
758     CHECK_NULL_RETURN(swiperLayoutProperty, false);
759     int32_t displayCount =
760         swiperLayoutProperty->GetDisplayCount().has_value() ? swiperLayoutProperty->GetDisplayCount().value() : 1;
761     bool itemPositionIsFull = static_cast<int32_t>(itemPosition_.size()) >= totalItemCount_ + displayCount - 1;
762     if ((currentIndex - 1 < 0 && !isLoop_) || (SwiperUtils::IsStretch(swiperLayoutProperty) && itemPositionIsFull)) {
763         return false;
764     }
765     if (hasCachedCapture_ && static_cast<int32_t>(itemPosition_.size()) >= totalItemCount_) {
766         return false;
767     }
768 
769     auto measureIndex = GetLoopIndex(currentIndex - 1);
770     if (isMeasureOneMoreItem_ && !itemPosition_.empty() &&
771         measureIndex == GetLoopIndex(itemPosition_.rbegin()->first)) {
772         return false;
773     }
774 
775     if (swipeByGroup_ && measureIndex >= realTotalCount_) {
776         --currentIndex;
777         startPos = endPos - placeItemWidth_.value_or(0.0f);
778         itemPosition_[currentIndex] = { startPos, endPos, nullptr };
779         return true;
780     }
781 
782     auto wrapper = layoutWrapper->GetOrCreateChildByIndex(GetLoopIndex(measureIndex));
783     if (!IsNormalItem(wrapper)) {
784         return false;
785     }
786     --currentIndex;
787     wrapper->Measure(layoutConstraint);
788     measuredItems_.insert(measureIndex);
789 
790     float mainAxisSize = GetChildMainAxisSize(wrapper, swiperLayoutProperty);
791     if (SwiperUtils::IsStretch(swiperLayoutProperty)) {
792         mainAxisSize = placeItemWidth_.value_or(mainAxisSize);
793     }
794     startPos = endPos - mainAxisSize;
795     if (!itemPositionIsFull) {
796         itemPosition_[currentIndex] = { startPos, endPos, wrapper->GetHostNode() };
797     }
798     if (targetIndex_ && currentIndex == targetIndex_.value()) {
799         targetStartPos_ = startPos;
800     }
801     return true;
802 }
803 
SetInactiveOnForward(LayoutWrapper * layoutWrapper)804 void SwiperLayoutAlgorithm::SetInactiveOnForward(LayoutWrapper* layoutWrapper)
805 {
806     auto displayCount = GetDisplayCount(layoutWrapper);
807     for (auto pos = itemPosition_.begin(); pos != itemPosition_.end();) {
808         auto endPos = pos->second.endPos;
809         auto index = pos->first;
810         if (swipeByGroup_) {
811             auto endPageIndex = SwiperUtils::ComputePageEndIndex(index, displayCount);
812             auto iter = itemPosition_.find(endPageIndex);
813             if (iter != itemPosition_.end()) {
814                 endPos = iter->second.endPos;
815             }
816         }
817         endPos += ignoreBlankOffset_;
818         if (GreatNotEqual(endPos, prevMargin_ != 0.0f ? startMainPos_ - prevMargin_ - spaceWidth_ : startMainPos_)) {
819             break;
820         }
821 
822         ResetOffscreenItemPosition(layoutWrapper, GetLoopIndex(pos->first), true);
823         pos = itemPosition_.erase(pos);
824     }
825 }
826 
GetDisplayCount(LayoutWrapper * layoutWrapper) const827 int32_t SwiperLayoutAlgorithm::GetDisplayCount(LayoutWrapper* layoutWrapper) const
828 {
829     auto layoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
830     CHECK_NULL_RETURN(layoutProperty, 1);
831     return layoutProperty->GetDisplayCount().value_or(1);
832 }
833 
GetChildMainAxisSize(const RefPtr<LayoutWrapper> & childWrapper,const RefPtr<SwiperLayoutProperty> & swiperProperty)834 float SwiperLayoutAlgorithm::GetChildMainAxisSize(
835     const RefPtr<LayoutWrapper>& childWrapper, const RefPtr<SwiperLayoutProperty>& swiperProperty)
836 {
837     CHECK_NULL_RETURN(childWrapper, 0.0f);
838     auto geometryNode = childWrapper->GetGeometryNode();
839     CHECK_NULL_RETURN(geometryNode, 0.0f);
840 
841     float mainAxisSize = GetMainAxisSize(geometryNode->GetMarginFrameSize(), axis_);
842     if (!placeItemWidth_.has_value()) {
843         placeItemWidth_ = mainAxisSize;
844     }
845 
846     auto displayCount = swiperProperty->GetDisplayCountValue(1);
847     if (!SwiperUtils::IsStretch(swiperProperty) || displayCount == 0) {
848         return mainAxisSize;
849     }
850 
851     auto childProperty = childWrapper->GetLayoutProperty();
852     CHECK_NULL_RETURN(childProperty, mainAxisSize);
853     auto visibilityValue = childProperty->GetVisibilityValue(VisibleType::VISIBLE);
854     if (visibilityValue == VisibleType::INVISIBLE || visibilityValue == VisibleType::GONE) {
855         mainAxisSize = (contentMainSize_ - nextMargin_ - prevMargin_ - (displayCount - 1) * spaceWidth_)
856             / displayCount;
857     }
858 
859     return mainAxisSize;
860 }
861 
NeedMeasureForward(int32_t currentIndex,float currentEndPos,float forwardEndPos,bool cachedLayout) const862 bool SwiperLayoutAlgorithm::NeedMeasureForward(
863     int32_t currentIndex, float currentEndPos, float forwardEndPos, bool cachedLayout) const
864 {
865     if (cachedLayout) {
866         return currentIndex < cachedEndIndex_;
867     }
868     auto contentMainSize = contentMainSize_;
869     if (Positive(prevMargin_) && !prevMarginIgnoreBlank_) {
870         contentMainSize -= prevMargin_ + spaceWidth_;
871     }
872     bool isLayoutOver = overScrollFeature_ && GreatOrEqual(currentEndPos, contentMainSize);
873     return !isLayoutOver &&
874            (LessNotEqual(currentEndPos, forwardEndPos) || (targetIndex_ && currentIndex < targetIndex_.value()));
875 }
876 
AdjustOffsetOnForward(float currentEndPos)877 void SwiperLayoutAlgorithm::AdjustOffsetOnForward(float currentEndPos)
878 {
879     if (itemPosition_.empty()) {
880         return;
881     }
882 
883     auto firstItemTop = itemPosition_.begin()->second.startPos;
884     auto itemTotalSize = currentEndPos - firstItemTop;
885     if (LessOrEqual(itemTotalSize, contentMainSize_) && (itemPosition_.begin()->first == 0)) {
886         // all items size is less than swiper.
887         if (!canOverScroll_) {
888             currentOffset_ = firstItemTop;
889             startMainPos_ = currentOffset_;
890         }
891         if (!mainSizeIsDefined_) {
892             // adapt child size.
893             contentMainSize_ = itemTotalSize;
894         }
895     } else {
896         // adjust offset. If edgeEffect is SPRING, jump adjust to allow swiper scroll through boundary
897         if (!canOverScroll_ || jumpIndex_.has_value()) {
898             auto prevMarginMontage = Positive(prevMargin_) ? prevMargin_ + spaceWidth_ : 0.0f;
899             auto nextMarginMontage = Positive(nextMargin_) ? nextMargin_ + spaceWidth_ : 0.0f;
900             currentOffset_ = currentEndPos - contentMainSize_ + prevMarginMontage + nextMarginMontage;
901         }
902         startMainPos_ = currentEndPos - contentMainSize_;
903         endMainPos_ = currentEndPos;
904     }
905 }
906 
LayoutForward(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint,int32_t startIndex,float startPos,bool cachedLayout)907 void SwiperLayoutAlgorithm::LayoutForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
908     int32_t startIndex, float startPos, bool cachedLayout)
909 {
910     float currentEndPos = startPos;
911     float currentStartPos = 0.0f;
912     float endMainPos = overScrollFeature_ ? std::max(startPos + contentMainSize_, endMainPos_) : endMainPos_;
913     if (targetIndex_) {
914         endMainPos = Infinity<float>();
915     }
916     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
917     CHECK_NULL_VOID(swiperLayoutProperty);
918 
919     auto currentIndex = startIndex - 1;
920     auto marginValue = NearZero(nextMargin_) ? 0.0f : nextMargin_ + spaceWidth_;
921     if (!NearZero(prevMargin_) && startIndex == 0 && swiperLayoutProperty->GetPrevMarginIgnoreBlankValue(false)) {
922         marginValue += prevMargin_ + spaceWidth_;
923     }
924     do {
925         currentStartPos = currentEndPos;
926         auto result = LayoutForwardItem(layoutWrapper, layoutConstraint, currentIndex, currentStartPos, currentEndPos);
927         if (!result) {
928             break;
929         }
930         if (SwiperUtils::CheckIsSingleCase(swiperLayoutProperty) && !mainSizeIsDefined_) {
931             endMainPos = itemPosition_.begin()->second.endPos - itemPosition_.begin()->second.startPos;
932             if (measured_) {
933                 endMainPos += currentOffset_;
934             }
935             endMainPos_ = endMainPos;
936         }
937         if ((currentIndex >= 0 && currentIndex < (totalItemCount_ - 1)) || isLoop_) {
938             currentEndPos += spaceWidth_;
939         }
940         // reach the valid target index
941         if (targetIndex_ && currentIndex >= targetIndex_.value()) {
942             endMainPos = targetIsSameWithStartFlag_ ? endMainPos_ : currentStartPos + contentMainSize_;
943             targetIndex_.reset();
944         }
945     } while (NeedMeasureForward(currentIndex, currentEndPos, endMainPos + marginValue, cachedLayout));
946 
947     if (overScrollFeature_ && canOverScroll_) {
948         return;
949     }
950 
951     if (LessNotEqual(currentEndPos, endMainPos_)) {
952         AdjustOffsetOnForward(currentEndPos);
953     }
954 
955     if (!cachedLayout) {
956         // Mark inactive in wrapper.
957         SetInactiveOnForward(layoutWrapper);
958     }
959 }
960 
SetInactive(LayoutWrapper * layoutWrapper,float startMainPos,float endMainPos,std::optional<int32_t> targetIndex)961 void SwiperLayoutAlgorithm::SetInactive(
962     LayoutWrapper* layoutWrapper, float startMainPos, float endMainPos, std::optional<int32_t> targetIndex)
963 {
964     if (cachedShow_) {
965         return;
966     }
967 
968     if (measured_) {
969         // Theoretically, offset should be added in all cases to get correct results. Only apply in flex for now.
970         startMainPos += currentOffset_;
971         endMainPos += currentOffset_;
972     }
973     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
974     CHECK_NULL_VOID(swiperLayoutProperty);
975     std::list<int32_t> removeIndexes;
976     for (auto pos = itemPosition_.rbegin(); pos != itemPosition_.rend(); ++pos) {
977         if (targetIndex.has_value() && targetIndex.value() == pos->first) {
978             continue;
979         }
980         if (LessOrEqual(
981             pos->second.endPos, prevMargin_ != 0.0f ? startMainPos - prevMargin_ - spaceWidth_ : startMainPos) ||
982             GreatOrEqual(
983                 pos->second.startPos, nextMargin_ != 0.0f ? endMainPos + nextMargin_ + spaceWidth_ : endMainPos)) {
984             removeIndexes.emplace_back(pos->first);
985         }
986     }
987     for (const auto& index : removeIndexes) {
988         itemPosition_.erase(index);
989     }
990 }
991 
SetInactiveOnBackward(LayoutWrapper * layoutWrapper)992 void SwiperLayoutAlgorithm::SetInactiveOnBackward(LayoutWrapper* layoutWrapper)
993 {
994     std::list<int32_t> removeIndexes;
995     auto displayCount = GetDisplayCount(layoutWrapper);
996     for (auto pos = itemPosition_.rbegin(); pos != itemPosition_.rend(); ++pos) {
997         auto startPos = pos->second.startPos;
998         auto index = pos->first;
999 
1000         if (swipeByGroup_) {
1001             auto startPageIndex = SwiperUtils::ComputePageIndex(index, displayCount);
1002             auto iter = itemPosition_.find(startPageIndex);
1003             if (iter != itemPosition_.end()) {
1004                 startPos = iter->second.startPos;
1005             }
1006         }
1007         startPos += ignoreBlankOffset_;
1008         if (LessNotEqual(startPos, nextMargin_ != 0.0f ? endMainPos_ + nextMargin_ + spaceWidth_ : endMainPos_)) {
1009             break;
1010         }
1011 
1012         ResetOffscreenItemPosition(layoutWrapper, GetLoopIndex(index), false);
1013         removeIndexes.emplace_back(index);
1014     }
1015 
1016     for (const auto& index : removeIndexes) {
1017         itemPosition_.erase(index);
1018     }
1019 }
1020 
NeedMeasureBackward(int32_t currentIndex,float currentStartPos,float backwardStartPos,bool isStretch,bool cachedLayout) const1021 bool SwiperLayoutAlgorithm::NeedMeasureBackward(
1022     int32_t currentIndex, float currentStartPos, float backwardStartPos, bool isStretch, bool cachedLayout) const
1023 {
1024     if (cachedLayout) {
1025         return currentIndex > cachedStartIndex_;
1026     }
1027 
1028     return GreatNotEqual(currentStartPos, backwardStartPos) ||
1029            (!isStretch && targetIndex_ && currentIndex > targetIndex_.value());
1030 }
1031 
LayoutBackward(LayoutWrapper * layoutWrapper,const LayoutConstraintF & layoutConstraint,int32_t endIndex,float endPos,bool cachedLayout)1032 void SwiperLayoutAlgorithm::LayoutBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
1033     int32_t endIndex, float endPos, bool cachedLayout)
1034 {
1035     float currentStartPos = endPos;
1036     float currentEndPos = 0.0f;
1037     float startMainPos = overScrollFeature_ ? std::min(endPos - contentMainSize_, startMainPos_) : startMainPos_;
1038     if (targetIndex_) {
1039         startMainPos = -Infinity<float>();
1040     }
1041     auto currentIndex = endIndex + 1;
1042 
1043     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1044     CHECK_NULL_VOID(swiperLayoutProperty);
1045     auto isStretch = SwiperUtils::IsStretch(swiperLayoutProperty);
1046     float adjustStartMainPos = 0.0f;
1047     do {
1048         currentEndPos = currentStartPos;
1049         auto result = LayoutBackwardItem(layoutWrapper, layoutConstraint, currentIndex, currentEndPos, currentStartPos);
1050         if (!result) {
1051             break;
1052         }
1053         if (currentIndex > 0 || isLoop_) {
1054             currentStartPos = currentStartPos - spaceWidth_;
1055         }
1056         // reach the valid target index
1057         if (targetIndex_ && LessOrEqual(currentIndex, targetIndex_.value())) {
1058             startMainPos = currentStartPos;
1059             targetIndex_.reset();
1060         }
1061         adjustStartMainPos = startMainPos - (Positive(prevMargin_) ? prevMargin_ + spaceWidth_ : 0.0f) -
1062                              (Positive(ignoreBlankOffset_) ? ignoreBlankOffset_ : 0.0f);
1063     } while (NeedMeasureBackward(currentIndex, currentStartPos, adjustStartMainPos, isStretch, cachedLayout));
1064 
1065     // adjust offset. If edgeEffect is SPRING, jump adjust to allow swiper scroll through boundary
1066     if (GreatNotEqual(currentStartPos, startMainPos_)) {
1067         AdjustOffsetOnBackward(currentStartPos);
1068     }
1069 
1070     if (overScrollFeature_) {
1071         return;
1072     }
1073 
1074     if (!cachedLayout) {
1075         // Mark inactive in wrapper.
1076         SetInactiveOnBackward(layoutWrapper);
1077     }
1078 }
1079 
AdjustOffsetOnBackward(float currentStartPos)1080 void SwiperLayoutAlgorithm::AdjustOffsetOnBackward(float currentStartPos)
1081 {
1082     if (!canOverScroll_ || jumpIndex_.has_value()) {
1083         currentOffset_ = currentStartPos;
1084         if (!mainSizeIsDefined_ && GetEndIndex() == totalItemCount_ - 1) {
1085             auto itemTotalSize = GetEndPosition() - currentStartPos;
1086             contentMainSize_ = std::min(contentMainSize_, itemTotalSize);
1087         }
1088     }
1089     endMainPos_ = currentStartPos + contentMainSize_;
1090     startMainPos_ = currentStartPos;
1091 }
1092 
LayoutCustomAnimation(LayoutWrapper * layoutWrapper) const1093 void SwiperLayoutAlgorithm::LayoutCustomAnimation(LayoutWrapper* layoutWrapper) const
1094 {
1095     auto layoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1096     CHECK_NULL_VOID(layoutProperty);
1097     auto geometryNode = layoutWrapper->GetGeometryNode();
1098     CHECK_NULL_VOID(geometryNode);
1099 
1100     auto size = geometryNode->GetFrameSize();
1101     auto padding = layoutProperty->CreatePaddingAndBorder();
1102     MinusPaddingToSize(padding, size);
1103     auto paddingOffset = padding.Offset();
1104 
1105     if (customAnimationToIndex_) {
1106         auto toIndexWrapper = layoutWrapper->GetOrCreateChildByIndex(customAnimationToIndex_.value());
1107         CHECK_NULL_VOID(toIndexWrapper);
1108         CHECK_NULL_VOID(toIndexWrapper->GetGeometryNode());
1109         toIndexWrapper->GetGeometryNode()->SetMarginFrameOffset(paddingOffset);
1110         toIndexWrapper->Layout();
1111     }
1112 
1113     auto currentIndex = layoutProperty->GetIndex().value_or(0);
1114     auto currentIndexWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex);
1115     CHECK_NULL_VOID(currentIndexWrapper);
1116     CHECK_NULL_VOID(currentIndexWrapper->GetGeometryNode());
1117     currentIndexWrapper->GetGeometryNode()->SetMarginFrameOffset(paddingOffset);
1118     currentIndexWrapper->Layout();
1119 }
1120 
Layout(LayoutWrapper * layoutWrapper)1121 void SwiperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
1122 {
1123     CHECK_NULL_VOID(layoutWrapper);
1124     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1125     CHECK_NULL_VOID(swiperLayoutProperty);
1126     auto geometryNode = layoutWrapper->GetGeometryNode();
1127     CHECK_NULL_VOID(geometryNode);
1128 
1129     if (swiperLayoutProperty->GetIsCustomAnimation().value_or(false)) {
1130         LayoutCustomAnimation(layoutWrapper);
1131         return;
1132     }
1133 
1134     axis_ = swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
1135     auto size = geometryNode->GetFrameSize();
1136     auto padding = swiperLayoutProperty->CreatePaddingAndBorder();
1137     MinusPaddingToSize(padding, size);
1138     auto paddingOffset = padding.Offset();
1139 
1140     // layout items.
1141     std::set<int32_t> layoutIndexSet;
1142     for (auto& pos : itemPosition_) {
1143         layoutIndexSet.insert(GetLoopIndex(pos.first));
1144         pos.second.startPos -= currentOffset_;
1145         pos.second.endPos -= currentOffset_;
1146         LayoutItem(layoutWrapper, paddingOffset, pos);
1147     }
1148     for (auto& pos : itemPositionInAnimation_) {
1149         if (layoutIndexSet.find(pos.first) == layoutIndexSet.end()) {
1150             LayoutItem(layoutWrapper, paddingOffset, pos);
1151         }
1152     }
1153     LayoutSwiperIndicator(layoutWrapper, swiperLayoutProperty, padding);
1154     CaptureLayout(layoutWrapper);
1155 }
1156 
LayoutSwiperIndicator(LayoutWrapper * layoutWrapper,const RefPtr<SwiperLayoutProperty> & swiperLayoutProperty,const PaddingPropertyF & padding)1157 void SwiperLayoutAlgorithm::LayoutSwiperIndicator(
1158     LayoutWrapper* layoutWrapper, const RefPtr<SwiperLayoutProperty>& swiperLayoutProperty,
1159     const PaddingPropertyF& padding)
1160 {
1161     auto hostNode = layoutWrapper->GetHostNode();
1162     CHECK_NULL_VOID(hostNode);
1163     auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
1164     CHECK_NULL_VOID(swiperPattern);
1165 
1166     // Layout swiper indicator
1167     if (swiperLayoutProperty->GetShowIndicatorValue(true)) {
1168         auto indicatorWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_INDICATOR_ETS_TAG);
1169         if (indicatorWrapper) {
1170             if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT) == SwiperIndicatorType::DIGIT) {
1171                 PlaceDigitChild(indicatorWrapper, swiperLayoutProperty);
1172             }
1173             indicatorWrapper->Layout();
1174         }
1175     }
1176 
1177     if (swiperLayoutProperty->GetDisplayArrowValue(false)) {
1178         if (swiperPattern->HasLeftButtonNode() && swiperPattern->HasRightButtonNode()) {
1179             auto leftArrowWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_ARROW_ETS_TAG);
1180             auto rightArrowWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_ARROW_ETS_TAG);
1181             if (leftArrowWrapper && (leftArrowWrapper->GetHostTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG)) {
1182                 ArrowLayout(layoutWrapper, leftArrowWrapper, padding);
1183             }
1184             if (rightArrowWrapper && (rightArrowWrapper->GetHostTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG)) {
1185                 ArrowLayout(layoutWrapper, rightArrowWrapper, padding);
1186             }
1187         }
1188     }
1189 }
1190 
LayoutItem(LayoutWrapper * layoutWrapper,OffsetF offset,std::pair<int32_t,SwiperItemInfo> pos)1191 void SwiperLayoutAlgorithm::LayoutItem(LayoutWrapper* layoutWrapper, OffsetF offset,
1192     std::pair<int32_t, SwiperItemInfo> pos)
1193 {
1194     pos.second.startPos += ignoreBlankOffset_;
1195     pos.second.endPos += ignoreBlankOffset_;
1196 
1197     auto layoutIndex = GetLoopIndex(pos.first);
1198     if (swipeByGroup_ && layoutIndex >= realTotalCount_) {
1199         return;
1200     }
1201 
1202     auto wrapper = layoutWrapper->GetOrCreateChildByIndex(layoutIndex);
1203     if (!IsNormalItem(wrapper)) {
1204         return;
1205     }
1206 
1207     float crossOffset = 0.0f;
1208     if (axis_ == Axis::VERTICAL) {
1209         offset += OffsetF(crossOffset, pos.second.startPos);
1210         if (!NearZero(prevMargin_)) {
1211             offset += OffsetF(crossOffset, prevMargin_ + spaceWidth_);
1212         }
1213     } else {
1214         CHECK_NULL_VOID(layoutWrapper->GetLayoutProperty());
1215         bool isRtl = layoutWrapper->GetLayoutProperty()->GetNonAutoLayoutDirection() == TextDirection::RTL;
1216         float offsetPos = isRtl ? contentMainSize_ - pos.second.endPos : pos.second.startPos;
1217         offset += OffsetF(offsetPos, crossOffset);
1218         if (!NearZero(prevMargin_) && !isRtl) {
1219             offset += OffsetF(prevMargin_ + spaceWidth_, crossOffset);
1220         }
1221         if (!NearZero(prevMargin_) && isRtl) {
1222             offset -= OffsetF(prevMargin_ + spaceWidth_, crossOffset);
1223         }
1224     }
1225     CHECK_NULL_VOID(wrapper->GetGeometryNode());
1226     wrapper->GetGeometryNode()->SetMarginFrameOffset(offset);
1227     wrapper->Layout();
1228 }
1229 
CaptureLayout(LayoutWrapper * layoutWrapper)1230 void SwiperLayoutAlgorithm::CaptureLayout(LayoutWrapper* layoutWrapper)
1231 {
1232     if (!hasCachedCapture_ || itemPosition_.empty()) {
1233         return;
1234     }
1235     auto leftCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_CAPTURE_ETS_TAG);
1236     auto rightCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_CAPTURE_ETS_TAG);
1237     if (isCaptureReverse_) {
1238         leftCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_RIGHT_CAPTURE_ETS_TAG);
1239         rightCaptureWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_LEFT_CAPTURE_ETS_TAG);
1240     }
1241     CHECK_NULL_VOID(leftCaptureWrapper);
1242     CHECK_NULL_VOID(rightCaptureWrapper);
1243     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1244     CHECK_NULL_VOID(swiperLayoutProperty);
1245     auto axis = swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
1246     auto leftGeometryNode = leftCaptureWrapper->GetGeometryNode();
1247     CHECK_NULL_VOID(leftGeometryNode);
1248     auto rightGeometryNode = rightCaptureWrapper->GetGeometryNode();
1249     CHECK_NULL_VOID(rightGeometryNode);
1250     auto leftCaptureSize = axis == Axis::VERTICAL ? leftGeometryNode->GetMarginFrameSize().Height()
1251                                                   : leftGeometryNode->GetMarginFrameSize().Width();
1252     auto leftPosition = itemPosition_.begin()->second.startPos - spaceWidth_ - leftCaptureSize;
1253     auto rightPosition = itemPosition_.rbegin()->second.endPos + spaceWidth_;
1254 
1255     auto padding = swiperLayoutProperty->CreatePaddingAndBorder();
1256     auto leftOffset = padding.Offset();
1257     auto rightOffset = padding.Offset();
1258     auto deltaOffset = 0.0f;
1259     if (!NearZero(prevMargin_)) {
1260         deltaOffset = prevMargin_ + spaceWidth_;
1261     }
1262     if (axis == Axis::VERTICAL) {
1263         leftOffset += OffsetF(0.0f, leftPosition + deltaOffset);
1264         rightOffset += OffsetF(0.0f, rightPosition + deltaOffset);
1265     } else {
1266         bool isRtl = swiperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
1267         if (isRtl) {
1268             leftPosition = contentMainSize_ - itemPosition_.begin()->second.startPos + spaceWidth_;
1269             rightPosition = contentMainSize_ - itemPosition_.rbegin()->second.endPos - spaceWidth_ - leftCaptureSize;
1270             leftOffset += OffsetF(leftPosition - deltaOffset, 0.0f);
1271             rightOffset += OffsetF(rightPosition - deltaOffset, 0.0f);
1272         } else {
1273             leftOffset += OffsetF(leftPosition + deltaOffset, 0.0f);
1274             rightOffset += OffsetF(rightPosition + deltaOffset, 0.0f);
1275         }
1276     }
1277     leftGeometryNode->SetMarginFrameOffset(leftOffset);
1278     leftCaptureWrapper->Layout();
1279     rightGeometryNode->SetMarginFrameOffset(rightOffset);
1280     rightCaptureWrapper->Layout();
1281 }
1282 
PlaceDigitChild(const RefPtr<LayoutWrapper> & indicatorWrapper,const RefPtr<LayoutProperty> & layoutProperty)1283 void SwiperLayoutAlgorithm::PlaceDigitChild(
1284     const RefPtr<LayoutWrapper>& indicatorWrapper, const RefPtr<LayoutProperty>& layoutProperty)
1285 {
1286     if (indicatorWrapper->GetTotalChildCount() != INDICATOR_HAS_CHILD) {
1287         return;
1288     }
1289     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutProperty);
1290     CHECK_NULL_VOID(swiperLayoutProperty);
1291     auto indicatorGeometryNode = indicatorWrapper->GetGeometryNode();
1292     CHECK_NULL_VOID(indicatorGeometryNode);
1293     auto indicatorWidth = INDICATOR_PADDING.ConvertToPx() * 2.0;
1294     auto indicatorHeight = 0.0f;
1295     for (auto&& child : indicatorWrapper->GetAllChildrenWithBuild()) {
1296         auto textGeometryNode = child->GetGeometryNode();
1297         CHECK_NULL_VOID(textGeometryNode);
1298         auto textFrameSize = textGeometryNode->GetFrameSize();
1299         indicatorWidth += textFrameSize.Width();
1300         if (indicatorHeight < textFrameSize.Height()) {
1301             indicatorHeight = textFrameSize.Height();
1302         }
1303     }
1304 
1305     auto pipelineContext = PipelineBase::GetCurrentContext();
1306     CHECK_NULL_VOID(pipelineContext);
1307     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1308     CHECK_NULL_VOID(swiperIndicatorTheme);
1309     if (LessNotEqual(indicatorHeight, swiperIndicatorTheme->GetIndicatorDigitHeight().ConvertToPx())) {
1310         indicatorHeight = swiperIndicatorTheme->GetIndicatorDigitHeight().ConvertToPx();
1311     }
1312 
1313     auto frameNode = indicatorWrapper->GetHostNode();
1314     CHECK_NULL_VOID(frameNode);
1315     auto indicatorlayoutProperty = frameNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
1316     CHECK_NULL_VOID(indicatorlayoutProperty);
1317 
1318     auto currentOffset = SwiperIndicatorUtils::CalcIndicatrFrameOffSet(
1319         swiperLayoutProperty, indicatorlayoutProperty, indicatorWidth, indicatorHeight);
1320 
1321     if (swiperLayoutProperty->GetDisplayArrowValue(false) && !swiperLayoutProperty->GetIsSidebarMiddleValue(false) &&
1322         HasCustomIndicatorOffset(indicatorWrapper)) {
1323         useCustomIndicatorOffset = true;
1324         auto indicatorOffset = CalculateCustomOffset(indicatorWrapper, currentOffset);
1325         if (swiperLayoutProperty->GetDirectionValue(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
1326             currentOffset.SetX(indicatorOffset.GetX());
1327         } else {
1328             currentOffset.SetY(indicatorOffset.GetY());
1329         }
1330     }
1331     if (swiperLayoutProperty->GetDirectionValue(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
1332         auto top = indicatorlayoutProperty->GetTop();
1333         auto bottom = indicatorlayoutProperty->GetBottom();
1334         if ((!top.has_value() || NearZero(top.value().Value())) &&
1335             (!bottom.has_value() || NearZero(bottom.value().Value()))) {
1336             auto themeHeight = swiperIndicatorTheme->GetIndicatorDigitHeight().ConvertToPx();
1337             auto dightPadding = 0.0;
1338             if (themeHeight > indicatorHeight) {
1339                 dightPadding = (themeHeight - indicatorHeight) / 2;
1340             }
1341             auto dightVerPadding = swiperIndicatorTheme->GetIndicatorDigitVerticalPadding().ConvertToPx();
1342             currentOffset.SetY(currentOffset.GetY() - dightVerPadding + dightPadding);
1343         }
1344     }
1345 
1346     indicatorGeometryNode->SetMarginFrameOffset(currentOffset);
1347 }
1348 
GetNodeLayoutWrapperByTag(LayoutWrapper * layoutWrapper,const std::string & tagName) const1349 RefPtr<LayoutWrapper> SwiperLayoutAlgorithm::GetNodeLayoutWrapperByTag(
1350     LayoutWrapper* layoutWrapper, const std::string& tagName) const
1351 {
1352     CHECK_NULL_RETURN(layoutWrapper, nullptr);
1353     auto hostNode = layoutWrapper->GetHostNode();
1354     CHECK_NULL_RETURN(hostNode, nullptr);
1355     auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
1356     CHECK_NULL_RETURN(swiperPattern, nullptr);
1357     if (swiperPattern->IsBindIndicator() && V2::SWIPER_INDICATOR_ETS_TAG == tagName) {
1358         return nullptr;
1359     }
1360     RefPtr<LayoutWrapper> nodeWrapper = nullptr;
1361     int32_t totalChildCount = layoutWrapper->GetTotalChildCount();
1362     if (totalChildCount == 0) {
1363         return nullptr;
1364     }
1365     int32_t lastChildIndex = totalChildCount - 1;
1366     int32_t endLoopChildIndex = lastChildIndex - SWIPER_HAS_CHILD;
1367     for (int32_t index = lastChildIndex; index > endLoopChildIndex && index >= 0; index--) {
1368         nodeWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
1369         if (nodeWrapper && (nodeWrapper->GetHostTag() == tagName)) {
1370             return nodeWrapper;
1371         }
1372     }
1373 
1374     return nullptr;
1375 }
1376 
HasCustomIndicatorOffset(const RefPtr<LayoutWrapper> & indicatorWrapper)1377 bool SwiperLayoutAlgorithm::HasCustomIndicatorOffset(const RefPtr<LayoutWrapper>& indicatorWrapper)
1378 {
1379     auto frameNode = indicatorWrapper->GetHostNode();
1380     CHECK_NULL_RETURN(frameNode, false);
1381     auto indicatorLayoutProperty = frameNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
1382     CHECK_NULL_RETURN(indicatorLayoutProperty, false);
1383     return indicatorLayoutProperty->GetLeft().has_value() || indicatorLayoutProperty->GetRight().has_value() ||
1384            indicatorLayoutProperty->GetTop().has_value() || indicatorLayoutProperty->GetBottom().has_value();
1385 }
1386 
CalculateCustomOffset(const RefPtr<LayoutWrapper> & indicatorWrapper,const OffsetF & currentOffset)1387 const OffsetF SwiperLayoutAlgorithm::CalculateCustomOffset(
1388     const RefPtr<LayoutWrapper>& indicatorWrapper, const OffsetF& currentOffset)
1389 {
1390     OffsetF indicatorOffset(currentOffset.GetX(), currentOffset.GetY());
1391     auto indicatorGeometryNode = indicatorWrapper->GetGeometryNode();
1392     CHECK_NULL_RETURN(indicatorGeometryNode, indicatorOffset);
1393     SizeF indicatorFrameSize = indicatorGeometryNode->GetFrameSize();
1394     auto indicatorLayoutProperty =
1395         AceType::DynamicCast<SwiperIndicatorLayoutProperty>(indicatorWrapper->GetLayoutProperty());
1396     CHECK_NULL_RETURN(indicatorLayoutProperty, indicatorOffset);
1397 
1398     auto indicatorNode = indicatorWrapper->GetHostNode();
1399     CHECK_NULL_RETURN(indicatorNode, indicatorOffset);
1400     auto swiperNode = DynamicCast<FrameNode>(indicatorNode->GetParent());
1401     CHECK_NULL_RETURN(swiperNode, indicatorOffset);
1402     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
1403     CHECK_NULL_RETURN(swiperLayoutProperty, indicatorOffset);
1404     CHECK_NULL_RETURN(swiperNode->GetGeometryNode(), indicatorOffset);
1405     SizeF swiperFrameSize = swiperNode->GetGeometryNode()->GetFrameSize();
1406     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
1407     CHECK_NULL_RETURN(swiperPattern, indicatorOffset);
1408     auto arrowNode = DynamicCast<FrameNode>(
1409         swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(swiperPattern->GetLeftButtonId())));
1410     CHECK_NULL_RETURN(arrowNode, indicatorOffset);
1411     CHECK_NULL_RETURN(arrowNode->GetGeometryNode(), indicatorOffset);
1412     SizeF arrowFrameSize = arrowNode->GetGeometryNode()->GetFrameSize();
1413     auto left = indicatorLayoutProperty->GetLeft();
1414     auto right = indicatorLayoutProperty->GetRight();
1415     auto top = indicatorLayoutProperty->GetTop();
1416     auto bottom = indicatorLayoutProperty->GetBottom();
1417     auto pipelineContext = PipelineBase::GetCurrentContext();
1418     CHECK_NULL_RETURN(pipelineContext, indicatorOffset);
1419     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1420     CHECK_NULL_RETURN(swiperIndicatorTheme, indicatorOffset);
1421     auto indicatorPadding = swiperIndicatorTheme->GetIndicatorDigitPadding().ConvertToPx();
1422 
1423     if (swiperLayoutProperty->GetDirectionValue(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
1424         auto horizonOffset = arrowFrameSize.Width() + indicatorPadding;
1425         auto offset = 0.0;
1426         if (left.has_value()) {
1427             offset = currentOffset.GetX() + horizonOffset;
1428             indicatorOffset.SetX(
1429                 std::min(offset, swiperFrameSize.Width() - indicatorFrameSize.Width() - horizonOffset));
1430         } else if (right.has_value()) {
1431             offset = currentOffset.GetX() - horizonOffset;
1432             indicatorOffset.SetX(std::max(offset, horizonOffset));
1433         }
1434     } else {
1435         auto verticleOffset = arrowFrameSize.Height() + indicatorPadding;
1436         auto offset = 0.0;
1437         if (top.has_value()) {
1438             offset = currentOffset.GetY() + verticleOffset;
1439             indicatorOffset.SetY(
1440                 std::min(offset, swiperFrameSize.Height() - indicatorFrameSize.Height() - verticleOffset));
1441         } else if (bottom.has_value()) {
1442             offset = currentOffset.GetY() - verticleOffset;
1443             indicatorOffset.SetY(std::max(offset, verticleOffset));
1444         }
1445     }
1446     return indicatorOffset;
1447 }
1448 
MeasureArrow(const RefPtr<LayoutWrapper> & arrowWrapper,const RefPtr<LayoutProperty> & layoutProperty) const1449 void SwiperLayoutAlgorithm::MeasureArrow(
1450     const RefPtr<LayoutWrapper>& arrowWrapper, const RefPtr<LayoutProperty>& layoutProperty) const
1451 {
1452     CHECK_NULL_VOID(arrowWrapper);
1453     CHECK_NULL_VOID(layoutProperty);
1454     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutProperty);
1455     CHECK_NULL_VOID(swiperLayoutProperty);
1456     auto arrowGeometryNode = arrowWrapper->GetGeometryNode();
1457     CHECK_NULL_VOID(arrowGeometryNode);
1458 
1459     auto pipelineContext = PipelineBase::GetCurrentContext();
1460     CHECK_NULL_VOID(pipelineContext);
1461     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1462     CHECK_NULL_VOID(swiperIndicatorTheme);
1463 
1464     arrowGeometryNode->SetFrameSize(
1465         SizeF { static_cast<float>(
1466                     swiperLayoutProperty->GetBackgroundSizeValue(swiperIndicatorTheme->GetBigArrowBackgroundSize())
1467                         .ConvertToPx()),
1468             static_cast<float>(
1469                 swiperLayoutProperty->GetBackgroundSizeValue(swiperIndicatorTheme->GetBigArrowBackgroundSize())
1470                     .ConvertToPx()) });
1471     auto indicatorLayoutConstraint = swiperLayoutProperty->CreateChildConstraint();
1472     arrowWrapper->Measure(indicatorLayoutConstraint);
1473 }
1474 
GetHeightForDigit(LayoutWrapper * layoutWrapper,float height) const1475 float SwiperLayoutAlgorithm::GetHeightForDigit(LayoutWrapper* layoutWrapper, float height) const
1476 {
1477     CHECK_NULL_RETURN(layoutWrapper, height);
1478     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1479     CHECK_NULL_RETURN(swiperLayoutProperty, height);
1480     auto indicatorType = swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT);
1481     if (indicatorType == SwiperIndicatorType::DIGIT) {
1482         auto indicatorWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_INDICATOR_ETS_TAG);
1483         CHECK_NULL_RETURN(indicatorWrapper, height);
1484         auto frameNode = indicatorWrapper->GetHostNode();
1485         CHECK_NULL_RETURN(frameNode, height);
1486         auto indicatorlayoutProperty = frameNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
1487         CHECK_NULL_RETURN(indicatorlayoutProperty, height);
1488         auto ignoreSize = indicatorlayoutProperty->GetIgnoreSize();
1489         if (ignoreSize.has_value() && ignoreSize.value() == true) {
1490             return 0.0f;
1491         }
1492     }
1493     return height;
1494 }
1495 
ArrowLayout(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & arrowWrapper,const PaddingPropertyF padding) const1496 void SwiperLayoutAlgorithm::ArrowLayout(
1497     LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& arrowWrapper, const PaddingPropertyF padding) const
1498 {
1499     CHECK_NULL_VOID(layoutWrapper);
1500     CHECK_NULL_VOID(arrowWrapper);
1501     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(layoutWrapper->GetLayoutProperty());
1502     CHECK_NULL_VOID(swiperLayoutProperty);
1503     auto axis = swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
1504     auto indicatorType = swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT);
1505     auto arrowGeometryNode = arrowWrapper->GetGeometryNode();
1506     CHECK_NULL_VOID(arrowGeometryNode);
1507     auto arrowFrameSize = arrowGeometryNode->GetFrameSize();
1508     auto layoutGeometryNode = layoutWrapper->GetGeometryNode();
1509     CHECK_NULL_VOID(layoutGeometryNode);
1510     auto swiperFrameSize = layoutGeometryNode->GetFrameSize();
1511     auto isShowIndicatorArrow =
1512         (!swiperLayoutProperty->GetIsSidebarMiddleValue(false) && swiperLayoutProperty->GetShowIndicatorValue(true));
1513     SizeF indicatorFrameSize;
1514     RectF indicatorFrameRect;
1515     auto normalArrowMargin = 0.0f;
1516     if (isShowIndicatorArrow) {
1517         auto indicatorWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::SWIPER_INDICATOR_ETS_TAG);
1518         CHECK_NULL_VOID(indicatorWrapper);
1519         auto indicatorGeometry = indicatorWrapper->GetGeometryNode();
1520         CHECK_NULL_VOID(indicatorGeometry);
1521         indicatorFrameSize = indicatorGeometry->GetFrameSize();
1522         indicatorFrameRect = indicatorGeometry->GetFrameRect();
1523         if (indicatorType == SwiperIndicatorType::DOT) {
1524             auto hostNode = layoutWrapper->GetHostNode();
1525             CHECK_NULL_VOID(hostNode);
1526             auto swiperPattern = hostNode->GetPattern<SwiperPattern>();
1527             CHECK_NULL_VOID(swiperPattern);
1528             auto itemCount = swiperPattern->TotalCount();
1529             auto indicatorNode = indicatorWrapper->GetHostNode();
1530             CHECK_NULL_VOID(indicatorNode);
1531             auto pipeline = PipelineBase::GetCurrentContext();
1532             CHECK_NULL_VOID(pipeline);
1533             auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
1534             CHECK_NULL_VOID(theme);
1535             auto indicatorPaintProperty = indicatorNode->GetPaintProperty<DotIndicatorPaintProperty>();
1536             CHECK_NULL_VOID(indicatorPaintProperty);
1537             auto itemWidth =
1538                 static_cast<float>(indicatorPaintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx());
1539             auto selectedItemWidth =
1540                 static_cast<float>(indicatorPaintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx());
1541             auto indicatorPadding = static_cast<float>(theme->GetIndicatorDotPadding().ConvertToPx());
1542             auto allPointDiameterSum = itemWidth * static_cast<float>(itemCount + 1);
1543             if (indicatorPaintProperty->GetIsCustomSizeValue(false)) {
1544                 allPointDiameterSum = itemWidth * static_cast<float>(itemCount - 1) + selectedItemWidth;
1545             }
1546             auto indicatorDotItemSpace = indicatorPaintProperty->GetSpaceValue(theme->GetIndicatorDotItemSpace());
1547             auto allPointSpaceSum =
1548                 static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (itemCount - 1);
1549             auto indicatorWidth = indicatorPadding + allPointDiameterSum + allPointSpaceSum + indicatorPadding;
1550             normalArrowMargin = ((axis == Axis::HORIZONTAL ? indicatorFrameSize.Width() : indicatorFrameSize.Height()) -
1551                                     indicatorWidth) * 0.5f;
1552         }
1553     }
1554     auto isLeftArrow = arrowWrapper->GetHostTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG;
1555     auto pipelineContext = PipelineBase::GetCurrentContext();
1556     CHECK_NULL_VOID(pipelineContext);
1557     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1558     CHECK_NULL_VOID(swiperIndicatorTheme);
1559     OffsetF arrowOffset(0.0f, 0.0f);
1560     float startPoint = 0.0f;
1561     if (axis == Axis::HORIZONTAL && isShowIndicatorArrow) {
1562         auto indicatorPadding = indicatorType == SwiperIndicatorType::DIGIT
1563                                     ? swiperIndicatorTheme->GetIndicatorDigitPadding().ConvertToPx()
1564                                     : swiperIndicatorTheme->GetIndicatorDotPadding().ConvertToPx();
1565         if (useCustomIndicatorOffset && indicatorType == SwiperIndicatorType::DIGIT) {
1566             startPoint = isLeftArrow ? (indicatorFrameRect.Left() - arrowFrameSize.Width() - indicatorPadding)
1567                                      : (indicatorFrameRect.Right() + indicatorPadding);
1568         } else {
1569             startPoint =
1570                 isLeftArrow
1571                     ? (indicatorFrameRect.Left() - arrowFrameSize.Width() -
1572                           swiperIndicatorTheme->GetArrowScale().ConvertToPx() + indicatorPadding + normalArrowMargin)
1573                     : (indicatorFrameRect.Right() + swiperIndicatorTheme->GetArrowScale().ConvertToPx() -
1574                           indicatorPadding - normalArrowMargin);
1575         }
1576         arrowOffset.SetX(startPoint);
1577         if (isLeftArrow && !NonNegative(arrowOffset.GetX() - padding.left.value_or(0.0f))) {
1578             arrowOffset.SetX(padding.left.value_or(0.0f));
1579         }
1580         if (GreatOrEqual(
1581             arrowOffset.GetX() + arrowFrameSize.Width(), swiperFrameSize.Width() - padding.right.value_or(0.0f))) {
1582             arrowOffset.SetX(swiperFrameSize.Width() - arrowFrameSize.Width() - padding.right.value_or(0.0f));
1583         }
1584         auto offsetY = indicatorFrameRect.Top() +
1585             (indicatorFrameSize.Height() - GetHeightForDigit(layoutWrapper, arrowFrameSize.Height())) * 0.5f;
1586         arrowOffset.SetY(offsetY);
1587     } else if (axis == Axis::HORIZONTAL && !isShowIndicatorArrow) {
1588         startPoint = isLeftArrow
1589                          ? swiperIndicatorTheme->GetArrowHorizontalMargin().ConvertToPx() + padding.left.value_or(0.0f)
1590                          : (swiperFrameSize.Width() - padding.right.value_or(0.0f) - arrowFrameSize.Width() -
1591                                swiperIndicatorTheme->GetArrowHorizontalMargin().ConvertToPx());
1592         arrowOffset.SetX(startPoint);
1593         arrowOffset.SetY((swiperFrameSize.Height() - padding.top.value_or(0.0f) - padding.bottom.value_or(0.0f) -
1594                              arrowFrameSize.Height()) *
1595                              0.5f +
1596                          padding.top.value_or(0.0f));
1597     } else if (axis != Axis::HORIZONTAL && isShowIndicatorArrow) {
1598         auto indicatorPadding = indicatorType == SwiperIndicatorType::DIGIT
1599                                     ? swiperIndicatorTheme->GetIndicatorDigitPadding().ConvertToPx()
1600                                     : swiperIndicatorTheme->GetIndicatorDotPadding().ConvertToPx();
1601         if (useCustomIndicatorOffset && indicatorType == SwiperIndicatorType::DIGIT) {
1602             startPoint = isLeftArrow ? (indicatorFrameRect.Top() - arrowFrameSize.Height() -
1603                                            padding.top.value_or(0.0f) - indicatorPadding)
1604                                      : (indicatorFrameRect.Bottom() + padding.bottom.value_or(0.0f) + indicatorPadding);
1605         } else {
1606             startPoint =
1607                 isLeftArrow
1608                     ? (indicatorFrameRect.Top() - arrowFrameSize.Height() - padding.top.value_or(0.0f) -
1609                           swiperIndicatorTheme->GetArrowScale().ConvertToPx() + indicatorPadding + normalArrowMargin)
1610                     : (indicatorFrameRect.Bottom() + padding.bottom.value_or(0.0f) +
1611                           swiperIndicatorTheme->GetArrowScale().ConvertToPx() - indicatorPadding - normalArrowMargin);
1612         }
1613         arrowOffset.SetX(indicatorFrameRect.Left() + (indicatorFrameSize.Width() - arrowFrameSize.Width()) * 0.5f);
1614         arrowOffset.SetY(startPoint);
1615         if (isLeftArrow && !NonNegative(arrowOffset.GetY() - padding.top.value_or(0.0f))) {
1616             arrowOffset.SetY(padding.top.value_or(0.0f));
1617         }
1618         if (GreatOrEqual(arrowOffset.GetY() + arrowFrameSize.Height(),
1619             swiperFrameSize.Height() - padding.bottom.value_or(0.0f))) {
1620             arrowOffset.SetY(swiperFrameSize.Height() - arrowFrameSize.Height() - padding.bottom.value_or(0.0f));
1621         }
1622     } else {
1623         startPoint = isLeftArrow
1624                          ? swiperIndicatorTheme->GetArrowVerticalMargin().ConvertToPx() + padding.top.value_or(0.0f)
1625                          : (swiperFrameSize.Height() - arrowFrameSize.Width() - padding.bottom.value_or(0.0f) -
1626                                swiperIndicatorTheme->GetArrowVerticalMargin().ConvertToPx());
1627         arrowOffset.SetX(padding.left.value_or(0.0f) + (swiperFrameSize.Width() - padding.left.value_or(0.0f) -
1628                                                            padding.right.value_or(0.0f) - arrowFrameSize.Width()) *
1629                                                            0.5f);
1630         arrowOffset.SetY(startPoint);
1631     }
1632     arrowGeometryNode->SetMarginFrameOffset(arrowOffset);
1633     arrowWrapper->Layout();
1634 }
1635 
ResetOffscreenItemPosition(LayoutWrapper * layoutWrapper,int32_t index,bool isForward) const1636 void SwiperLayoutAlgorithm::ResetOffscreenItemPosition(
1637     LayoutWrapper* layoutWrapper, int32_t index, bool isForward) const
1638 {
1639     auto swiperGeometryNode = layoutWrapper->GetGeometryNode();
1640     CHECK_NULL_VOID(swiperGeometryNode);
1641     auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
1642     CHECK_NULL_VOID(childWrapper);
1643 
1644     if (childWrapper->GetHostTag() == V2::SWIPER_INDICATOR_ETS_TAG ||
1645         childWrapper->GetHostTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG ||
1646         childWrapper->GetHostTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
1647         return;
1648     }
1649 
1650     auto childGeometryNode = childWrapper->GetGeometryNode();
1651     CHECK_NULL_VOID(childGeometryNode);
1652     auto swiperFrameRect = swiperGeometryNode->GetFrameRect();
1653     auto childFrameRect = childGeometryNode->GetFrameRect();
1654 
1655     OffsetF offset(0.0f, 0.0f);
1656     if (axis_ == Axis::HORIZONTAL) {
1657         offset.SetX(isForward ? -childFrameRect.Width() : swiperFrameRect.Width());
1658     } else {
1659         offset.SetY(isForward ? -childFrameRect.Height() : swiperFrameRect.Height());
1660     }
1661 
1662     childGeometryNode->SetMarginFrameOffset(offset);
1663     childWrapper->Layout();
1664 }
1665 
IsNormalItem(const RefPtr<LayoutWrapper> & wrapper) const1666 bool SwiperLayoutAlgorithm::IsNormalItem(const RefPtr<LayoutWrapper>& wrapper) const
1667 {
1668     CHECK_NULL_RETURN(wrapper, false);
1669     auto tag = wrapper->GetHostTag();
1670     if (tag == V2::SWIPER_INDICATOR_ETS_TAG || tag == V2::SWIPER_LEFT_ARROW_ETS_TAG ||
1671         tag == V2::SWIPER_RIGHT_ARROW_ETS_TAG || tag == V2::SWIPER_LEFT_CAPTURE_ETS_TAG ||
1672         tag == V2::SWIPER_RIGHT_CAPTURE_ETS_TAG) {
1673         return false;
1674     }
1675     return true;
1676 }
1677 
CheckCachedItem(int32_t startIndex,int32_t endIndex,LayoutWrapper * layoutWrapper)1678 void SwiperLayoutAlgorithm::CheckCachedItem(int32_t startIndex, int32_t endIndex, LayoutWrapper* layoutWrapper)
1679 {
1680     if (!layoutWrapper || cachedShow_) {
1681         return;
1682     }
1683     if (startIndex <= endIndex) {
1684         for (auto i = startIndex; i <= endIndex; ++i) {
1685             activeItems_.insert(i);
1686         }
1687     } else {
1688         for (auto i = 0; i <= endIndex; ++i) {
1689             activeItems_.insert(i);
1690         }
1691         for (auto i = startIndex; i < totalItemCount_; ++i) {
1692             activeItems_.insert(i);
1693         }
1694     }
1695     auto cachedCount = cachedCount_;
1696     while (cachedCount > 0) {
1697         if (isLoop_) {
1698             startIndex = GetLoopIndex(startIndex - 1);
1699             endIndex = GetLoopIndex(endIndex + 1);
1700         } else {
1701             startIndex = startIndex >= 0 ? startIndex - 1 : startIndex;
1702             endIndex = endIndex < totalItemCount_ ? endIndex + 1 : endIndex;
1703         }
1704         if (startIndex >= 0) {
1705             if (activeItems_.find(startIndex) == activeItems_.end()
1706                 && layoutWrapper->GetChildByIndex(startIndex, true) == nullptr) {
1707                 cachedItems_.insert(startIndex);
1708             }
1709         }
1710         if (endIndex < totalItemCount_) {
1711             if (activeItems_.find(endIndex) == activeItems_.end()
1712                 && layoutWrapper->GetChildByIndex(endIndex, true) == nullptr) {
1713                 cachedItems_.insert(endIndex);
1714             }
1715         }
1716         --cachedCount;
1717     }
1718     if (swipeByGroup_) {
1719         for (auto i = realTotalCount_; i < totalItemCount_; ++i) {
1720             activeItems_.erase(i);
1721             cachedItems_.erase(i);
1722         }
1723     }
1724 }
1725 } // namespace OHOS::Ace::NG
1726