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