• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_pattern.h"
17 
18 #include <algorithm>
19 #include <cmath>
20 #include <cstdint>
21 #include <optional>
22 
23 #include "base/geometry/axis.h"
24 #include "base/geometry/dimension.h"
25 #include "base/geometry/ng/offset_t.h"
26 #include "base/ressched/ressched_report.h"
27 #include "base/utils/utils.h"
28 #include "core/animation/curve.h"
29 #include "core/animation/curves.h"
30 #include "core/animation/spring_curve.h"
31 #include "core/common/container_scope.h"
32 #include "core/components/common/layout/constants.h"
33 #include "core/components_ng/pattern/swiper/swiper_layout_algorithm.h"
34 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
35 #include "core/components_ng/pattern/swiper/swiper_model.h"
36 #include "core/components_ng/pattern/swiper/swiper_paint_property.h"
37 #include "core/components_ng/pattern/swiper/swiper_utils.h"
38 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_arrow_pattern.h"
39 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_pattern.h"
40 #include "core/components_ng/property/measure_utils.h"
41 #include "core/components_ng/property/property.h"
42 #include "core/components_ng/syntax/for_each_node.h"
43 #include "core/components_ng/syntax/lazy_for_each_node.h"
44 #include "core/components_v2/inspector/inspector_constants.h"
45 #include "core/event/ace_events.h"
46 #include "core/event/touch_event.h"
47 #include "core/pipeline_ng/pipeline_context.h"
48 
49 namespace OHOS::Ace::NG {
50 namespace {
51 
52 // TODO use theme.
53 constexpr int32_t MIN_TURN_PAGE_VELOCITY = 1200;
54 constexpr Dimension INDICATOR_BORDER_RADIUS = 16.0_vp;
55 
56 constexpr Dimension SWIPER_MARGIN = 16.0_vp;
57 constexpr Dimension SWIPER_GUTTER = 16.0_vp;
58 constexpr float PX_EPSILON = 0.01f;
59 // TODO define as common method
CalculateFriction(float gamma)60 float CalculateFriction(float gamma)
61 {
62     constexpr float SCROLL_RATIO = 0.72f;
63     if (GreatOrEqual(gamma, 1.0)) {
64         gamma = 1.0;
65     }
66     return SCROLL_RATIO * static_cast<float>(std::pow(1.0 - gamma, SQUARE));
67 }
68 
69 } // namespace
70 
SwiperPattern()71 SwiperPattern::SwiperPattern()
72 {
73     swiperController_ = MakeRefPtr<SwiperController>();
74 }
75 
OnAttachToFrameNode()76 void SwiperPattern::OnAttachToFrameNode()
77 {
78     auto host = GetHost();
79     CHECK_NULL_VOID(host);
80     host->GetRenderContext()->SetClipToFrame(true);
81     host->GetRenderContext()->SetClipToBounds(true);
82     host->GetRenderContext()->UpdateClipEdge(true);
83     InitSurfaceChangedCallback();
84 }
85 
OnDetachFromFrameNode(FrameNode * node)86 void SwiperPattern::OnDetachFromFrameNode(FrameNode* node)
87 {
88     auto pipeline = PipelineContext::GetCurrentContext();
89     CHECK_NULL_VOID(pipeline);
90     if (HasSurfaceChangedCallback()) {
91         LOGD("Unregister surface change callback with id %{public}d", surfaceChangedCallbackId_.value_or(-1));
92         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
93     }
94 }
95 
CreateLayoutAlgorithm()96 RefPtr<LayoutAlgorithm> SwiperPattern::CreateLayoutAlgorithm()
97 {
98     auto host = GetHost();
99     CHECK_NULL_RETURN(host, nullptr);
100     auto swiperPaintProperty = host->GetPaintProperty<SwiperPaintProperty>();
101     auto swiperLayoutProperty = host->GetLayoutProperty<SwiperLayoutProperty>();
102     auto swiperLayoutAlgorithm = MakeRefPtr<SwiperLayoutAlgorithm>();
103     if (jumpIndex_) {
104         swiperLayoutAlgorithm->SetJumpIndex(jumpIndex_.value());
105     } else if (targetIndex_) {
106         swiperLayoutAlgorithm->SetTargetIndex(targetIndex_.value());
107     }
108     swiperLayoutAlgorithm->SetContentCrossSize(contentCrossSize_);
109     swiperLayoutAlgorithm->SetMainSizeIsMeasured(mainSizeIsMeasured_);
110     swiperLayoutAlgorithm->SetContentMainSize(contentMainSize_);
111     swiperLayoutAlgorithm->SetCurrentDelta(currentDelta_);
112     swiperLayoutAlgorithm->SetItemsPosition(itemPosition_);
113     swiperLayoutAlgorithm->SetIsNeedResetPrevMarginAndNextMargin();
114     if (IsOutOfBoundary() && !IsLoop()) {
115         swiperLayoutAlgorithm->SetOverScrollFeature();
116     }
117     swiperLayoutAlgorithm->SetTotalItemCount(TotalCount());
118     swiperLayoutAlgorithm->SetIsLoop(IsLoop());
119     auto effect = swiperPaintProperty->GetEdgeEffect().value_or(EdgeEffect::SPRING);
120     bool canOverScroll = effect == EdgeEffect::SPRING;
121     swiperLayoutAlgorithm->SetCanOverScroll(canOverScroll);
122     return swiperLayoutAlgorithm;
123 }
124 
OnIndexChange() const125 void SwiperPattern::OnIndexChange() const
126 {
127     auto totalCount = TotalCount();
128     if (NonPositive(totalCount)) {
129         return;
130     }
131 
132     auto oldIndex = GetLoopIndex(oldIndex_);
133     auto targetIndex = GetLoopIndex(CurrentIndex());
134     if (oldIndex != targetIndex) {
135         auto swiperEventHub = GetEventHub<SwiperEventHub>();
136         CHECK_NULL_VOID(swiperEventHub);
137         swiperEventHub->FireChangeEvent(targetIndex);
138         swiperEventHub->FireChangeDoneEvent(moveDirection_);
139         // lazyBuild feature.
140         SetLazyLoadFeature(true);
141     }
142 }
143 
StopAndResetSpringAnimation()144 void SwiperPattern::StopAndResetSpringAnimation()
145 {
146     if (springController_ && !springController_->IsStopped()) {
147         springController_->Stop();
148         currentDelta_ = 0.0f;
149         itemPosition_.clear();
150         isVoluntarilyClear_ = true;
151         jumpIndex_ = currentIndex_;
152     }
153 }
154 
OnLoopChange()155 void SwiperPattern::OnLoopChange()
156 {
157     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
158     CHECK_NULL_VOID(layoutProperty);
159 
160     if (!preLoop_.has_value()) {
161         preLoop_ = layoutProperty->GetLoop().value_or(true);
162         return;
163     }
164 
165     if (preLoop_.value() != layoutProperty->GetLoop().value_or(true) &&
166         (layoutProperty->GetPrevMargin().has_value() || layoutProperty->GetNextMargin().has_value())) {
167         jumpIndex_ = GetLoopIndex(currentIndex_);
168         preLoop_ = layoutProperty->GetLoop().value_or(true);
169     }
170 }
171 
OnModifyDone()172 void SwiperPattern::OnModifyDone()
173 {
174     currentOffset_ = 0.0f;
175     Pattern::OnModifyDone();
176     auto host = GetHost();
177     CHECK_NULL_VOID(host);
178     auto hub = host->GetEventHub<EventHub>();
179     CHECK_NULL_VOID(hub);
180     auto gestureHub = hub->GetOrCreateGestureEventHub();
181     CHECK_NULL_VOID(gestureHub);
182     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
183     CHECK_NULL_VOID(layoutProperty);
184     InitIndicator();
185     InitArrow();
186     SetLazyLoadIsLoop();
187     RegisterVisibleAreaChange();
188     InitSwiperController();
189     InitTouchEvent(gestureHub);
190     InitHoverMouseEvent();
191     StopAndResetSpringAnimation();
192     OnLoopChange();
193     if ((layoutProperty->GetPropertyChangeFlag() & PROPERTY_UPDATE_MEASURE) == PROPERTY_UPDATE_MEASURE) {
194         StopPropertyTranslateAnimation();
195         StopTranslateAnimation();
196         StopSpringAnimation();
197         StopFadeAnimation();
198         if (indicatorController_) {
199             indicatorController_->Stop();
200         }
201         currentOffset_ = 0.0f;
202         mainSizeIsMeasured_ = false;
203         itemPosition_.clear();
204         isVoluntarilyClear_ = true;
205         jumpIndex_ = currentIndex_;
206         for (const auto& child : host->GetChildren()) {
207             if (child->GetTag() == V2::JS_LAZY_FOR_EACH_ETS_TAG) {
208                 auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(child);
209                 CHECK_NULL_VOID(lazyForEachNode);
210                 lazyForEachNode->SetFlagForGeneratedItem(PROPERTY_UPDATE_MEASURE);
211             }
212         }
213     }
214     if (IsDisableSwipe()) {
215         if (panEvent_) {
216             gestureHub->RemovePanEvent(panEvent_);
217             panEvent_.Reset();
218         }
219         return;
220     }
221     InitPanEvent(gestureHub);
222     auto focusHub = host->GetFocusHub();
223     if (focusHub) {
224         InitOnKeyEvent(focusHub);
225     }
226     auto removeSwiperEventCallback = [weak = WeakClaim(this)]() {
227         auto swiperPattern = weak.Upgrade();
228         CHECK_NULL_VOID(swiperPattern);
229         auto host = swiperPattern->GetHost();
230         CHECK_NULL_VOID(host);
231         auto hub = host->GetEventHub<EventHub>();
232         CHECK_NULL_VOID(hub);
233         auto gestureHub = hub->GetOrCreateGestureEventHub();
234         CHECK_NULL_VOID(gestureHub);
235         gestureHub->RemoveTouchEvent(swiperPattern->touchEvent_);
236         if (!swiperPattern->IsDisableSwipe()) {
237             gestureHub->RemovePanEvent(swiperPattern->panEvent_);
238         }
239     };
240     swiperController_->SetRemoveSwiperEventCallback(std::move(removeSwiperEventCallback));
241 
242     auto addSwiperEventCallback = [weak = WeakClaim(this)]() {
243         auto swiperPattern = weak.Upgrade();
244         CHECK_NULL_VOID(swiperPattern);
245         auto host = swiperPattern->GetHost();
246         CHECK_NULL_VOID(host);
247         auto hub = host->GetEventHub<EventHub>();
248         CHECK_NULL_VOID(hub);
249         auto gestureHub = hub->GetOrCreateGestureEventHub();
250         CHECK_NULL_VOID(gestureHub);
251         gestureHub->AddTouchEvent(swiperPattern->touchEvent_);
252         if (!swiperPattern->IsDisableSwipe()) {
253             gestureHub->AddPanEvent(swiperPattern->panEvent_, swiperPattern->panDirection_, 1, DEFAULT_PAN_DISTANCE);
254         }
255     };
256     swiperController_->SetAddSwiperEventCallback(std::move(addSwiperEventCallback));
257 
258     auto updateCubicCurveCallback = [weak = WeakClaim(this)]() {
259         auto swiperPattern = weak.Upgrade();
260         CHECK_NULL_VOID(swiperPattern);
261         auto host = swiperPattern->GetHost();
262         CHECK_NULL_VOID(host);
263         auto swiperPaintProperty = host->GetPaintProperty<SwiperPaintProperty>();
264         CHECK_NULL_VOID(swiperPaintProperty);
265         auto curve = MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
266         swiperPaintProperty->UpdateCurve(curve);
267     };
268     swiperController_->SetUpdateCubicCurveCallback(std::move(updateCubicCurveCallback));
269 
270     if (IsAutoPlay()) {
271         StartAutoPlay();
272     } else {
273         translateTask_.Cancel();
274     }
275 
276     SetAccessibilityAction();
277 }
278 
BeforeCreateLayoutWrapper()279 void SwiperPattern::BeforeCreateLayoutWrapper()
280 {
281     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
282     CHECK_NULL_VOID(layoutProperty);
283     oldIndex_ = currentIndex_;
284     auto userSetCurrentIndex = CurrentIndex();
285     if (userSetCurrentIndex < 0 || userSetCurrentIndex >= TotalCount()) {
286         currentIndex_ = 0;
287         layoutProperty->UpdateIndexWithoutMeasure(GetLoopIndex(currentIndex_));
288     } else {
289         if (GetLoopIndex(currentIndex_) != userSetCurrentIndex) {
290             currentIndex_ = userSetCurrentIndex;
291         }
292     }
293     if (oldIndex_ != currentIndex_ || (itemPosition_.empty() && !isVoluntarilyClear_)) {
294         jumpIndex_ = GetLoopIndex(currentIndex_);
295         currentFirstIndex_ = jumpIndex_.value_or(0);
296         turnPageRate_ = 0.0f;
297     }
298     isVoluntarilyClear_ = false;
299     if (jumpIndex_) {
300         if ((jumpIndex_.value() < 0 || jumpIndex_.value() >= TotalCount()) && !IsLoop()) {
301             jumpIndex_ = 0;
302         }
303         targetIndex_.reset();
304         if (usePropertyAnimation_) {
305             StopPropertyTranslateAnimation(true);
306             currentDelta_ = 0.0f;
307             if (indicatorController_) {
308                 indicatorController_->Stop();
309             }
310         }
311     }
312     if (mainSizeIsMeasured_ && isNeedResetPrevMarginAndNextMargin_) {
313         layoutProperty->UpdatePrevMarginWithoutMeasure(0.0_px);
314         layoutProperty->UpdateNextMarginWithoutMeasure(0.0_px);
315     }
316 }
317 
InitSurfaceChangedCallback()318 void SwiperPattern::InitSurfaceChangedCallback()
319 {
320     auto host = GetHost();
321     CHECK_NULL_VOID(host);
322     auto pipeline = host->GetContext();
323     CHECK_NULL_VOID(pipeline);
324     if (!HasSurfaceChangedCallback()) {
325         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
326             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
327                 WindowSizeChangeReason type) {
328                 if (type == WindowSizeChangeReason::UNDEFINED) {
329                     return;
330                 }
331                 auto swiper = weak.Upgrade();
332                 if (!swiper) {
333                     return;
334                 }
335                 swiper->StopPropertyTranslateAnimation();
336                 swiper->StopTranslateAnimation();
337                 swiper->StopSpringAnimation();
338                 swiper->StopFadeAnimation();
339                 if (swiper->indicatorController_) {
340                     swiper->indicatorController_->Stop();
341                 }
342                 swiper->currentOffset_ = 0.0f;
343                 swiper->itemPosition_.clear();
344                 swiper->isVoluntarilyClear_ = true;
345                 swiper->jumpIndex_ = swiper->currentIndex_;
346                 auto swiperNode = swiper->GetHost();
347                 CHECK_NULL_VOID(swiperNode);
348                 swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
349                 for (const auto& child : swiperNode->GetChildren()) {
350                     if (child->GetTag() == V2::JS_LAZY_FOR_EACH_ETS_TAG) {
351                         auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(child);
352                         CHECK_NULL_VOID(lazyForEachNode);
353                         lazyForEachNode->SetFlagForGeneratedItem(PROPERTY_UPDATE_MEASURE);
354                     }
355                 }
356             });
357         LOGD("Add surface changed callback id %{public}d", callbackId);
358         UpdateSurfaceChangedCallbackId(callbackId);
359     }
360 }
361 
FlushFocus(const RefPtr<FrameNode> & curShowFrame)362 void SwiperPattern::FlushFocus(const RefPtr<FrameNode>& curShowFrame)
363 {
364     CHECK_NULL_VOID(curShowFrame);
365     auto swiperHost = GetHost();
366     CHECK_NULL_VOID(swiperHost);
367     auto swiperFocusHub = swiperHost->GetFocusHub();
368     CHECK_NULL_VOID(swiperFocusHub);
369     auto showChildFocusHub = curShowFrame->GetFirstFocusHubChild();
370     CHECK_NULL_VOID(showChildFocusHub);
371     auto focusChildren = swiperFocusHub->GetChildren();
372     CHECK_NULL_VOID(!focusChildren.empty());
373     auto iter = focusChildren.rbegin();
374     if (IsShowIndicator()) {
375         ++iter;
376     }
377     if (HasLeftButtonNode()) {
378         ++iter;
379     }
380     if (HasRightButtonNode()) {
381         ++iter;
382     }
383     while (iter != focusChildren.rend()) {
384         auto child = *iter;
385         if (!child) {
386             ++iter;
387             continue;
388         }
389         if (child != showChildFocusHub) {
390             child->SetParentFocusable(false);
391         } else {
392             child->SetParentFocusable(true);
393         }
394         ++iter;
395     }
396 
397     RefPtr<FocusHub> needFocusNode = showChildFocusHub;
398     if (IsShowIndicator() && isLastIndicatorFocused_) {
399         needFocusNode = GetFocusHubChild(V2::SWIPER_INDICATOR_ETS_TAG);
400     }
401     CHECK_NULL_VOID(needFocusNode);
402     lastWeakShowNode_ = AceType::WeakClaim(AceType::RawPtr(curShowFrame));
403     if (swiperFocusHub->IsCurrentFocus()) {
404         needFocusNode->RequestFocusImmediately();
405     } else {
406         swiperFocusHub->SetLastWeakFocusNode(AceType::WeakClaim(AceType::RawPtr(needFocusNode)));
407     }
408 }
GetFocusHubChild(std::string childFrameName)409 RefPtr<FocusHub> SwiperPattern::GetFocusHubChild(std::string childFrameName)
410 {
411     auto swiperHost = GetHost();
412     CHECK_NULL_RETURN(swiperHost, nullptr);
413     auto swiperFocusHub = swiperHost->GetFocusHub();
414     CHECK_NULL_RETURN(swiperFocusHub, nullptr);
415     auto focusChildren = swiperFocusHub->GetChildren();
416     CHECK_NULL_RETURN(!focusChildren.empty(), nullptr);
417     for (const auto& child : focusChildren) {
418         CHECK_NULL_RETURN(child, nullptr);
419         if (child->GetFrameName() == childFrameName) {
420             return child;
421         }
422     }
423     return nullptr;
424 }
425 
GetNextFocusNode(FocusStep step,const WeakPtr<FocusHub> & currentFocusNode)426 WeakPtr<FocusHub> SwiperPattern::GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode)
427 {
428     auto curFocusNode = currentFocusNode.Upgrade();
429     CHECK_NULL_RETURN(curFocusNode, nullptr);
430     if ((direction_ == Axis::HORIZONTAL && step == FocusStep::UP) ||
431         (direction_ == Axis::HORIZONTAL && step == FocusStep::SHIFT_TAB) ||
432         (direction_ == Axis::VERTICAL && step == FocusStep::LEFT)) {
433         return PreviousFocus(curFocusNode);
434     }
435     if ((direction_ == Axis::HORIZONTAL && step == FocusStep::DOWN) ||
436         (direction_ == Axis::HORIZONTAL && step == FocusStep::TAB) ||
437         (direction_ == Axis::VERTICAL && step == FocusStep::RIGHT)) {
438         return NextFocus(curFocusNode);
439     }
440     return nullptr;
441 }
442 
PreviousFocus(const RefPtr<FocusHub> & curFocusNode)443 WeakPtr<FocusHub> SwiperPattern::PreviousFocus(const RefPtr<FocusHub>& curFocusNode)
444 {
445     CHECK_NULL_RETURN(curFocusNode, nullptr);
446     RefPtr<FocusHub> indicatorNode;
447     RefPtr<FocusHub> leftArrowNode;
448     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
449     CHECK_NULL_RETURN(layoutProperty, nullptr);
450     if (HasLeftButtonNode()) {
451         leftArrowNode = GetFocusHubChild(V2::SWIPER_LEFT_ARROW_ETS_TAG);
452         CHECK_NULL_RETURN(leftArrowNode, nullptr);
453     }
454     if (HasIndicatorNode()) {
455         indicatorNode = GetFocusHubChild(V2::SWIPER_INDICATOR_ETS_TAG);
456         CHECK_NULL_RETURN(indicatorNode, nullptr);
457     }
458     if (curFocusNode->GetFrameName() == V2::SWIPER_LEFT_ARROW_ETS_TAG) {
459         isLastIndicatorFocused_ = false;
460         (!IsLoop() && GetLoopIndex(currentIndex_) == 0) ? curFocusNode->SetParentFocusable(false)
461                                                         : curFocusNode->SetParentFocusable(true);
462         return nullptr;
463     }
464     if (curFocusNode->GetFrameName() == V2::SWIPER_INDICATOR_ETS_TAG) {
465         if (!HasLeftButtonNode() || (!IsLoop() && GetLoopIndex(currentIndex_) == 0) ||
466             layoutProperty->GetHoverShowValue(false)) {
467             isLastIndicatorFocused_ = true;
468             curFocusNode->SetParentFocusable(true);
469             return nullptr;
470         }
471         isLastIndicatorFocused_ = false;
472         leftArrowNode->SetParentFocusable(true);
473         return AceType::WeakClaim(AceType::RawPtr(leftArrowNode));
474     }
475     if (curFocusNode->GetFrameName() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
476         if (HasIndicatorNode()) {
477             isLastIndicatorFocused_ = true;
478             indicatorNode->SetParentFocusable(true);
479             return AceType::WeakClaim(AceType::RawPtr(indicatorNode));
480         }
481         if (!IsLoop() && GetLoopIndex(currentIndex_) == 0) {
482             curFocusNode->SetParentFocusable(true);
483             return nullptr;
484         }
485         isLastIndicatorFocused_ = true;
486         leftArrowNode->SetParentFocusable(true);
487         return AceType::WeakClaim(AceType::RawPtr(leftArrowNode));
488     }
489     curFocusNode->SetParentFocusable(true);
490     return nullptr;
491 }
492 
NextFocus(const RefPtr<FocusHub> & curFocusNode)493 WeakPtr<FocusHub> SwiperPattern::NextFocus(const RefPtr<FocusHub>& curFocusNode)
494 {
495     CHECK_NULL_RETURN(curFocusNode, nullptr);
496     RefPtr<FocusHub> indicatorNode;
497     RefPtr<FocusHub> rightArrowNode;
498     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
499     CHECK_NULL_RETURN(layoutProperty, nullptr);
500     if (HasIndicatorNode()) {
501         indicatorNode = GetFocusHubChild(V2::SWIPER_INDICATOR_ETS_TAG);
502         CHECK_NULL_RETURN(indicatorNode, nullptr);
503     }
504     if (HasRightButtonNode()) {
505         rightArrowNode = GetFocusHubChild(V2::SWIPER_RIGHT_ARROW_ETS_TAG);
506         CHECK_NULL_RETURN(rightArrowNode, nullptr);
507     }
508     if (curFocusNode->GetFrameName() == V2::SWIPER_LEFT_ARROW_ETS_TAG) {
509         if (HasIndicatorNode()) {
510             isLastIndicatorFocused_ = true;
511             indicatorNode->SetParentFocusable(true);
512             return AceType::WeakClaim(AceType::RawPtr(indicatorNode));
513         }
514         if (!IsLoop() && GetLoopIndex(currentIndex_) == TotalCount() - 1) {
515             curFocusNode->SetParentFocusable(true);
516             return nullptr;
517         }
518         isLastIndicatorFocused_ = true;
519         rightArrowNode->SetParentFocusable(true);
520         return AceType::WeakClaim(AceType::RawPtr(rightArrowNode));
521     }
522     if (curFocusNode->GetFrameName() == V2::SWIPER_INDICATOR_ETS_TAG) {
523         if (!HasRightButtonNode() || (!IsLoop() && GetLoopIndex(currentIndex_) == TotalCount() - 1) ||
524             layoutProperty->GetHoverShowValue(false)) {
525             isLastIndicatorFocused_ = true;
526             curFocusNode->SetParentFocusable(true);
527             return nullptr;
528         }
529         isLastIndicatorFocused_ = false;
530         rightArrowNode->SetParentFocusable(true);
531         return AceType::WeakClaim(AceType::RawPtr(rightArrowNode));
532     }
533     if (curFocusNode->GetFrameName() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
534         isLastIndicatorFocused_ = false;
535         (!IsLoop() && GetLoopIndex(currentIndex_) == TotalCount() - 1) ? curFocusNode->SetParentFocusable(false)
536                                                                        : curFocusNode->SetParentFocusable(true);
537         return nullptr;
538     }
539     curFocusNode->SetParentFocusable(true);
540     return nullptr;
541 }
542 
GetLoopIndex(int32_t originalIndex) const543 int32_t SwiperPattern::GetLoopIndex(int32_t originalIndex) const
544 {
545     if (TotalCount() <= 0) {
546         return originalIndex;
547     }
548     auto loopIndex = originalIndex;
549     while (loopIndex < 0) {
550         loopIndex = loopIndex + TotalCount();
551     }
552     loopIndex %= TotalCount();
553     return loopIndex;
554 }
555 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)556 bool SwiperPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
557 {
558     auto isNotInit = true;
559     if (isInit_) {
560         isNotInit = false;
561         isInit_ = false;
562         // first load Swiper to preload page.
563         SetLazyLoadFeature(true);
564     } else {
565         OnIndexChange();
566         oldIndex_ = currentIndex_;
567     }
568 
569     if (!IsAutoPlay() && config.skipMeasure && config.skipLayout) {
570         return false;
571     }
572 
573     bool isJump = false;
574     auto layoutAlgorithmWrapper = dirty->GetLayoutAlgorithm();
575     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
576     auto swiperLayoutAlgorithm = DynamicCast<SwiperLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
577     CHECK_NULL_RETURN(swiperLayoutAlgorithm, false);
578     itemPosition_ = std::move(swiperLayoutAlgorithm->GetItemPosition());
579     currentOffset_ -= swiperLayoutAlgorithm->GetCurrentOffset();
580     if (!itemPosition_.empty()) {
581         const auto& turnPageRateCallback = swiperController_->GetTurnPageRateCallback();
582         if (turnPageRateCallback && isDragging_ && !NearZero(GetTranslateLength())) {
583             turnPageRateCallback(
584                 itemPosition_.begin()->first, -itemPosition_.begin()->second.startPos / GetTranslateLength());
585         }
586     }
587     auto host = GetHost();
588     CHECK_NULL_RETURN(host, false);
589     if (!targetIndex_) {
590         CheckMarkDirtyNodeForRenderIndicator();
591     }
592     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
593     CHECK_NULL_RETURN(layoutProperty, false);
594     if (jumpIndex_) {
595         isJump = true;
596         UpdateCurrentIndex(swiperLayoutAlgorithm->GetCurrentIndex());
597         auto curChild = dirty->GetOrCreateChildByIndex(GetLoopIndex(currentIndex_));
598         if (curChild) {
599             auto curChildFrame = curChild->GetHostNode();
600             CHECK_NULL_RETURN(curChildFrame, false);
601             FlushFocus(curChildFrame);
602         }
603         currentIndexOffset_ = 0.0f;
604         if (isNotInit) {
605             OnIndexChange();
606         }
607         jumpIndex_.reset();
608     } else if (targetIndex_) {
609         auto targetIndexValue = IsLoop() ? targetIndex_.value() : GetLoopIndex(targetIndex_.value());
610         auto iter = itemPosition_.find(targetIndexValue);
611         if (iter != itemPosition_.end()) {
612             float targetPos = 0.0f;
613             targetPos = iter->second.startPos;
614             auto context = PipelineContext::GetCurrentContext();
615             if (context) {
616                 // displayCount is auto, loop is false, if the content width less than windows size
617                 // need offset to keep right aligned
618                 bool isNeedOffset = (GetLoopIndex(iter->first) == TotalCount() - 1)
619                     && !layoutProperty->GetDisplayCount().has_value() && !IsLoop()
620                     && LessNotEqual(iter->second.endPos - iter->second.startPos, CalculateVisibleSize());
621                 float offset = isNeedOffset
622                     ? CalculateVisibleSize() - iter->second.endPos + iter->second.startPos : 0.0;
623                 targetPos -= offset;
624                 context->AddAfterLayoutTask([weak = WeakClaim(this), targetPos, velocity = velocity_.value_or(0.0f),
625                                                 nextIndex = iter->first]() {
626                     auto swiper = weak.Upgrade();
627                     CHECK_NULL_VOID(swiper);
628                     swiper->PlayPropertyTranslateAnimation(-targetPos, nextIndex, velocity);
629                     swiper->PlayIndicatorTranslateAnimation(-targetPos);
630                 });
631             } else {
632                 PlayTranslateAnimation(
633                     currentOffset_, currentOffset_ - targetPos, iter->first, false, velocity_.value_or(0.0f));
634             }
635             velocity_.reset();
636         }
637         pauseTargetIndex_ = targetIndex_;
638     }
639     mainSizeIsMeasured_ = swiperLayoutAlgorithm->GetMainSizeIsMeasured();
640     isNeedResetPrevMarginAndNextMargin_ = swiperLayoutAlgorithm->GetIsNeedResetPrevMarginAndNextMargin();
641     contentCrossSize_ = swiperLayoutAlgorithm->GetContentCrossSize();
642     currentDelta_ = 0.0f;
643     contentMainSize_ = swiperLayoutAlgorithm->GetContentMainSize();
644     startMainPos_ = swiperLayoutAlgorithm->GetStartPosition();
645     endMainPos_ = swiperLayoutAlgorithm->GetEndPosition();
646     startIndex_ = swiperLayoutAlgorithm->GetStartIndex();
647     endIndex_ = swiperLayoutAlgorithm->GetEndIndex();
648     oldIndex_ = currentIndex_;
649     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
650     return GetEdgeEffect() == EdgeEffect::FADE || paddingProperty != nullptr;
651 }
652 
FireChangeEvent() const653 void SwiperPattern::FireChangeEvent() const
654 {
655     auto swiperEventHub = GetEventHub<SwiperEventHub>();
656     CHECK_NULL_VOID(swiperEventHub);
657     swiperEventHub->FireChangeEvent(GetLoopIndex(currentIndex_));
658     swiperEventHub->FireIndicatorChangeEvent(GetLoopIndex(currentIndex_));
659     swiperEventHub->FireChangeDoneEvent(moveDirection_);
660 }
661 
FireAnimationStartEvent(int32_t currentIndex,int32_t nextIndex,const AnimationCallbackInfo & info) const662 void SwiperPattern::FireAnimationStartEvent(
663     int32_t currentIndex, int32_t nextIndex, const AnimationCallbackInfo& info) const
664 {
665     auto swiperEventHub = GetEventHub<SwiperEventHub>();
666     CHECK_NULL_VOID(swiperEventHub);
667     swiperEventHub->FireAnimationStartEvent(currentIndex, nextIndex, info);
668 }
669 
FireAnimationEndEvent(int32_t currentIndex,const AnimationCallbackInfo & info) const670 void SwiperPattern::FireAnimationEndEvent(int32_t currentIndex, const AnimationCallbackInfo& info) const
671 {
672     if (currentIndex == -1) {
673         return;
674     }
675     auto swiperEventHub = GetEventHub<SwiperEventHub>();
676     CHECK_NULL_VOID(swiperEventHub);
677     swiperEventHub->FireAnimationEndEvent(currentIndex, info);
678 }
679 
FireGestureSwipeEvent(int32_t currentIndex,const AnimationCallbackInfo & info) const680 void SwiperPattern::FireGestureSwipeEvent(int32_t currentIndex, const AnimationCallbackInfo& info) const
681 {
682     auto swiperEventHub = GetEventHub<SwiperEventHub>();
683     CHECK_NULL_VOID(swiperEventHub);
684     swiperEventHub->FireGestureSwipeEvent(currentIndex, info);
685 }
686 
SwipeToWithoutAnimation(int32_t index)687 void SwiperPattern::SwipeToWithoutAnimation(int32_t index)
688 {
689     LOGD("Swipe to index: %{public}d without animation", index);
690     if (IsVisibleChildrenSizeLessThanSwiper()) {
691         return;
692     }
693 
694     if (usePropertyAnimation_) {
695         StopPropertyTranslateAnimation();
696     }
697 
698     StopFadeAnimation();
699     StopSpringAnimation();
700     auto host = GetHost();
701     CHECK_NULL_VOID(host);
702     jumpIndex_ = index;
703     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
704 }
705 
StopSpringAnimationAndFlushImmediately()706 void SwiperPattern::StopSpringAnimationAndFlushImmediately()
707 {
708     if (springController_ && !springController_->IsStopped()) {
709         springController_->Stop();
710         currentDelta_ = 0.0f;
711         itemPosition_.clear();
712         isVoluntarilyClear_ = true;
713         jumpIndex_ = currentIndex_;
714         auto host = GetHost();
715         CHECK_NULL_VOID(host);
716         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
717         auto pipeline = PipelineContext::GetCurrentContext();
718         if (pipeline) {
719             pipeline->FlushUITasks();
720         }
721     }
722 }
723 
SwipeTo(int32_t index)724 void SwiperPattern::SwipeTo(int32_t index)
725 {
726     LOGD("Swipe to index: %{public}d with animation, duration: %{public}d", index, GetDuration());
727     if (IsVisibleChildrenSizeLessThanSwiper()) {
728         return;
729     }
730     auto host = GetHost();
731     CHECK_NULL_VOID(host);
732     auto targetIndex = IsLoop() ? index : (index < 0 || index > (TotalCount() - 1)) ? 0 : index;
733     targetIndex = IsLoop() ? targetIndex : std::clamp(targetIndex, 0, TotalCount() - GetDisplayCount());
734     // If targetIndex_ has a value, means animation is still running, stop it before play new animation.
735     if (currentIndex_ == targetIndex && !targetIndex_.has_value()) {
736         LOGD("Target index %{public}d is same with current index %{public}d.", targetIndex, currentIndex_);
737         return;
738     }
739     StopFadeAnimation();
740     if (springController_ && !springController_->IsStopped()) {
741         springController_->Stop();
742         jumpIndex_ = currentIndex_;
743         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
744         auto pipeline = PipelineContext::GetCurrentContext();
745         if (pipeline) {
746             pipeline->FlushUITasks();
747         }
748     }
749     StopAutoPlay();
750     StopTranslateAnimation();
751 
752     if (indicatorController_) {
753         indicatorController_->Stop();
754     }
755     if (usePropertyAnimation_) {
756         StopPropertyTranslateAnimation();
757     }
758 
759     targetIndex_ = targetIndex;
760 
761     if (GetDuration() == 0 || !isVisible_) {
762         SwipeToWithoutAnimation(index);
763         return;
764     }
765 
766     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
767 }
768 
ShowNext()769 void SwiperPattern::ShowNext()
770 {
771     LOGI("SwiperPattern::ShowNext");
772     if (IsVisibleChildrenSizeLessThanSwiper()) {
773         return;
774     }
775     indicatorDoingAnimation_ = false;
776     auto host = GetHost();
777     CHECK_NULL_VOID(host);
778     auto childrenSize = TotalCount();
779     std::optional<int32_t> preIndex;
780     if (preTargetIndex_.has_value()) {
781         if (GetLoopIndex(preTargetIndex_.value()) >= childrenSize - GetDisplayCount() && !IsLoop()) {
782             LOGW("already last one, can't show next");
783             return;
784         }
785         preIndex = preTargetIndex_.value();
786     } else if (GetLoopIndex(currentIndex_) >= childrenSize - GetDisplayCount() && !IsLoop()) {
787         LOGW("already last one, can't show next");
788         return;
789     }
790     if (childrenSize <= 0 || GetDisplayCount() == 0) {
791         return;
792     }
793     StopAutoPlay();
794     StopTranslateAnimation();
795 
796     StopSpringAnimationAndFlushImmediately();
797     StopFadeAnimation();
798 
799     if (indicatorController_) {
800         indicatorController_->Stop();
801     }
802     if (preIndex) {
803         isUserFinish_ = false;
804         FinishAnimation();
805     }
806     moveDirection_ = true;
807 
808     if (isVisible_) {
809         targetIndex_ = currentIndex_ + 1;
810         preTargetIndex_ = targetIndex_;
811         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
812         auto pipeline = PipelineContext::GetCurrentContext();
813         if (pipeline) {
814             pipeline->FlushUITasks();
815         }
816     } else {
817         SwipeToWithoutAnimation(currentIndex_ + 1);
818     }
819     auto swiperEventHub = GetEventHub<SwiperEventHub>();
820     CHECK_NULL_VOID(swiperEventHub);
821     swiperEventHub->FireIndicatorChangeEvent(GetLoopIndex(currentIndex_));
822 }
823 
ShowPrevious()824 void SwiperPattern::ShowPrevious()
825 {
826     if (IsVisibleChildrenSizeLessThanSwiper()) {
827         return;
828     }
829     indicatorDoingAnimation_ = false;
830     auto host = GetHost();
831     CHECK_NULL_VOID(host);
832     auto childrenSize = TotalCount();
833     std::optional<int32_t> preIndex;
834     if (preTargetIndex_.has_value()) {
835         if (GetLoopIndex(preTargetIndex_.value()) <= 0 && !IsLoop()) {
836             LOGW("already last one, can't show next");
837             return;
838         }
839         preIndex = preTargetIndex_.value();
840     } else if (GetLoopIndex(currentIndex_) <= 0 && !IsLoop()) {
841         LOGW("already last one, can't show next");
842         return;
843     }
844     if (childrenSize <= 0 || GetDisplayCount() == 0) {
845         return;
846     }
847     StopAutoPlay();
848     StopTranslateAnimation();
849     StopSpringAnimationAndFlushImmediately();
850     StopFadeAnimation();
851 
852     if (indicatorController_) {
853         indicatorController_->Stop();
854     }
855     if (preIndex) {
856         isUserFinish_ = false;
857         FinishAnimation();
858     }
859     moveDirection_ = false;
860 
861     if (isVisible_) {
862         targetIndex_ = currentIndex_ - 1;
863         preTargetIndex_ = targetIndex_;
864         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
865         auto pipeline = PipelineContext::GetCurrentContext();
866         if (pipeline) {
867             pipeline->FlushUITasks();
868         }
869     } else {
870         SwipeToWithoutAnimation(currentIndex_ - 1);
871     }
872     auto swiperEventHub = GetEventHub<SwiperEventHub>();
873     CHECK_NULL_VOID(swiperEventHub);
874     swiperEventHub->FireIndicatorChangeEvent(GetLoopIndex(currentIndex_));
875 }
876 
FinishAnimation()877 void SwiperPattern::FinishAnimation()
878 {
879     LOGI("SwiperPattern::FinishAnimation start");
880     StopTranslateAnimation();
881     if (indicatorController_) {
882         indicatorController_->Stop();
883     }
884     if (usePropertyAnimation_) {
885         isFinishAnimation_ = true;
886         StopPropertyTranslateAnimation();
887     }
888     if (isUserFinish_) {
889         if (swiperController_ && swiperController_->GetFinishCallback()) {
890             LOGI("SwiperPattern::FinishAnimation execute finish callback.");
891             swiperController_->GetFinishCallback()();
892         }
893     } else {
894         isUserFinish_ = true;
895     }
896 }
897 
StopTranslateAnimation()898 void SwiperPattern::StopTranslateAnimation()
899 {
900     if (controller_ && !controller_->IsStopped()) {
901         isFinishAnimation_ = true;
902         controller_->Stop();
903     }
904 }
905 
StopSpringAnimation()906 void SwiperPattern::StopSpringAnimation()
907 {
908     if (springController_ && !springController_->IsStopped()) {
909         springController_->Stop();
910     }
911 }
912 
StopFadeAnimation()913 void SwiperPattern::StopFadeAnimation()
914 {
915     if (fadeController_ && !fadeController_->IsStopped()) {
916         fadeController_->Stop();
917     }
918 }
919 
InitSwiperController()920 void SwiperPattern::InitSwiperController()
921 {
922     if (swiperController_->HasInitialized()) {
923         return;
924     }
925 
926     swiperController_->SetSwipeToImpl([weak = WeakClaim(this)](int32_t index, bool reverse) {
927         auto swiper = weak.Upgrade();
928         if (swiper) {
929             swiper->SwipeTo(index);
930         }
931     });
932 
933     swiperController_->SetSwipeToWithoutAnimationImpl([weak = WeakClaim(this)](int32_t index) {
934         auto swiper = weak.Upgrade();
935         if (swiper) {
936             swiper->SwipeToWithoutAnimation(index);
937         }
938     });
939 
940     swiperController_->SetShowNextImpl([weak = WeakClaim(this)]() {
941         auto swiper = weak.Upgrade();
942         if (swiper) {
943             swiper->ShowNext();
944         }
945     });
946 
947     swiperController_->SetShowPrevImpl([weak = WeakClaim(this)]() {
948         auto swiper = weak.Upgrade();
949         if (swiper) {
950             swiper->ShowPrevious();
951         }
952     });
953 
954     swiperController_->SetFinishImpl([weak = WeakClaim(this)]() {
955         auto swiper = weak.Upgrade();
956         if (swiper) {
957             swiper->FinishAnimation();
958         }
959     });
960 }
961 
InitIndicator()962 void SwiperPattern::InitIndicator()
963 {
964     auto swiperNode = GetHost();
965     CHECK_NULL_VOID(swiperNode);
966     RefPtr<FrameNode> indicatorNode;
967     if (!HasIndicatorNode()) {
968         LOGI("Swiper create new indicator");
969         if (!IsShowIndicator()) {
970             return;
971         }
972         indicatorNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_INDICATOR_ETS_TAG, GetIndicatorId(),
973             []() { return AceType::MakeRefPtr<SwiperIndicatorPattern>(); });
974         swiperNode->AddChild(indicatorNode);
975     } else {
976         LOGI("Swiper indicator already exist");
977         indicatorNode =
978             DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(GetIndicatorId())));
979         CHECK_NULL_VOID(indicatorNode);
980         if (!IsShowIndicator()) {
981             RemoveIndicatorNode();
982             return;
983         }
984         if (GetIndicatorType() == SwiperIndicatorType::DIGIT && lastSwiperIndicatorType_ == SwiperIndicatorType::DOT) {
985             RemoveIndicatorNode();
986             indicatorNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_INDICATOR_ETS_TAG, GetIndicatorId(),
987                 []() { return AceType::MakeRefPtr<SwiperIndicatorPattern>(); });
988             swiperNode->AddChild(indicatorNode);
989         }
990     }
991     lastSwiperIndicatorType_ = GetIndicatorType();
992     CHECK_NULL_VOID(indicatorNode);
993     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
994     CHECK_NULL_VOID(layoutProperty);
995     if (layoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT) == SwiperIndicatorType::DOT) {
996         SaveDotIndicatorProperty(indicatorNode);
997     } else {
998         SaveDigitIndicatorProperty(indicatorNode);
999     }
1000 
1001     auto renderContext = indicatorNode->GetRenderContext();
1002     CHECK_NULL_VOID(renderContext);
1003     BorderRadiusProperty radius;
1004     radius.SetRadius(INDICATOR_BORDER_RADIUS);
1005     renderContext->UpdateBorderRadius(radius);
1006 
1007     indicatorNode->MarkModifyDone();
1008     indicatorNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1009 }
1010 
InitArrow()1011 void SwiperPattern::InitArrow()
1012 {
1013     auto swiperNode = GetHost();
1014     CHECK_NULL_VOID(swiperNode);
1015     RefPtr<FrameNode> leftArrow;
1016     RefPtr<FrameNode> rightArrow;
1017     if (!HasLeftButtonNode() && !HasRightButtonNode()) {
1018         if (!IsShowArrow()) {
1019             return;
1020         }
1021         leftArrow = FrameNode::GetOrCreateFrameNode(V2::SWIPER_LEFT_ARROW_ETS_TAG, GetLeftButtonId(),
1022             []() { return AceType::MakeRefPtr<SwiperArrowPattern>(); });
1023         swiperNode->AddChild(leftArrow);
1024         rightArrow = FrameNode::GetOrCreateFrameNode(V2::SWIPER_RIGHT_ARROW_ETS_TAG, GetRightButtonId(),
1025             []() { return AceType::MakeRefPtr<SwiperArrowPattern>(); });
1026         swiperNode->AddChild(rightArrow);
1027     } else {
1028         leftArrow =
1029             DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(GetLeftButtonId())));
1030         CHECK_NULL_VOID(leftArrow);
1031         rightArrow =
1032             DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(GetRightButtonId())));
1033         CHECK_NULL_VOID(rightArrow);
1034         if (!IsShowArrow()) {
1035             RemoveLeftButtonNode();
1036             RemoveRightButtonNode();
1037             return;
1038         }
1039     }
1040 
1041     SaveArrowProperty(leftArrow);
1042     SaveArrowProperty(rightArrow);
1043 
1044     leftArrow->MarkModifyDone();
1045     rightArrow->MarkModifyDone();
1046 }
1047 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)1048 void SwiperPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1049 {
1050     if (direction_ == GetDirection() && panEvent_) {
1051         return;
1052     }
1053     direction_ = GetDirection();
1054 
1055     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1056         LOGD("Pan event start");
1057         auto pattern = weak.Upgrade();
1058         if (pattern) {
1059             if (info.GetInputEventType() == InputEventType::AXIS && info.GetSourceTool() == SourceTool::MOUSE) {
1060                 return;
1061             }
1062             pattern->HandleDragStart();
1063         }
1064     };
1065 
1066     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1067         auto pattern = weak.Upgrade();
1068         if (pattern) {
1069             if (info.GetInputEventType() == InputEventType::AXIS && info.GetSourceTool() == SourceTool::MOUSE) {
1070                 if (GreatNotEqual(info.GetMainDelta(), 0.0)) {
1071                     pattern->ShowPrevious();
1072                 } else if (LessNotEqual(info.GetMainDelta(), 0.0)) {
1073                     pattern->ShowNext();
1074                 }
1075             } else {
1076                 pattern->HandleDragUpdate(info);
1077             }
1078         }
1079     };
1080 
1081     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1082         LOGD("Pan event end mainVelocity: %{public}lf", info.GetMainVelocity());
1083         auto pattern = weak.Upgrade();
1084         if (pattern) {
1085             if (info.GetInputEventType() == InputEventType::AXIS && info.GetSourceTool() == SourceTool::MOUSE) {
1086                 return;
1087             }
1088             pattern->HandleDragEnd(info.GetMainVelocity());
1089         }
1090     };
1091 
1092     auto actionCancelTask = [weak = WeakClaim(this)]() {
1093         LOGD("Pan event cancel");
1094         auto pattern = weak.Upgrade();
1095         if (pattern) {
1096             pattern->HandleDragEnd(0.0);
1097         }
1098     };
1099 
1100     if (GetDirection() == Axis::VERTICAL) {
1101         panDirection_.type = PanDirection::VERTICAL;
1102     } else {
1103         panDirection_.type = PanDirection::HORIZONTAL;
1104     }
1105     if (panEvent_) {
1106         gestureHub->RemovePanEvent(panEvent_);
1107     }
1108 
1109     panEvent_ = MakeRefPtr<PanEvent>(
1110         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1111     gestureHub->AddPanEvent(panEvent_, panDirection_, 1, DEFAULT_PAN_DISTANCE);
1112 }
1113 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)1114 void SwiperPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
1115 {
1116     if (touchEvent_) {
1117         return;
1118     }
1119 
1120     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
1121         auto pattern = weak.Upgrade();
1122         if (pattern) {
1123             pattern->HandleTouchEvent(info);
1124         }
1125     };
1126 
1127     if (touchEvent_) {
1128         gestureHub->RemoveTouchEvent(touchEvent_);
1129     }
1130     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
1131     gestureHub->AddTouchEvent(touchEvent_);
1132 }
1133 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)1134 void SwiperPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1135 {
1136     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1137         auto pattern = wp.Upgrade();
1138         if (pattern) {
1139             return pattern->OnKeyEvent(event);
1140         }
1141         return false;
1142     };
1143     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1144 }
1145 
OnKeyEvent(const KeyEvent & event)1146 bool SwiperPattern::OnKeyEvent(const KeyEvent& event)
1147 {
1148     if (event.action != KeyAction::DOWN) {
1149         return false;
1150     }
1151     if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_LEFT) ||
1152         (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_UP)) {
1153         ShowPrevious();
1154         return true;
1155     }
1156     if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_RIGHT) ||
1157         (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_DOWN)) {
1158         ShowNext();
1159         return true;
1160     }
1161     return false;
1162 }
1163 
StopAutoPlay()1164 void SwiperPattern::StopAutoPlay()
1165 {
1166     if (IsAutoPlay()) {
1167         translateTask_.Cancel();
1168     }
1169 }
1170 
StartAutoPlay()1171 void SwiperPattern::StartAutoPlay()
1172 {
1173     if (NeedAutoPlay()) {
1174         PostTranslateTask(GetInterval());
1175     }
1176 }
1177 
OnVisibleChange(bool isVisible)1178 void SwiperPattern::OnVisibleChange(bool isVisible)
1179 {
1180     isVisible_ = isVisible;
1181     if (isInit_) {
1182         return;
1183     }
1184 
1185     if (!isVisible_) {
1186         StopAutoPlay();
1187         return;
1188     }
1189 
1190     if (NeedStartAutoPlay()) {
1191         StartAutoPlay();
1192     }
1193 }
1194 
UpdateCurrentOffset(float offset)1195 void SwiperPattern::UpdateCurrentOffset(float offset)
1196 {
1197     if (IsVisibleChildrenSizeLessThanSwiper() && !IsAutoFill()) {
1198         return;
1199     }
1200     if (itemPosition_.empty()) {
1201         return;
1202     }
1203     auto edgeEffect = GetEdgeEffect();
1204     auto isOutOfBoundary = isTouchPad_ ? IsOutOfBoundary(offset) : IsOutOfBoundary();
1205     if (!IsLoop() && isOutOfBoundary && edgeEffect == EdgeEffect::SPRING) {
1206         LOGD("Swiper has reached boundary, can't drag any more, effect spring.");
1207 
1208         targetIndex_.reset();
1209 
1210         auto visibleSize = CalculateVisibleSize();
1211         if (LessOrEqual(visibleSize, 0.0)) {
1212             return;
1213         }
1214         auto friction = currentOffset_ > 0
1215                             ? CalculateFriction(itemPosition_.begin()->second.startPos / visibleSize)
1216                             : CalculateFriction((visibleSize - itemPosition_.rbegin()->second.endPos) / visibleSize);
1217 
1218         currentDelta_ = currentDelta_ - friction * offset;
1219         if (isDragging_) {
1220             currentIndexOffset_ += friction * offset;
1221             AnimationCallbackInfo callbackInfo;
1222             callbackInfo.currentOffset =
1223                 GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1224             FireGestureSwipeEvent(GetLoopIndex(gestureSwipeIndex_), callbackInfo);
1225         }
1226     } else if (!IsLoop() && IsOutOfBoundary(offset) &&
1227                (edgeEffect == EdgeEffect::FADE || edgeEffect == EdgeEffect::NONE)) {
1228         currentDelta_ = currentDelta_ - offset;
1229         if (edgeEffect == EdgeEffect::FADE) {
1230             auto host = GetHost();
1231             CHECK_NULL_VOID(host);
1232             if (itemPosition_.begin()->first == 0 || itemPosition_.rbegin()->first == TotalCount() - 1) {
1233                 auto remainOffset = GetRemainingOffset();
1234                 fadeOffset_ += (offset - remainOffset);
1235             }
1236             host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1237         }
1238     } else {
1239         currentDelta_ = currentDelta_ - offset;
1240         currentIndexOffset_ += offset;
1241         if (isDragging_) {
1242             AnimationCallbackInfo callbackInfo;
1243             callbackInfo.currentOffset =
1244                 GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1245             FireGestureSwipeEvent(GetLoopIndex(gestureSwipeIndex_), callbackInfo);
1246         }
1247     }
1248     auto host = GetHost();
1249     CHECK_NULL_VOID(host);
1250     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1251 }
1252 
CheckMarkDirtyNodeForRenderIndicator(float additionalOffset)1253 void SwiperPattern::CheckMarkDirtyNodeForRenderIndicator(float additionalOffset)
1254 {
1255     auto host = GetHost();
1256     CHECK_NULL_VOID(host);
1257     if (!indicatorId_.has_value()) {
1258         return;
1259     }
1260     auto child = DynamicCast<FrameNode>(host->GetChildAtIndex(host->GetChildIndexById(GetIndicatorId())));
1261     CHECK_NULL_VOID(child);
1262 
1263     if (child->GetTag() != V2::SWIPER_INDICATOR_ETS_TAG) {
1264         return;
1265     }
1266     auto currentShowIndex = 0;
1267     for (const auto& iter : itemPosition_) {
1268         if ((iter.second.startPos + additionalOffset) < 0 && (iter.second.endPos + additionalOffset) < 0) {
1269             continue;
1270         }
1271         if ((iter.second.startPos + additionalOffset) >= 0 && (iter.second.endPos + additionalOffset) > 0) {
1272             currentShowIndex = iter.first;
1273             turnPageRate_ = 0.0f;
1274             break;
1275         }
1276         if ((iter.second.endPos + additionalOffset) > 0) {
1277             currentShowIndex = iter.first;
1278             turnPageRate_ = (iter.second.startPos + additionalOffset) / (iter.second.endPos - iter.second.startPos);
1279             break;
1280         }
1281     }
1282     currentFirstIndex_ = GetLoopIndex(currentShowIndex);
1283     if (!IsLoop() && ((currentFirstIndex_ == 0 && turnPageRate_ > 0.0f) ||
1284                          (currentFirstIndex_ == TotalCount() - 1 && turnPageRate_ < 0.0f))) {
1285         return;
1286     }
1287 
1288     if (!indicatorDoingAnimation_) {
1289         child->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1290     }
1291     if (GetLoopIndex(currentIndex_) != GetLoopIndex(currentShowIndex)) {
1292         auto swiperEventHub = GetEventHub<SwiperEventHub>();
1293         CHECK_NULL_VOID(swiperEventHub);
1294         swiperEventHub->FireIndicatorChangeEvent(GetLoopIndex(currentShowIndex));
1295     }
1296 }
1297 
UpdateAnimationProperty(float velocity)1298 void SwiperPattern::UpdateAnimationProperty(float velocity)
1299 {
1300     if (isDragging_) {
1301         targetIndex_ = ComputeNextIndexByVelocity(velocity);
1302         velocity_ = velocity;
1303     } else {
1304         targetIndex_ = pauseTargetIndex_;
1305         velocity_ = velocity;
1306     }
1307 
1308     auto host = GetHost();
1309     CHECK_NULL_VOID(host);
1310     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1311     moveDirection_ = velocity <= 0;
1312 }
1313 
OnTouchTestHit(SourceType hitTestType)1314 void SwiperPattern::OnTouchTestHit(SourceType hitTestType)
1315 {
1316     // in mouse hover test case.
1317     if (hitTestType == SourceType::MOUSE) {
1318         return;
1319     }
1320     if (!isTouchDown_) {
1321         isTouchDown_ = true;
1322     }
1323 }
1324 
HandleTouchEvent(const TouchEventInfo & info)1325 void SwiperPattern::HandleTouchEvent(const TouchEventInfo& info)
1326 {
1327     auto touchType = info.GetTouches().front().GetTouchType();
1328     if (touchType == TouchType::DOWN) {
1329         HandleTouchDown();
1330     } else if (touchType == TouchType::UP) {
1331         HandleTouchUp();
1332     } else if (touchType == TouchType::CANCEL) {
1333         HandleTouchUp();
1334     }
1335 }
1336 
HandleTouchDown()1337 void SwiperPattern::HandleTouchDown()
1338 {
1339     if (indicatorController_) {
1340         indicatorController_->Stop();
1341     }
1342     if (usePropertyAnimation_) {
1343         StopPropertyTranslateAnimation();
1344     }
1345 
1346     indicatorDoingAnimation_ = false;
1347     // Stop translate animation when touch down.
1348     if (controller_ && controller_->IsRunning()) {
1349         controller_->Stop();
1350     }
1351 
1352     if (springController_ && springController_->IsRunning()) {
1353         springController_->Pause();
1354     }
1355 
1356     // Stop auto play when touch down.
1357     StopAutoPlay();
1358 }
1359 
HandleTouchUp()1360 void SwiperPattern::HandleTouchUp()
1361 {
1362     isTouchDown_ = false;
1363     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
1364     if (!isDragging_ && !NearZero(firstItemInfoInVisibleArea.second.startPos)) {
1365         UpdateAnimationProperty(0.0);
1366     }
1367 
1368     if (springController_ && springController_->GetStatus() == Animator::Status::PAUSED) {
1369         springController_->Resume();
1370     }
1371 
1372     StartAutoPlay();
1373 }
1374 
HandleDragStart()1375 void SwiperPattern::HandleDragStart()
1376 {
1377     if (usePropertyAnimation_) {
1378         StopPropertyTranslateAnimation();
1379     }
1380     if (indicatorController_) {
1381         indicatorController_->Stop();
1382     }
1383     StopTranslateAnimation();
1384     StopSpringAnimationAndFlushImmediately();
1385     StopAutoPlay();
1386 
1387     const auto& tabBarFinishCallback = swiperController_->GetTabBarFinishCallback();
1388     if (tabBarFinishCallback) {
1389         tabBarFinishCallback();
1390     }
1391 
1392     const auto& removeEventCallback = swiperController_->GetRemoveTabBarEventCallback();
1393     if (removeEventCallback) {
1394         removeEventCallback();
1395     }
1396 #ifdef OHOS_PLATFORM
1397     // Increase the cpu frequency when sliding.
1398     ResSchedReport::GetInstance().ResSchedDataReport("slide_on");
1399 #endif
1400 
1401     gestureSwipeIndex_ = currentIndex_;
1402     isDragging_ = true;
1403     mainDeltaSum_ = 0.0f;
1404     // in drag process, close lazy feature.
1405     SetLazyLoadFeature(false);
1406 }
1407 
HandleDragUpdate(const GestureEvent & info)1408 void SwiperPattern::HandleDragUpdate(const GestureEvent& info)
1409 {
1410     auto mainDelta = static_cast<float>(info.GetMainDelta());
1411     if (info.GetInputEventType() == InputEventType::AXIS && info.GetSourceTool() == SourceTool::TOUCHPAD) {
1412         isTouchPad_ = true;
1413         auto mainSize = CalculateVisibleSize();
1414         if ((mainDeltaSum_ + std::abs(mainDelta)) > mainSize) {
1415             mainDelta = mainDelta > 0 ? (mainSize - mainDeltaSum_) : (mainDeltaSum_ - mainSize);
1416             mainDeltaSum_ = mainSize;
1417         } else {
1418             mainDeltaSum_ += std::abs(mainDelta);
1419         }
1420     }
1421 
1422     auto dragPoint =
1423         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
1424     if (IsOutOfHotRegion(dragPoint)) {
1425         isTouchPad_ = false;
1426         return;
1427     }
1428 
1429     UpdateCurrentOffset(static_cast<float>(mainDelta));
1430     UpdateItemRenderGroup(true);
1431     isTouchPad_ = false;
1432 }
1433 
HandleDragEnd(double dragVelocity)1434 void SwiperPattern::HandleDragEnd(double dragVelocity)
1435 {
1436     if (IsVisibleChildrenSizeLessThanSwiper()) {
1437         return;
1438     }
1439     const auto& addEventCallback = swiperController_->GetAddTabBarEventCallback();
1440     if (addEventCallback) {
1441         addEventCallback();
1442     }
1443     LOGD("Drag end velocity: %{public}lf, currentOffset: %{public}lf", dragVelocity, currentOffset_);
1444 
1445     auto pipeline = PipelineContext::GetCurrentContext();
1446     if (pipeline) {
1447         pipeline->FlushUITasks();
1448     }
1449     if (itemPosition_.empty()) {
1450         return;
1451     }
1452 
1453     // Play edge effect animation.
1454     auto edgeEffect = GetEdgeEffect();
1455     bool noneOutOfBoundary = (itemPosition_.begin()->first == 0 || itemPosition_.rbegin()->first == TotalCount() - 1) &&
1456                              NearZero(GetRemainingOffset()) && edgeEffect == EdgeEffect::NONE;
1457     if (!IsLoop() && (IsOutOfBoundary() || !NearZero(fadeOffset_) || noneOutOfBoundary)) {
1458         isDragging_ = false;
1459 
1460         if (edgeEffect == EdgeEffect::SPRING) {
1461             PlaySpringAnimation(dragVelocity);
1462             return;
1463         }
1464 
1465         if (edgeEffect == EdgeEffect::FADE) {
1466             PlayFadeAnimation();
1467             return;
1468         }
1469 
1470         auto nextIndex = ComputeNextIndexByVelocity(static_cast<float>(dragVelocity), true);
1471         nextIndex = std::clamp(nextIndex, 0, TotalCount() - GetDisplayCount());
1472         if (currentIndex_ != nextIndex) {
1473             UpdateCurrentIndex(nextIndex);
1474             do {
1475                 auto host = GetHost();
1476                 if (!host) {
1477                     break;
1478                 }
1479                 auto curChild = host->GetChildAtIndex(currentIndex_);
1480                 if (!curChild) {
1481                     break;
1482                 }
1483                 auto curChildFrame = AceType::DynamicCast<FrameNode>(curChild);
1484                 if (!curChildFrame) {
1485                     break;
1486                 }
1487                 FlushFocus(curChildFrame);
1488             } while (0);
1489             OnIndexChange();
1490             oldIndex_ = currentIndex_;
1491         }
1492 
1493         if (edgeEffect == EdgeEffect::NONE) {
1494             return;
1495         }
1496     }
1497 
1498 #ifdef OHOS_PLATFORM
1499     ResSchedReport::GetInstance().ResSchedDataReport("slide_off");
1500 #endif
1501 
1502     UpdateAnimationProperty(static_cast<float>(dragVelocity));
1503 
1504     if (pipeline) {
1505         pipeline->FlushUITasks();
1506     }
1507 
1508     isDragging_ = false;
1509 }
1510 
UpdateCurrentIndex(int32_t index)1511 void SwiperPattern::UpdateCurrentIndex(int32_t index)
1512 {
1513     currentIndex_ = index;
1514     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
1515     CHECK_NULL_VOID(layoutProperty);
1516     layoutProperty->UpdateIndexWithoutMeasure(GetLoopIndex(currentIndex_));
1517 }
1518 
ComputeNextIndexByVelocity(float velocity,bool onlyDistance) const1519 int32_t SwiperPattern::ComputeNextIndexByVelocity(float velocity, bool onlyDistance) const
1520 {
1521     auto nextIndex = currentIndex_;
1522     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
1523     auto firstItemLength = firstItemInfoInVisibleArea.second.endPos - firstItemInfoInVisibleArea.second.startPos;
1524     if (LessOrEqual(firstItemLength, 0)) {
1525         LOGE("Main size is not positive.");
1526         return nextIndex;
1527     }
1528 
1529     auto direction = GreatNotEqual(velocity, 0.0);
1530     auto dragThresholdFlag = direction ? firstItemInfoInVisibleArea.second.endPos > firstItemLength / 2
1531                                        : firstItemInfoInVisibleArea.second.endPos < firstItemLength / 2;
1532     if ((!onlyDistance && std::abs(velocity) > MIN_TURN_PAGE_VELOCITY) || dragThresholdFlag) {
1533         nextIndex = direction ? firstItemInfoInVisibleArea.first : firstItemInfoInVisibleArea.first + 1;
1534     } else {
1535         nextIndex = direction ? firstItemInfoInVisibleArea.first + 1 : firstItemInfoInVisibleArea.first;
1536     }
1537 
1538     return nextIndex;
1539 }
1540 
PlayPropertyTranslateAnimation(float translate,int32_t nextIndex,float velocity)1541 void SwiperPattern::PlayPropertyTranslateAnimation(float translate, int32_t nextIndex, float velocity)
1542 {
1543     if (NearZero(translate)) {
1544         ResetAndUpdateIndexOnAnimationEnd(nextIndex);
1545         return;
1546     }
1547 
1548     AnimationOption option;
1549     option.SetDuration(GetDuration());
1550     option.SetCurve(GetCurveIncludeMotion(velocity / translate));
1551     OffsetF offset;
1552     if (GetDirection() == Axis::HORIZONTAL) {
1553         offset.AddX(translate);
1554     } else {
1555         offset.AddY(translate);
1556     }
1557     if (usePropertyAnimation_) {
1558         auto startNewAnimationFlag = false;
1559         if (itemPositionInAnimation_.empty()) {
1560             startNewAnimationFlag = true;
1561         }
1562         if (!startNewAnimationFlag) {
1563             for (const auto& animaitonItem : itemPositionInAnimation_) {
1564                 auto iter = itemPosition_.find(animaitonItem.first);
1565                 if (iter == itemPosition_.end()) {
1566                     startNewAnimationFlag = true;
1567                     break;
1568                 }
1569                 if (animaitonItem.second.finialOffset != offset ||
1570                     !NearEqual(animaitonItem.second.startPos, iter->second.startPos) ||
1571                     !NearEqual(animaitonItem.second.endPos, iter->second.endPos)) {
1572                     startNewAnimationFlag = true;
1573                     break;
1574                 }
1575             }
1576         }
1577         if (!startNewAnimationFlag) {
1578             stopIndicatorAnimation_ = false;
1579             return;
1580         }
1581         std::optional<int32_t> targetIndex;
1582         if (targetIndex_) {
1583             targetIndex = targetIndex_;
1584         }
1585         StopPropertyTranslateAnimation();
1586         if (indicatorController_) {
1587             indicatorController_->Stop();
1588         }
1589         if (targetIndex) {
1590             targetIndex_ = targetIndex;
1591             auto host = GetHost();
1592             CHECK_NULL_VOID(host);
1593             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1594             return;
1595         }
1596     }
1597     auto finishCallback = [id = Container::CurrentId(), weak = WeakClaim(this), offset]() {
1598         ContainerScope scope(id);
1599         auto context = PipelineContext::GetCurrentContext();
1600         CHECK_NULL_VOID(context);
1601         auto task = [weak, offset]() {
1602             auto swiper = weak.Upgrade();
1603             CHECK_NULL_VOID(swiper);
1604             swiper->targetIndex_.reset();
1605             swiper->OnPropertyTranslateAnimationFinish(offset);
1606         };
1607         context->PostSyncEvent(task);
1608     };
1609     // initial translate info.
1610     for (auto& item : itemPosition_) {
1611         auto frameNode = item.second.node;
1612         if (frameNode) {
1613             frameNode->GetRenderContext()->UpdateTranslateInXY(item.second.finialOffset);
1614         }
1615     }
1616     // property callback will call immediately.
1617     auto propertyUpdateCallback = [swiper = WeakClaim(this), offset]() {
1618         auto swiperPattern = swiper.Upgrade();
1619         if (!swiperPattern) {
1620             return;
1621         }
1622         for (auto& item : swiperPattern->itemPosition_) {
1623             auto frameNode = item.second.node;
1624             if (frameNode) {
1625                 frameNode->GetRenderContext()->UpdateTranslateInXY(offset);
1626                 item.second.finialOffset = offset;
1627             }
1628         }
1629         swiperPattern->itemPositionInAnimation_ = swiperPattern->itemPosition_;
1630     };
1631     usePropertyAnimation_ = true;
1632     propertyAnimationIndex_ = nextIndex;
1633     AnimationUtils::Animate(option, propertyUpdateCallback, finishCallback);
1634     AnimationCallbackInfo info;
1635     info.velocity = Dimension(velocity, DimensionUnit::PX).ConvertToVp();
1636     info.currentOffset = GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1637     info.targetOffset = GetCustomPropertyOffset() - Dimension(translate, DimensionUnit::PX).ConvertToVp();
1638 
1639     auto pipeline = PipelineContext::GetCurrentContext();
1640     if (pipeline) {
1641         pipeline->AddAfterRenderTask([weak = WeakClaim(this), info, nextIndex = GetLoopIndex(nextIndex)]() {
1642             auto swiper = weak.Upgrade();
1643             CHECK_NULL_VOID(swiper);
1644             swiper->FireAnimationStartEvent(swiper->GetLoopIndex(swiper->currentIndex_), nextIndex, info);
1645         });
1646     }
1647 
1648     // enable lazy load feature.
1649     SetLazyLoadFeature(true);
1650     UpdateItemRenderGroup(true);
1651 }
1652 
UpdateOffsetAfterPropertyAnimation(float offset)1653 void SwiperPattern::UpdateOffsetAfterPropertyAnimation(float offset)
1654 {
1655     UpdateCurrentOffset(offset);
1656     auto pipeline = PipelineContext::GetCurrentContext();
1657     if (pipeline) {
1658         pipeline->FlushUITasks();
1659     }
1660 }
1661 
OnPropertyTranslateAnimationFinish(const OffsetF & offset)1662 void SwiperPattern::OnPropertyTranslateAnimationFinish(const OffsetF& offset)
1663 {
1664     if (!usePropertyAnimation_) {
1665         // force stop.
1666         return;
1667     }
1668     if (indicatorController_) {
1669         indicatorController_->Stop();
1670     }
1671     usePropertyAnimation_ = false;
1672     // reset translate.
1673     for (auto& item : itemPositionInAnimation_) {
1674         auto frameNode = item.second.node;
1675         if (frameNode) {
1676             frameNode->GetRenderContext()->UpdateTranslateInXY(OffsetF());
1677         }
1678         item.second.finialOffset = OffsetF();
1679     }
1680     itemPositionInAnimation_.clear();
1681     // update postion info.
1682     UpdateOffsetAfterPropertyAnimation(offset.GetMainOffset(GetDirection()));
1683     OnTranslateFinish(propertyAnimationIndex_, false);
1684 }
1685 
StopPropertyTranslateAnimation(bool isBeforeCreateLayoutWrapper)1686 void SwiperPattern::StopPropertyTranslateAnimation(bool isBeforeCreateLayoutWrapper)
1687 {
1688     if (!usePropertyAnimation_) {
1689         return;
1690     }
1691     usePropertyAnimation_ = false;
1692     // Stop CurrentAnimationProperty.
1693     OffsetF currentOffset;
1694     for (auto& item : itemPositionInAnimation_) {
1695         auto frameNode = item.second.node;
1696         if (!frameNode) {
1697             continue;
1698         }
1699         currentOffset = frameNode->GetRenderContext()->GetShowingTranslateProperty();
1700         frameNode->GetRenderContext()->UpdateTranslateInXY(OffsetF());
1701         item.second.finialOffset = OffsetF();
1702     }
1703     itemPositionInAnimation_.clear();
1704     if (!isBeforeCreateLayoutWrapper) {
1705         UpdateOffsetAfterPropertyAnimation(currentOffset.GetMainOffset(GetDirection()));
1706     }
1707     OnTranslateFinish(propertyAnimationIndex_, false, true);
1708 }
1709 
GetCurveIncludeMotion(float velocity) const1710 RefPtr<Curve> SwiperPattern::GetCurveIncludeMotion(float velocity) const
1711 {
1712     auto curve = GetCurve();
1713     auto container = Container::Current();
1714     bool isLauncherFeature = container ? container->IsLauncherContainer() : false;
1715     if (!curve && !isLauncherFeature) {
1716         curve = Curves::LINEAR;
1717     }
1718     if (curve) {
1719         if (InstanceOf<SpringCurve>(curve)) {
1720             auto springCurve = DynamicCast<SpringCurve>(curve);
1721             // check velocity to judge if this current velocity.
1722             if (springCurve->GetCurrentVelocity() < 0) {
1723                 springCurve->UpdateVelocity(velocity);
1724             }
1725         }
1726         if (InstanceOf<InterpolatingSpring>(curve)) {
1727             auto interpolatingSpring = DynamicCast<InterpolatingSpring>(curve);
1728             // check velocity to judge if this current velocity.
1729             if (interpolatingSpring->GetVelocity() < 0) {
1730                 return AceType::MakeRefPtr<InterpolatingSpring>(velocity, interpolatingSpring->GetMass(),
1731                     interpolatingSpring->GetStiffness(), interpolatingSpring->GetDamping());
1732             }
1733         }
1734         return curve;
1735     }
1736     // use spring motion feature.
1737     // interpolatingSpring: (mass: 1, stiffness:328, damping: 34)
1738     return AceType::MakeRefPtr<InterpolatingSpring>(velocity, 1, 328, 34);
1739 }
1740 
PlayIndicatorTranslateAnimation(float translate)1741 void SwiperPattern::PlayIndicatorTranslateAnimation(float translate)
1742 {
1743     if (!stopIndicatorAnimation_) {
1744         stopIndicatorAnimation_ = true;
1745         return;
1746     }
1747     const auto& turnPageRateCallback = swiperController_->GetTurnPageRateCallback();
1748     if (!indicatorId_.has_value() && !turnPageRateCallback) {
1749         return;
1750     }
1751     auto host = GetHost();
1752     CHECK_NULL_VOID(host);
1753     if (!indicatorController_) {
1754         indicatorController_ = CREATE_ANIMATOR(host->GetContext());
1755     }
1756     indicatorController_->Stop();
1757     indicatorController_->ClearStartListeners();
1758     indicatorController_->ClearStopListeners();
1759     indicatorController_->ClearInterpolators();
1760 
1761     auto translateAnimation = AceType::MakeRefPtr<CurveAnimation<double>>(0, translate, Curves::LINEAR);
1762     if (itemPosition_.empty()) {
1763         return;
1764     }
1765     translateAnimation->AddListener(Animation<double>::ValueCallback(
1766         [weak = WeakClaim(this), currentContentOffset = -itemPosition_.begin()->second.startPos,
1767             index = itemPosition_.begin()->first](double value) {
1768             auto swiper = weak.Upgrade();
1769             CHECK_NULL_VOID(swiper);
1770             const auto& turnPageRateCallback = swiper->swiperController_->GetTurnPageRateCallback();
1771             if (turnPageRateCallback && !NearZero(swiper->GetTranslateLength())) {
1772                 turnPageRateCallback(index, (currentContentOffset - value) / swiper->GetTranslateLength());
1773             }
1774             swiper->CheckMarkDirtyNodeForRenderIndicator(static_cast<float>(value));
1775         }));
1776     indicatorController_->SetDuration(GetDuration());
1777     indicatorController_->AddInterpolator(translateAnimation);
1778     indicatorController_->Play();
1779 }
1780 
PlayTranslateAnimation(float startPos,float endPos,int32_t nextIndex,bool restartAutoPlay,float velocity)1781 void SwiperPattern::PlayTranslateAnimation(
1782     float startPos, float endPos, int32_t nextIndex, bool restartAutoPlay, float velocity)
1783 {
1784     auto host = GetHost();
1785     CHECK_NULL_VOID(host);
1786     auto curve = GetCurve();
1787 
1788     // If animation is still running, stop it before play new animation.
1789     StopSpringAnimation();
1790     StopFadeAnimation();
1791     StopTranslateAnimation();
1792     StopAutoPlay();
1793 
1794     SetLazyLoadFeature(false);
1795 
1796     if (!controller_) {
1797         controller_ = CREATE_ANIMATOR(host->GetContext());
1798     }
1799     controller_->ClearStartListeners();
1800     controller_->ClearStopListeners();
1801     controller_->ClearInterpolators();
1802 
1803     auto weak = WeakClaim(this);
1804     auto targetOffset = Dimension(startPos - endPos, DimensionUnit::PX).ConvertToVp();
1805     controller_->AddStartListener([weak, nextIndex, targetOffset, velocity]() {
1806         auto swiper = weak.Upgrade();
1807         CHECK_NULL_VOID(swiper);
1808         AnimationCallbackInfo info;
1809         info.velocity = Dimension(velocity, DimensionUnit::PX).ConvertToVp();
1810         info.currentOffset =
1811             swiper->GetCustomPropertyOffset() + Dimension(swiper->currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1812         info.targetOffset = swiper->GetCustomPropertyOffset() + targetOffset;
1813         swiper->FireAnimationStartEvent(
1814             swiper->GetLoopIndex(swiper->currentIndex_), swiper->GetLoopIndex(nextIndex), info);
1815     });
1816 
1817     auto container = Container::Current();
1818     bool isLauncherFeature = container ? container->IsLauncherContainer() : false;
1819     if (!curve && !isLauncherFeature) {
1820         curve = Curves::LINEAR;
1821     }
1822 
1823     if (curve) {
1824         auto currentIndexStartPos = currentIndexOffset_;
1825         auto translate = AceType::MakeRefPtr<CurveAnimation<double>>(startPos, endPos, curve);
1826         translate->AddListener(
1827             Animation<double>::ValueCallback([weak, startPos, endPos, currentIndexStartPos](double value) {
1828                 auto swiper = weak.Upgrade();
1829                 CHECK_NULL_VOID(swiper);
1830                 if (!NearEqual(value, startPos) && !NearEqual(value, endPos) && !NearEqual(startPos, endPos)) {
1831                     float moveRate =
1832                         Curves::EASE_OUT->MoveInternal(static_cast<float>((value - startPos) / (endPos - startPos)));
1833                     value = startPos + (endPos - startPos) * moveRate;
1834                     auto moveOffset = (endPos - startPos) * moveRate;
1835                     swiper->currentIndexOffset_ = currentIndexStartPos + moveOffset;
1836                 }
1837                 swiper->UpdateCurrentOffset(static_cast<float>(value - swiper->currentOffset_));
1838             }));
1839         controller_->AddStopListener([weak, nextIndex, restartAutoPlay]() {
1840             auto swiper = weak.Upgrade();
1841             CHECK_NULL_VOID(swiper);
1842             swiper->OnTranslateFinish(nextIndex, restartAutoPlay);
1843         });
1844         controller_->SetDuration(GetDuration());
1845         controller_->AddInterpolator(translate);
1846         controller_->Play();
1847         return;
1848     }
1849     // use spring motion feature.
1850     // interpolatingSpring: (mass: 1, stiffness:328, damping: 34)
1851     static const auto springProperty = AceType::MakeRefPtr<SpringProperty>(1, 328, 34);
1852     auto scrollMotion = AceType::MakeRefPtr<SpringMotion>(startPos, endPos, velocity, springProperty);
1853     scrollMotion->AddListener([weak](double value) {
1854         auto swiper = weak.Upgrade();
1855         if (swiper) {
1856             swiper->UpdateCurrentOffset(static_cast<float>(value) - swiper->currentOffset_);
1857         }
1858     });
1859     controller_->AddStopListener([weak, nextIndex, restartAutoPlay]() {
1860         auto swiper = weak.Upgrade();
1861         CHECK_NULL_VOID(swiper);
1862         swiper->OnTranslateFinish(nextIndex, restartAutoPlay);
1863     });
1864     controller_->PlayMotion(scrollMotion);
1865 }
1866 
OnSpringAnimationStart(float velocity)1867 void SwiperPattern::OnSpringAnimationStart(float velocity)
1868 {
1869     AnimationCallbackInfo info;
1870     info.velocity = velocity;
1871     info.currentOffset = GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1872 
1873     auto nextIndex = ComputeNextIndexByVelocity(velocity);
1874     nextIndex = std::clamp(nextIndex, 0, TotalCount() - GetDisplayCount());
1875     if (GetLoopIndex(currentIndex_) == GetLoopIndex(nextIndex)) {
1876         info.targetOffset = info.currentOffset;
1877     } else {
1878         auto iter = itemPosition_.find(nextIndex);
1879         auto nextOffset = iter != itemPosition_.end() ? iter->second.startPos : 0.0f;
1880         info.targetOffset = GetCustomPropertyOffset() + Dimension(nextOffset, DimensionUnit::PX).ConvertToVp();
1881     }
1882 
1883     FireAnimationStartEvent(GetLoopIndex(currentIndex_), GetLoopIndex(nextIndex), info);
1884 }
1885 
OnSpringAndFadeAnimationFinish()1886 void SwiperPattern::OnSpringAndFadeAnimationFinish()
1887 {
1888     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
1889     auto nextIndex = firstItemInfoInVisibleArea.first;
1890     if (GetLoopIndex(currentIndex_) != GetLoopIndex(nextIndex)) {
1891         UpdateCurrentIndex(nextIndex);
1892         do {
1893             auto host = GetHost();
1894             if (!host) {
1895                 break;
1896             }
1897             auto curChild = host->GetChildAtIndex(currentIndex_);
1898             if (!curChild) {
1899                 break;
1900             }
1901             auto curChildFrame = AceType::DynamicCast<FrameNode>(curChild);
1902             if (!curChildFrame) {
1903                 break;
1904             }
1905             FlushFocus(curChildFrame);
1906         } while (0);
1907         OnIndexChange();
1908         oldIndex_ = currentIndex_;
1909     }
1910     AnimationCallbackInfo info;
1911     auto firstIndexStartPos = firstItemInfoInVisibleArea.second.startPos;
1912     info.currentOffset = GetCustomPropertyOffset() + Dimension(firstIndexStartPos, DimensionUnit::PX).ConvertToVp();
1913     FireAnimationEndEvent(GetLoopIndex(currentIndex_), info);
1914     currentIndexOffset_ = firstIndexStartPos;
1915 }
1916 
OnFadeAnimationStart()1917 void SwiperPattern::OnFadeAnimationStart()
1918 {
1919     AnimationCallbackInfo info;
1920     info.currentOffset = GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
1921     auto nextIndex = ComputeNextIndexByVelocity(0.0);
1922     nextIndex = std::clamp(nextIndex, 0, TotalCount() - GetDisplayCount());
1923     if (GetLoopIndex(currentIndex_) == GetLoopIndex(nextIndex)) {
1924         info.targetOffset = info.currentOffset;
1925     } else {
1926         info.targetOffset = GetCustomPropertyOffset();
1927     }
1928 
1929     FireAnimationStartEvent(GetLoopIndex(currentIndex_), GetLoopIndex(nextIndex), info);
1930 }
1931 
PlaySpringAnimation(double dragVelocity)1932 void SwiperPattern::PlaySpringAnimation(double dragVelocity)
1933 {
1934     LOGD("Play spring animation start");
1935     auto host = GetHost();
1936     CHECK_NULL_VOID(host);
1937     if (!springController_) {
1938         springController_ = CREATE_ANIMATOR(host->GetContext());
1939     }
1940     springController_->ClearStartListeners();
1941     springController_->ClearStopListeners();
1942     springController_->ClearInterpolators();
1943 
1944     auto mainSize = CalculateVisibleSize();
1945     if (LessOrEqual(mainSize, 0)) {
1946         LOGE("Main size is not positive.");
1947         return;
1948     }
1949     if (itemPosition_.empty()) {
1950         return;
1951     }
1952 
1953     static const auto springProperty = AceType::MakeRefPtr<SpringProperty>(1, 228, 30);
1954     ExtentPair extentPair = ExtentPair(currentOffset_ + mainSize - itemPosition_.rbegin()->second.endPos,
1955         currentOffset_ - itemPosition_.begin()->second.startPos);
1956     float friction = currentOffset_ > 0
1957                          ? CalculateFriction(itemPosition_.begin()->second.startPos / mainSize)
1958                          : CalculateFriction((mainSize - itemPosition_.rbegin()->second.endPos) / mainSize);
1959     auto springMotion = AceType::MakeRefPtr<SpringMotion>(currentOffset_,
1960         currentOffset_ < 0.0f ? extentPair.Leading() : extentPair.Trailing(), dragVelocity * friction, springProperty);
1961     springMotion->AddListener([weak = AceType::WeakClaim(this)](double position) {
1962         auto swiper = weak.Upgrade();
1963         if (swiper) {
1964             swiper->UpdateCurrentOffset(static_cast<float>(position) - swiper->currentOffset_);
1965         }
1966     });
1967     springController_->AddStartListener([weak = AceType::WeakClaim(this), dragVelocity]() {
1968         auto swiperPattern = weak.Upgrade();
1969         CHECK_NULL_VOID(swiperPattern);
1970         swiperPattern->OnSpringAnimationStart(static_cast<float>(dragVelocity));
1971     });
1972     springController_->AddStopListener([weak = AceType::WeakClaim(this)]() {
1973         auto swiperPattern = weak.Upgrade();
1974         CHECK_NULL_VOID(swiperPattern);
1975         swiperPattern->OnSpringAndFadeAnimationFinish();
1976     });
1977     springController_->PlayMotion(springMotion);
1978 }
1979 
PlayFadeAnimation()1980 void SwiperPattern::PlayFadeAnimation()
1981 {
1982     auto host = GetHost();
1983     CHECK_NULL_VOID(host);
1984 
1985     if (NearZero(fadeOffset_)) {
1986         return;
1987     }
1988 
1989     LOGD("Play fade animation start");
1990     if (!fadeController_) {
1991         fadeController_ = CREATE_ANIMATOR(host->GetContext());
1992     }
1993     fadeController_->ClearAllListeners();
1994 
1995     auto translate = AceType::MakeRefPtr<CurveAnimation<double>>(fadeOffset_, 0.0, Curves::LINEAR);
1996     auto weak = AceType::WeakClaim(this);
1997     translate->AddListener(Animation<double>::ValueCallback([weak](double value) {
1998         auto swiper = weak.Upgrade();
1999         if (swiper && swiper->GetHost()) {
2000             swiper->fadeOffset_ = static_cast<float>(value);
2001             swiper->GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2002         }
2003     }));
2004 
2005     fadeController_->AddStartListener([weak]() {
2006         auto swiperPattern = weak.Upgrade();
2007         CHECK_NULL_VOID(swiperPattern);
2008         swiperPattern->OnFadeAnimationStart();
2009     });
2010     fadeController_->AddStopListener([weak]() {
2011         auto swiperPattern = weak.Upgrade();
2012         CHECK_NULL_VOID(swiperPattern);
2013         swiperPattern->OnSpringAndFadeAnimationFinish();
2014     });
2015     constexpr float FADE_DURATION = 500.0f;
2016     fadeController_->SetDuration(FADE_DURATION);
2017     fadeController_->AddInterpolator(translate);
2018     fadeController_->Play();
2019 }
2020 
IsOutOfBoundary(float mainOffset) const2021 bool SwiperPattern::IsOutOfBoundary(float mainOffset) const
2022 {
2023     if (IsLoop() || itemPosition_.empty()) {
2024         return false;
2025     }
2026 
2027     auto startPos = itemPosition_.begin()->second.startPos;
2028     startPos = NearZero(startPos, PX_EPSILON) ? 0.0 : startPos;
2029     auto isOutOfStart = itemPosition_.begin()->first == 0 && GreatNotEqual(startPos + mainOffset, 0.0);
2030 
2031     auto visibleWindowSize = CalculateVisibleSize();
2032     auto endPos = itemPosition_.rbegin()->second.endPos + mainOffset;
2033     endPos = NearEqual(endPos, visibleWindowSize, PX_EPSILON) ? visibleWindowSize : endPos;
2034     auto isOutOfEnd = itemPosition_.rbegin()->first == TotalCount() - 1 && LessNotEqual(endPos, visibleWindowSize);
2035 
2036     return isOutOfStart || isOutOfEnd;
2037 }
2038 
GetRemainingOffset() const2039 float SwiperPattern::GetRemainingOffset() const
2040 {
2041     if (IsLoop() || itemPosition_.empty()) {
2042         return 0.0f;
2043     }
2044     if (itemPosition_.begin()->first == 0) {
2045         return -itemPosition_.begin()->second.startPos;
2046     }
2047     auto visibleWindowSize = CalculateVisibleSize();
2048     return itemPosition_.rbegin()->second.endPos - visibleWindowSize;
2049 }
2050 
MainSize() const2051 float SwiperPattern::MainSize() const
2052 {
2053     auto host = GetHost();
2054     CHECK_NULL_RETURN(host, 0.0);
2055     auto geometryNode = host->GetGeometryNode();
2056     CHECK_NULL_RETURN(geometryNode, 0.0);
2057     return geometryNode->GetFrameSize().MainSize(GetDirection());
2058 }
2059 
GetMainContentSize() const2060 float SwiperPattern::GetMainContentSize() const
2061 {
2062     auto host = GetHost();
2063     CHECK_NULL_RETURN(host, 0.0);
2064     auto geometryNode = host->GetGeometryNode();
2065     CHECK_NULL_RETURN(geometryNode, 0.0);
2066     return geometryNode->GetPaddingSize().Width();
2067 }
2068 
CalculateVisibleSize() const2069 float SwiperPattern::CalculateVisibleSize() const
2070 {
2071     auto prevMargin = GetPrevMargin();
2072     auto nextMargin = GetNextMargin();
2073     auto itemSpace = GetItemSpace();
2074     auto host = GetHost();
2075     CHECK_NULL_RETURN(host, 0.0f);
2076     auto geometryNode = host->GetGeometryNode();
2077     CHECK_NULL_RETURN(geometryNode, 0.0);
2078     auto mainSize = geometryNode->GetFrameSize().MainSize(GetDirection());
2079     if (itemSpace > mainSize) {
2080         itemSpace = 0.0f;
2081     }
2082     if (prevMargin != 0.0f) {
2083         if (nextMargin != 0.0f) {
2084             return contentMainSize_ - prevMargin - nextMargin - 2 * itemSpace;
2085         }
2086         return contentMainSize_ - prevMargin - itemSpace;
2087     }
2088 
2089     if (nextMargin != 0.0f) {
2090         return contentMainSize_ - nextMargin - itemSpace;
2091     }
2092     return contentMainSize_;
2093 }
2094 
GetItemSpace() const2095 float SwiperPattern::GetItemSpace() const
2096 {
2097     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2098     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
2099     return ConvertToPx(swiperLayoutProperty->GetItemSpace().value_or(0.0_vp),
2100         swiperLayoutProperty->GetLayoutConstraint()->scaleProperty, 0)
2101         .value_or(0);
2102 }
2103 
GetPrevMargin() const2104 float SwiperPattern::GetPrevMargin() const
2105 {
2106     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2107     CHECK_NULL_RETURN(swiperLayoutProperty, 0.0f);
2108     return SwiperUtils::IsStretch(swiperLayoutProperty) ?
2109         ConvertToPx(swiperLayoutProperty->GetPrevMargin().value_or(0.0_vp),
2110         swiperLayoutProperty->GetLayoutConstraint()->scaleProperty, 0).value_or(0) : 0.0f;
2111 }
2112 
GetNextMargin() const2113 float SwiperPattern::GetNextMargin() const
2114 {
2115     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2116     CHECK_NULL_RETURN(swiperLayoutProperty, 0.0f);
2117     return SwiperUtils::IsStretch(swiperLayoutProperty) ?
2118         ConvertToPx(swiperLayoutProperty->GetNextMargin().value_or(0.0_vp),
2119         swiperLayoutProperty->GetLayoutConstraint()->scaleProperty, 0).value_or(0) : 0.0f;
2120 }
2121 
GetDirection() const2122 Axis SwiperPattern::GetDirection() const
2123 {
2124     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2125     CHECK_NULL_RETURN(swiperLayoutProperty, Axis::HORIZONTAL);
2126     return swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
2127 }
2128 
CurrentIndex() const2129 int32_t SwiperPattern::CurrentIndex() const
2130 {
2131     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2132     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
2133     return swiperLayoutProperty->GetIndex().value_or(0);
2134 }
2135 
GetDisplayCount() const2136 int32_t SwiperPattern::GetDisplayCount() const
2137 {
2138     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2139     CHECK_NULL_RETURN(swiperLayoutProperty, 1);
2140     auto displayCount = CalculateDisplayCount();
2141     return displayCount;
2142 }
2143 
CalculateDisplayCount() const2144 int32_t SwiperPattern::CalculateDisplayCount() const
2145 {
2146     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2147     CHECK_NULL_RETURN(swiperLayoutProperty, 1);
2148     bool isAutoFill = IsAutoFill();
2149     if (isAutoFill) {
2150         auto minSize = swiperLayoutProperty->GetMinSize()->ConvertToPx();
2151         float contentWidth = GetMainContentSize();
2152         auto displayCount =
2153             CalculateCount(contentWidth, minSize, SWIPER_MARGIN.ConvertToPx(), SWIPER_GUTTER.ConvertToPx());
2154         if (LessOrEqual(minSize, 0)) {
2155             displayCount = 1;
2156         }
2157         displayCount = displayCount > 0 ? displayCount : 1;
2158         auto totalCount = TotalCount();
2159         displayCount = displayCount > totalCount ? totalCount : displayCount;
2160         auto displayCountProperty = swiperLayoutProperty->GetDisplayCount().value_or(1);
2161 
2162         if (displayCountProperty != displayCount) {
2163             swiperLayoutProperty->UpdateDisplayCount(displayCount);
2164             auto host = GetHost();
2165             CHECK_NULL_RETURN(host, 1);
2166             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF | PROPERTY_UPDATE_RENDER);
2167         }
2168         return displayCount;
2169     } else {
2170         return swiperLayoutProperty->GetDisplayCount().value_or(1);
2171     }
2172 }
2173 
CalculateCount(float contentWidth,float minSize,float margin,float gutter,float swiperPadding) const2174 int32_t SwiperPattern::CalculateCount(
2175     float contentWidth, float minSize, float margin, float gutter, float swiperPadding) const
2176 {
2177     return static_cast<int32_t>(floor((contentWidth - 2 * margin + gutter - 2 * swiperPadding) / (minSize + gutter)));
2178 }
2179 
IsAutoFill() const2180 bool SwiperPattern::IsAutoFill() const
2181 {
2182     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2183     CHECK_NULL_RETURN(swiperLayoutProperty, false);
2184     return swiperLayoutProperty->GetMinSize().has_value();
2185 }
2186 
IsAutoPlay() const2187 bool SwiperPattern::IsAutoPlay() const
2188 {
2189     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2190     CHECK_NULL_RETURN(swiperPaintProperty, false);
2191     return swiperPaintProperty->GetAutoPlay().value_or(false);
2192 }
2193 
GetDuration() const2194 int32_t SwiperPattern::GetDuration() const
2195 {
2196     const int32_t DEFAULT_DURATION = 400;
2197     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2198     CHECK_NULL_RETURN(swiperPaintProperty, DEFAULT_DURATION);
2199     return swiperPaintProperty->GetDuration().value_or(DEFAULT_DURATION);
2200 }
2201 
GetInterval() const2202 int32_t SwiperPattern::GetInterval() const
2203 {
2204     const int32_t DEFAULT_INTERVAL = 3000;
2205     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2206     CHECK_NULL_RETURN(swiperPaintProperty, DEFAULT_INTERVAL);
2207     return swiperPaintProperty->GetAutoPlayInterval().value_or(DEFAULT_INTERVAL);
2208 }
2209 
GetCurve() const2210 RefPtr<Curve> SwiperPattern::GetCurve() const
2211 {
2212     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2213     CHECK_NULL_RETURN(swiperPaintProperty, nullptr);
2214     return swiperPaintProperty->GetCurve().value_or(nullptr);
2215 }
2216 
IsLoop() const2217 bool SwiperPattern::IsLoop() const
2218 {
2219     if (TotalDisPlayCount() >= TotalCount()) {
2220         return false;
2221     }
2222     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2223     CHECK_NULL_RETURN(swiperLayoutProperty, true);
2224     return swiperLayoutProperty->GetLoop().value_or(true);
2225 }
2226 
IsEnabled() const2227 bool SwiperPattern::IsEnabled() const
2228 {
2229     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2230     CHECK_NULL_RETURN(swiperPaintProperty, true);
2231     return swiperPaintProperty->GetEnabled().value_or(true);
2232 }
2233 
GetEdgeEffect() const2234 EdgeEffect SwiperPattern::GetEdgeEffect() const
2235 {
2236     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2237     CHECK_NULL_RETURN(swiperPaintProperty, EdgeEffect::SPRING);
2238     return swiperPaintProperty->GetEdgeEffect().value_or(EdgeEffect::SPRING);
2239 }
2240 
IsDisableSwipe() const2241 bool SwiperPattern::IsDisableSwipe() const
2242 {
2243     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2244     CHECK_NULL_RETURN(swiperPaintProperty, false);
2245     return swiperPaintProperty->GetDisableSwipe().value_or(false);
2246 }
2247 
IsShowIndicator() const2248 bool SwiperPattern::IsShowIndicator() const
2249 {
2250     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2251     CHECK_NULL_RETURN(swiperLayoutProperty, true);
2252     return swiperLayoutProperty->GetShowIndicatorValue(true);
2253 }
2254 
IsShowArrow() const2255 bool SwiperPattern::IsShowArrow() const
2256 {
2257     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2258     CHECK_NULL_RETURN(swiperLayoutProperty, true);
2259     return swiperLayoutProperty->GetDisplayArrowValue(false);
2260 }
2261 
GetIndicatorType() const2262 SwiperIndicatorType SwiperPattern::GetIndicatorType() const
2263 {
2264     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2265     CHECK_NULL_RETURN(swiperLayoutProperty, SwiperIndicatorType::DOT);
2266     return swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT);
2267 }
2268 
GetSwiperParameters() const2269 std::shared_ptr<SwiperParameters> SwiperPattern::GetSwiperParameters() const
2270 {
2271     if (swiperParameters_ == nullptr) {
2272         swiperParameters_ = std::make_shared<SwiperParameters>();
2273         auto pipelineContext = PipelineBase::GetCurrentContext();
2274         CHECK_NULL_RETURN(pipelineContext, swiperParameters_);
2275         auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
2276         swiperParameters_->dimLeft = 0.0_vp;
2277         swiperParameters_->dimTop = 0.0_vp;
2278         swiperParameters_->dimRight = 0.0_vp;
2279         swiperParameters_->dimBottom = 0.0_vp;
2280         swiperParameters_->itemWidth = swiperIndicatorTheme->GetSize();
2281         swiperParameters_->itemHeight = swiperIndicatorTheme->GetSize();
2282         swiperParameters_->selectedItemWidth = swiperIndicatorTheme->GetSize();
2283         swiperParameters_->selectedItemHeight = swiperIndicatorTheme->GetSize();
2284         swiperParameters_->maskValue = false;
2285         swiperParameters_->colorVal = swiperIndicatorTheme->GetColor();
2286         swiperParameters_->selectedColorVal = swiperIndicatorTheme->GetSelectedColor();
2287     }
2288     return swiperParameters_;
2289 }
2290 
GetSwiperDigitalParameters() const2291 std::shared_ptr<SwiperDigitalParameters> SwiperPattern::GetSwiperDigitalParameters() const
2292 {
2293     if (swiperDigitalParameters_ == nullptr) {
2294         swiperDigitalParameters_ = std::make_shared<SwiperDigitalParameters>();
2295         auto pipelineContext = PipelineBase::GetCurrentContext();
2296         CHECK_NULL_RETURN(pipelineContext, swiperDigitalParameters_);
2297         auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
2298         swiperDigitalParameters_->dimLeft = 0.0_vp;
2299         swiperDigitalParameters_->dimTop = 0.0_vp;
2300         swiperDigitalParameters_->dimRight = 0.0_vp;
2301         swiperDigitalParameters_->dimBottom = 0.0_vp;
2302         swiperDigitalParameters_->fontColor = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
2303         swiperDigitalParameters_->selectedFontColor =
2304             swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
2305         swiperDigitalParameters_->fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
2306         swiperDigitalParameters_->selectedFontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
2307         swiperDigitalParameters_->fontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
2308         swiperDigitalParameters_->selectedFontWeight =
2309             swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
2310     }
2311     return swiperDigitalParameters_;
2312 }
2313 
TotalCount() const2314 int32_t SwiperPattern::TotalCount() const
2315 {
2316     auto host = GetHost();
2317     CHECK_NULL_RETURN(host, 0);
2318     // last child is swiper indicator
2319     int num = 0;
2320     if (IsShowIndicator()) {
2321         num += 1;
2322     }
2323     if (HasLeftButtonNode()) {
2324         num += 1;
2325     }
2326     if (HasRightButtonNode()) {
2327         num += 1;
2328     }
2329 
2330     return host->TotalChildCount() - num;
2331 }
2332 
GetTranslateLength() const2333 float SwiperPattern::GetTranslateLength() const
2334 {
2335     if (itemPosition_.empty()) {
2336         return 0.0f;
2337     }
2338     return itemPosition_.begin()->second.endPos - itemPosition_.begin()->second.startPos;
2339 }
2340 
GetFirstItemInfoInVisibleArea() const2341 std::pair<int32_t, SwiperItemInfo> SwiperPattern::GetFirstItemInfoInVisibleArea() const
2342 {
2343     if (itemPosition_.empty()) {
2344         return std::make_pair(0, SwiperItemInfo {});
2345     }
2346     auto targetIndex = 0;
2347     if (GetPrevMargin() != 0.0f) {
2348         for (const auto& item : itemPosition_) {
2349             if (item.second.startPos < 0 && item.second.endPos < 0) {
2350                 continue;
2351             }
2352             if (item.second.startPos <= 0 && item.second.endPos > 0) {
2353                 targetIndex = item.first;
2354                 return std::make_pair(targetIndex, SwiperItemInfo { item.second.startPos, item.second.endPos });
2355             }
2356             if (item.second.startPos > 0 && item.second.endPos > 0) {
2357                 targetIndex = item.first;
2358                 return std::make_pair(targetIndex, SwiperItemInfo { item.second.startPos, item.second.endPos });
2359             }
2360         }
2361     }
2362     return std::make_pair(itemPosition_.begin()->first,
2363         SwiperItemInfo { itemPosition_.begin()->second.startPos, itemPosition_.begin()->second.endPos });
2364 }
2365 
GetLastItemInfoInVisibleArea() const2366 std::pair<int32_t, SwiperItemInfo> SwiperPattern::GetLastItemInfoInVisibleArea() const
2367 {
2368     if (itemPosition_.empty()) {
2369         return std::make_pair(0, SwiperItemInfo {});
2370     }
2371     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
2372     auto targetVisableIndex = firstItemInfoInVisibleArea.first;
2373     targetVisableIndex += GetDisplayCount() - 1;
2374     auto iter = itemPosition_.find(targetVisableIndex);
2375     if (iter != itemPosition_.end()) {
2376         return std::make_pair(iter->first,
2377             SwiperItemInfo { iter->second.startPos, iter->second.endPos });
2378     }
2379     return std::make_pair(itemPosition_.rbegin()->first,
2380         SwiperItemInfo { itemPosition_.rbegin()->second.startPos, itemPosition_.rbegin()->second.endPos });
2381 }
2382 
GetSecondItemInfoInVisibleArea() const2383 std::pair<int32_t, SwiperItemInfo> SwiperPattern::GetSecondItemInfoInVisibleArea() const
2384 {
2385     if (itemPosition_.empty()) {
2386         return std::make_pair(0, SwiperItemInfo {});
2387     }
2388     auto targetIndex = itemPosition_.begin()->first;
2389     if (GetPrevMargin() != 0.0f) {
2390         for (const auto& item : itemPosition_) {
2391             if (item.second.startPos < 0 && item.second.endPos < 0) {
2392                 continue;
2393             }
2394             if (item.second.startPos <= 0 && item.second.endPos > 0) {
2395                 targetIndex = item.first;
2396                 break;
2397             }
2398             if (item.second.startPos > 0 && item.second.endPos > 0) {
2399                 targetIndex = item.first;
2400                 break;
2401             }
2402         }
2403     }
2404 
2405     targetIndex++;
2406     auto iter = itemPosition_.find(targetIndex);
2407     if (iter != itemPosition_.end()) {
2408         return std::make_pair(targetIndex, SwiperItemInfo { iter->second.startPos, iter->second.endPos });
2409     }
2410     return std::make_pair(itemPosition_.begin()->first,
2411         SwiperItemInfo { itemPosition_.begin()->second.startPos, itemPosition_.begin()->second.endPos });
2412 }
2413 
IsOutOfHotRegion(const PointF & dragPoint) const2414 bool SwiperPattern::IsOutOfHotRegion(const PointF& dragPoint) const
2415 {
2416     auto host = GetHost();
2417     CHECK_NULL_RETURN(host, true);
2418     auto geometryNode = host->GetGeometryNode();
2419     CHECK_NULL_RETURN(geometryNode, true);
2420 
2421     auto hotRegion = geometryNode->GetFrameRect();
2422     return !hotRegion.IsInRegion(dragPoint + OffsetF(hotRegion.GetX(), hotRegion.GetY()));
2423 }
2424 
SaveDotIndicatorProperty(const RefPtr<FrameNode> & indicatorNode)2425 void SwiperPattern::SaveDotIndicatorProperty(const RefPtr<FrameNode>& indicatorNode)
2426 {
2427     CHECK_NULL_VOID(indicatorNode);
2428     auto indicatorPattern = indicatorNode->GetPattern<SwiperIndicatorPattern>();
2429     CHECK_NULL_VOID(indicatorPattern);
2430     auto layoutProperty = indicatorNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
2431     CHECK_NULL_VOID(layoutProperty);
2432     auto paintProperty = indicatorNode->GetPaintProperty<DotIndicatorPaintProperty>();
2433     CHECK_NULL_VOID(paintProperty);
2434     auto pipelineContext = PipelineBase::GetCurrentContext();
2435     CHECK_NULL_VOID(pipelineContext);
2436     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
2437     CHECK_NULL_VOID(swiperIndicatorTheme);
2438     auto swiperParameters = GetSwiperParameters();
2439     CHECK_NULL_VOID(swiperParameters);
2440     layoutProperty->UpdateLeft(swiperParameters->dimLeft.value_or(0.0_vp));
2441     layoutProperty->UpdateTop(swiperParameters->dimTop.value_or(0.0_vp));
2442     layoutProperty->UpdateRight(swiperParameters->dimRight.value_or(0.0_vp));
2443     layoutProperty->UpdateBottom(swiperParameters->dimBottom.value_or(0.0_vp));
2444     paintProperty->UpdateItemWidth(swiperParameters->itemWidth.value_or(swiperIndicatorTheme->GetSize()));
2445     paintProperty->UpdateItemHeight(swiperParameters->itemHeight.value_or(swiperIndicatorTheme->GetSize()));
2446     paintProperty->UpdateSelectedItemWidth(
2447         swiperParameters->selectedItemWidth.value_or(swiperIndicatorTheme->GetSize()));
2448     paintProperty->UpdateSelectedItemHeight(
2449         swiperParameters->selectedItemHeight.value_or(swiperIndicatorTheme->GetSize()));
2450     paintProperty->UpdateIndicatorMask(swiperParameters->maskValue.value_or(false));
2451     paintProperty->UpdateColor(swiperParameters->colorVal.value_or(swiperIndicatorTheme->GetColor()));
2452     paintProperty->UpdateSelectedColor(
2453         swiperParameters->selectedColorVal.value_or(swiperIndicatorTheme->GetSelectedColor()));
2454     paintProperty->UpdateIsCustomSize(IsCustomSize_);
2455 
2456     auto host = GetHost();
2457     CHECK_NULL_VOID(host);
2458     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2459     indicatorNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2460 }
2461 
SaveDigitIndicatorProperty(const RefPtr<FrameNode> & indicatorNode)2462 void SwiperPattern::SaveDigitIndicatorProperty(const RefPtr<FrameNode>& indicatorNode)
2463 {
2464     CHECK_NULL_VOID(indicatorNode);
2465     auto indicatorPattern = indicatorNode->GetPattern<SwiperIndicatorPattern>();
2466     CHECK_NULL_VOID(indicatorPattern);
2467     auto layoutProperty = indicatorNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
2468     CHECK_NULL_VOID(layoutProperty);
2469     auto pipelineContext = PipelineBase::GetCurrentContext();
2470     CHECK_NULL_VOID(pipelineContext);
2471     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
2472     auto swiperDigitalParameters = GetSwiperDigitalParameters();
2473     CHECK_NULL_VOID(swiperDigitalParameters);
2474     layoutProperty->UpdateLeft(swiperDigitalParameters->dimLeft.value_or(0.0_vp));
2475     layoutProperty->UpdateTop(swiperDigitalParameters->dimTop.value_or(0.0_vp));
2476     layoutProperty->UpdateRight(swiperDigitalParameters->dimRight.value_or(0.0_vp));
2477     layoutProperty->UpdateBottom(swiperDigitalParameters->dimBottom.value_or(0.0_vp));
2478     layoutProperty->UpdateFontColor(swiperDigitalParameters->fontColor.value_or(
2479         swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor()));
2480     layoutProperty->UpdateSelectedFontColor(swiperDigitalParameters->selectedFontColor.value_or(
2481         swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor()));
2482     layoutProperty->UpdateFontSize(
2483         swiperDigitalParameters->fontSize.value_or(swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize()));
2484     layoutProperty->UpdateSelectedFontSize(swiperDigitalParameters->selectedFontSize.value_or(
2485         swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize()));
2486     layoutProperty->UpdateFontWeight(swiperDigitalParameters->fontWeight.value_or(
2487         swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight()));
2488     layoutProperty->UpdateSelectedFontWeight(swiperDigitalParameters->selectedFontWeight.value_or(
2489         swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight()));
2490     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2491     CHECK_NULL_VOID(swiperLayoutProperty);
2492     swiperLayoutProperty->UpdateLeft(swiperDigitalParameters->dimLeft.value_or(0.0_vp));
2493     swiperLayoutProperty->UpdateTop(swiperDigitalParameters->dimTop.value_or(0.0_vp));
2494     swiperLayoutProperty->UpdateRight(swiperDigitalParameters->dimRight.value_or(0.0_vp));
2495     swiperLayoutProperty->UpdateBottom(swiperDigitalParameters->dimBottom.value_or(0.0_vp));
2496 }
2497 
PostTranslateTask(uint32_t delayTime)2498 void SwiperPattern::PostTranslateTask(uint32_t delayTime)
2499 {
2500     auto pipeline = PipelineContext::GetCurrentContext();
2501     CHECK_NULL_VOID(pipeline);
2502     auto taskExecutor = pipeline->GetTaskExecutor();
2503     CHECK_NULL_VOID(taskExecutor);
2504 
2505     if (translateTask_) {
2506         translateTask_.Cancel();
2507     }
2508 
2509     auto weak = AceType::WeakClaim(this);
2510     translateTask_.Reset([weak, delayTime] {
2511         auto swiper = weak.Upgrade();
2512         if (swiper) {
2513             auto childrenSize = swiper->TotalCount();
2514             auto displayCount = swiper->GetDisplayCount();
2515             if (childrenSize <= 0 || displayCount <= 0 || swiper->itemPosition_.empty()) {
2516                 return;
2517             }
2518             if (!swiper->IsLoop() &&
2519                 swiper->GetLoopIndex(swiper->currentIndex_ + 1) > (childrenSize - displayCount)) {
2520                 return;
2521             }
2522             swiper->targetIndex_ = swiper->currentIndex_ + 1;
2523             auto host = swiper->GetHost();
2524             CHECK_NULL_VOID(host);
2525             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2526             auto pipeline = PipelineContext::GetCurrentContext();
2527             if (pipeline) {
2528                 pipeline->FlushUITasks();
2529             }
2530         }
2531     });
2532 
2533     taskExecutor->PostDelayedTask(translateTask_, TaskExecutor::TaskType::UI, delayTime);
2534 }
2535 
RegisterVisibleAreaChange()2536 void SwiperPattern::RegisterVisibleAreaChange()
2537 {
2538     if (hasVisibleChangeRegistered_ || !IsAutoPlay()) {
2539         return;
2540     }
2541 
2542     auto pipeline = PipelineContext::GetCurrentContext();
2543     CHECK_NULL_VOID(pipeline);
2544     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
2545         auto swiperPattern = weak.Upgrade();
2546         CHECK_NULL_VOID(swiperPattern);
2547         swiperPattern->isVisibleArea_ = visible;
2548         if (!visible) {
2549             swiperPattern->translateTask_.Cancel();
2550             return;
2551         }
2552 
2553         if (swiperPattern->NeedStartAutoPlay()) {
2554             swiperPattern->StartAutoPlay();
2555         }
2556     };
2557     auto host = GetHost();
2558     CHECK_NULL_VOID(host);
2559     pipeline->RemoveVisibleAreaChangeNode(host->GetId());
2560     pipeline->AddVisibleAreaChangeNode(host, 0.0f, callback);
2561 
2562     pipeline->AddWindowStateChangedCallback(host->GetId());
2563     hasVisibleChangeRegistered_ = true;
2564 }
2565 
NeedAutoPlay() const2566 bool SwiperPattern::NeedAutoPlay() const
2567 {
2568     bool reachEnd = GetLoopIndex(CurrentIndex()) >= TotalCount() - 1 && !IsLoop();
2569     return IsAutoPlay() && !reachEnd && isVisible_ && !isIndicatorLongPress_;
2570 }
2571 
TriggerAnimationEndOnSwipeToLeft()2572 void SwiperPattern::TriggerAnimationEndOnSwipeToLeft()
2573 {
2574     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
2575     auto firstItemLength = firstItemInfoInVisibleArea.second.endPos - firstItemInfoInVisibleArea.second.startPos;
2576     auto firstIndexStartPos = firstItemInfoInVisibleArea.second.startPos;
2577     if (std::abs(firstIndexStartPos) < (firstItemLength / 2)) {
2578         currentIndexOffset_ = firstItemInfoInVisibleArea.second.startPos;
2579         UpdateCurrentIndex(firstItemInfoInVisibleArea.first);
2580     } else {
2581         auto secondItemInfoInVisibleArea = GetSecondItemInfoInVisibleArea();
2582         currentIndexOffset_ = secondItemInfoInVisibleArea.second.startPos;
2583         UpdateCurrentIndex(secondItemInfoInVisibleArea.first);
2584     }
2585 
2586     AnimationCallbackInfo info;
2587     info.currentOffset = GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
2588     FireAnimationEndEvent(GetLoopIndex(currentIndex_), info);
2589 }
2590 
TriggerAnimationEndOnSwipeToRight()2591 void SwiperPattern::TriggerAnimationEndOnSwipeToRight()
2592 {
2593     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
2594     auto firstItemLength = firstItemInfoInVisibleArea.second.endPos - firstItemInfoInVisibleArea.second.startPos;
2595     auto secondItemInfoInVisibleArea = GetSecondItemInfoInVisibleArea();
2596     auto secondIndexStartPos = secondItemInfoInVisibleArea.second.startPos;
2597     if (std::abs(secondIndexStartPos) < (firstItemLength / 2)) {
2598         currentIndexOffset_ = secondItemInfoInVisibleArea.second.startPos;
2599         UpdateCurrentIndex(secondItemInfoInVisibleArea.first);
2600     } else {
2601         currentIndexOffset_ = firstItemInfoInVisibleArea.second.startPos;
2602         UpdateCurrentIndex(firstItemInfoInVisibleArea.first);
2603     }
2604 
2605     AnimationCallbackInfo info;
2606     info.currentOffset = GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
2607     FireAnimationEndEvent(GetLoopIndex(currentIndex_), info);
2608 }
2609 
TriggerAnimationEndOnForceStop()2610 void SwiperPattern::TriggerAnimationEndOnForceStop()
2611 {
2612     auto pauseTargetIndex = pauseTargetIndex_.has_value() ? pauseTargetIndex_.value() : currentIndex_;
2613     if (currentIndex_ == pauseTargetIndex) {
2614         AnimationCallbackInfo info;
2615         info.currentOffset =
2616             GetCustomPropertyOffset() + Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
2617         FireAnimationEndEvent(GetLoopIndex(currentIndex_), info);
2618     } else {
2619         auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
2620         if (currentIndex_ == firstItemInfoInVisibleArea.first) {
2621             // swipe to left
2622             TriggerAnimationEndOnSwipeToLeft();
2623         } else {
2624             // swipe to right
2625             TriggerAnimationEndOnSwipeToRight();
2626         }
2627         do {
2628             auto host = GetHost();
2629             if (!host) {
2630                 break;
2631             }
2632             auto curChild = host->GetChildAtIndex(currentIndex_);
2633             if (!curChild) {
2634                 break;
2635             }
2636             auto curChildFrame = AceType::DynamicCast<FrameNode>(curChild);
2637             if (!curChildFrame) {
2638                 break;
2639             }
2640             FlushFocus(curChildFrame);
2641         } while (0);
2642 
2643         OnIndexChange();
2644         oldIndex_ = currentIndex_;
2645     }
2646 }
2647 
TriggerEventOnFinish(int32_t nextIndex)2648 void SwiperPattern::TriggerEventOnFinish(int32_t nextIndex)
2649 {
2650     ResetAndUpdateIndexOnAnimationEnd(nextIndex);
2651 
2652     AnimationCallbackInfo info;
2653     info.currentOffset = GetCustomPropertyOffset();
2654     FireAnimationEndEvent(GetLoopIndex(currentIndex_), info);
2655 }
2656 
SetLazyLoadFeature(bool useLazyLoad) const2657 void SwiperPattern::SetLazyLoadFeature(bool useLazyLoad) const
2658 {
2659     // lazyBuild feature.
2660     auto host = GetHost();
2661     CHECK_NULL_VOID(host);
2662     const auto& children = host->GetChildren();
2663     for (auto&& child : children) {
2664         auto lazyForEach = DynamicCast<LazyForEachNode>(child);
2665         if (lazyForEach) {
2666             lazyForEach->SetRequestLongPredict(useLazyLoad);
2667         }
2668     }
2669     if (useLazyLoad) {
2670         auto layoutProperty = host->GetLayoutProperty<SwiperLayoutProperty>();
2671         CHECK_NULL_VOID(layoutProperty);
2672         auto cacheCount = layoutProperty->GetCachedCountValue(1);
2673         std::set<int32_t> forEachIndexSet;
2674         for (auto count = 1; count <= cacheCount; count++) {
2675             forEachIndexSet.emplace(GetLoopIndex(currentIndex_ + count));
2676             forEachIndexSet.emplace(GetLoopIndex(currentIndex_ - count));
2677         }
2678         if (forEachIndexSet.empty()) {
2679             return;
2680         }
2681         for (const auto& child : children) {
2682             if (child->GetTag() != V2::JS_FOR_EACH_ETS_TAG) {
2683                 continue;
2684             }
2685             auto pipeline = PipelineContext::GetCurrentContext();
2686             CHECK_NULL_VOID(pipeline);
2687             auto taskExecutor = pipeline->GetTaskExecutor();
2688             CHECK_NULL_VOID(taskExecutor);
2689             taskExecutor->PostTask(
2690                 [weak = WeakClaim(RawPtr(child)), forEachIndexSet]() {
2691                     auto node = weak.Upgrade();
2692                     CHECK_NULL_VOID(node);
2693                     auto forEachNode = AceType::DynamicCast<ForEachNode>(node);
2694                     CHECK_NULL_VOID(forEachNode);
2695                     for (auto index : forEachIndexSet) {
2696                         auto childNode = forEachNode->GetChildAtIndex(index);
2697                         CHECK_NULL_VOID(childNode);
2698                         childNode->Build();
2699                     }
2700                 },
2701                 TaskExecutor::TaskType::UI);
2702         }
2703     }
2704 }
2705 
SetLazyLoadIsLoop() const2706 void SwiperPattern::SetLazyLoadIsLoop() const
2707 {
2708     auto host = GetHost();
2709     CHECK_NULL_VOID(host);
2710     const auto& children = host->GetChildren();
2711     for (auto&& child : children) {
2712         auto lazyForEach = DynamicCast<LazyForEachNode>(child);
2713         if (lazyForEach) {
2714             lazyForEach->SetIsLoop(IsLoop());
2715         }
2716     }
2717 }
2718 
IsVisibleChildrenSizeLessThanSwiper()2719 bool SwiperPattern::IsVisibleChildrenSizeLessThanSwiper()
2720 {
2721     if (itemPosition_.empty()) {
2722         return true;
2723     }
2724     auto firstItemInfoInVisibleArea = GetFirstItemInfoInVisibleArea();
2725     auto lastItemInfoInVisibleArea = GetLastItemInfoInVisibleArea();
2726     auto calcDisPlayCount = lastItemInfoInVisibleArea.first - firstItemInfoInVisibleArea.first + 1;
2727     if (Positive(TotalCount() - calcDisPlayCount)) {
2728         return false;
2729     }
2730     if (static_cast<int32_t>(itemPosition_.size()) == TotalCount()) {
2731         auto totalChildrenSize = lastItemInfoInVisibleArea.second.endPos - firstItemInfoInVisibleArea.second.startPos;
2732         if (NonPositive(totalChildrenSize)) {
2733             return true;
2734         }
2735         auto prevMargin = GetPrevMargin();
2736         auto nextMargin = GetNextMargin();
2737         auto itemSpace = GetItemSpace();
2738         auto host = GetHost();
2739         CHECK_NULL_RETURN(host, true);
2740         auto geometryNode = host->GetGeometryNode();
2741         CHECK_NULL_RETURN(geometryNode, true);
2742         auto mainSize = geometryNode->GetFrameSize().MainSize(GetDirection());
2743         if (itemSpace > mainSize) {
2744             itemSpace = 0.0f;
2745         }
2746         auto prevMarginMontage = Positive(prevMargin) ? prevMargin + itemSpace : 0.0f;
2747         auto nextMarginMontage = Positive(nextMargin) ? nextMargin + itemSpace : 0.0f;
2748 
2749         if (totalChildrenSize <= (contentMainSize_ - prevMarginMontage - nextMarginMontage)) {
2750             return true;
2751         }
2752     }
2753     return false;
2754 }
2755 
UpdateItemRenderGroup(bool itemRenderGroup)2756 void SwiperPattern::UpdateItemRenderGroup(bool itemRenderGroup)
2757 {
2758     for (auto& item : itemPosition_) {
2759         if (auto frameNode = item.second.node) {
2760             auto context = frameNode->GetRenderContext();
2761             CHECK_NULL_VOID(context);
2762             context->UpdateRenderGroup(itemRenderGroup);
2763         }
2764     }
2765 }
2766 
OnTranslateFinish(int32_t nextIndex,bool restartAutoPlay,bool forceStop)2767 void SwiperPattern::OnTranslateFinish(int32_t nextIndex, bool restartAutoPlay, bool forceStop)
2768 {
2769     if (forceStop && !isFinishAnimation_) {
2770         TriggerAnimationEndOnForceStop();
2771     } else {
2772         TriggerEventOnFinish(nextIndex);
2773     }
2774 
2775     auto host = GetHost();
2776     CHECK_NULL_VOID(host);
2777     if (HasIndicatorNode()) {
2778         auto indicatorNode = DynamicCast<FrameNode>(host->GetChildAtIndex(host->GetChildIndexById(GetIndicatorId())));
2779         CHECK_NULL_VOID(indicatorNode);
2780         if (indicatorNode->GetTag() == V2::SWIPER_INDICATOR_ETS_TAG) {
2781             indicatorNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2782             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2783         }
2784     }
2785 
2786     auto delayTime = GetInterval() - GetDuration();
2787     delayTime = std::clamp(delayTime, 0, delayTime);
2788     if (NeedAutoPlay() && isUserFinish_) {
2789         PostTranslateTask(delayTime);
2790     }
2791     host->OnAccessibilityEvent(AccessibilityEventType::SCROLL_END);
2792     UpdateItemRenderGroup(false);
2793 }
2794 
OnWindowShow()2795 void SwiperPattern::OnWindowShow()
2796 {
2797     isWindowShow_ = true;
2798     if (NeedStartAutoPlay()) {
2799         StartAutoPlay();
2800     }
2801 }
2802 
OnWindowHide()2803 void SwiperPattern::OnWindowHide()
2804 {
2805     isWindowShow_ = false;
2806     StopAutoPlay();
2807 }
2808 
ArrowHover(bool hoverFlag)2809 void SwiperPattern::ArrowHover(bool hoverFlag)
2810 {
2811     if (HasLeftButtonNode() && HasRightButtonNode()) {
2812         auto swiperNode = GetHost();
2813         CHECK_NULL_VOID(swiperNode);
2814         auto leftArrowNode =
2815             DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(GetLeftButtonId())));
2816         CHECK_NULL_VOID(leftArrowNode);
2817         auto leftArrowPattern = leftArrowNode->GetPattern<SwiperArrowPattern>();
2818         CHECK_NULL_VOID(leftArrowPattern);
2819         leftArrowPattern->SetButtonVisible(hoverFlag);
2820         auto rightArrowNode =
2821             DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(GetRightButtonId())));
2822         CHECK_NULL_VOID(rightArrowNode);
2823         auto rightArrowPattern = rightArrowNode->GetPattern<SwiperArrowPattern>();
2824         CHECK_NULL_VOID(rightArrowPattern);
2825         rightArrowPattern->SetButtonVisible(hoverFlag);
2826     }
2827 }
2828 
SaveArrowProperty(const RefPtr<FrameNode> & arrowNode)2829 void SwiperPattern::SaveArrowProperty(const RefPtr<FrameNode>& arrowNode)
2830 {
2831     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2832     CHECK_NULL_VOID(layoutProperty);
2833     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
2834     CHECK_NULL_VOID(swiperPaintProperty);
2835     auto arrowLayoutProperty = arrowNode->GetLayoutProperty<SwiperArrowLayoutProperty>();
2836     CHECK_NULL_VOID(arrowLayoutProperty);
2837     arrowLayoutProperty->UpdateDirection(layoutProperty->GetDirection().value_or(Axis::HORIZONTAL));
2838     arrowLayoutProperty->UpdateIndex(layoutProperty->GetIndex().value_or(0));
2839     arrowLayoutProperty->UpdateLoop(layoutProperty->GetLoop().value_or(true));
2840     arrowLayoutProperty->UpdateEnabled(swiperPaintProperty->GetEnabled().value_or(true));
2841     arrowLayoutProperty->UpdateDisplayArrow(layoutProperty->GetDisplayArrowValue());
2842     arrowLayoutProperty->UpdateHoverShow(layoutProperty->GetHoverShowValue());
2843     arrowLayoutProperty->UpdateIsShowBackground(layoutProperty->GetIsShowBackgroundValue());
2844     arrowLayoutProperty->UpdateBackgroundSize(layoutProperty->GetBackgroundSizeValue());
2845     arrowLayoutProperty->UpdateBackgroundColor(layoutProperty->GetBackgroundColorValue());
2846     arrowLayoutProperty->UpdateArrowSize(layoutProperty->GetArrowSizeValue());
2847     arrowLayoutProperty->UpdateArrowColor(layoutProperty->GetArrowColorValue());
2848     arrowLayoutProperty->UpdateIsSidebarMiddle(layoutProperty->GetIsSidebarMiddleValue());
2849 }
2850 
SetAccessibilityAction()2851 void SwiperPattern::SetAccessibilityAction()
2852 {
2853     auto host = GetHost();
2854     CHECK_NULL_VOID(host);
2855     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
2856     CHECK_NULL_VOID(accessibilityProperty);
2857     accessibilityProperty->SetActionScrollForward(
2858         [weakPtr = WeakClaim(this), accessibility = WeakClaim(RawPtr(accessibilityProperty))]() {
2859             const auto& pattern = weakPtr.Upgrade();
2860             CHECK_NULL_VOID(pattern);
2861             const auto& accessibilityProperty = accessibility.Upgrade();
2862             CHECK_NULL_VOID(accessibilityProperty);
2863             if (!accessibilityProperty->IsScrollable()) {
2864                 return;
2865             }
2866             pattern->ShowNext();
2867         });
2868 
2869     accessibilityProperty->SetActionScrollBackward(
2870         [weakPtr = WeakClaim(this), accessibility = WeakClaim(RawPtr(accessibilityProperty))]() {
2871             const auto& pattern = weakPtr.Upgrade();
2872             CHECK_NULL_VOID(pattern);
2873             const auto& accessibilityProperty = accessibility.Upgrade();
2874             CHECK_NULL_VOID(accessibilityProperty);
2875             if (!accessibilityProperty->IsScrollable()) {
2876                 return;
2877             }
2878             pattern->ShowPrevious();
2879         });
2880 }
2881 
NeedStartAutoPlay() const2882 bool SwiperPattern::NeedStartAutoPlay() const
2883 {
2884     return isWindowShow_ && isVisibleArea_ && isVisible_;
2885 }
2886 
ProvideRestoreInfo()2887 std::string SwiperPattern::ProvideRestoreInfo()
2888 {
2889     auto jsonObj = JsonUtil::Create(true);
2890     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2891     CHECK_NULL_RETURN(swiperLayoutProperty, "");
2892     jsonObj->Put("Index", swiperLayoutProperty->GetIndex().value_or(0));
2893     return jsonObj->ToString();
2894 }
2895 
OnRestoreInfo(const std::string & restoreInfo)2896 void SwiperPattern::OnRestoreInfo(const std::string& restoreInfo)
2897 {
2898     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2899     CHECK_NULL_VOID(swiperLayoutProperty);
2900     auto info = JsonUtil::ParseJsonString(restoreInfo);
2901     if (!info->IsValid() || !info->IsObject()) {
2902         return;
2903     }
2904     auto jsonIsOn = info->GetValue("Index");
2905     swiperLayoutProperty->UpdateIndex(jsonIsOn->GetInt());
2906     OnModifyDone();
2907 }
2908 
InitHoverMouseEvent()2909 void SwiperPattern::InitHoverMouseEvent()
2910 {
2911     auto host = GetHost();
2912     CHECK_NULL_VOID(host);
2913     auto eventHub = host->GetEventHub<EventHub>();
2914     CHECK_NULL_VOID(eventHub);
2915     auto inputHub = eventHub->GetOrCreateInputEventHub();
2916     CHECK_NULL_VOID(inputHub);
2917 
2918     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
2919         auto pattern = weak.Upgrade();
2920         CHECK_NULL_VOID(pattern);
2921         if (!pattern->IsShowIndicator()) {
2922             pattern->ArrowHover(isHover);
2923         }
2924     };
2925 
2926     if (!hoverEvent_) {
2927         hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
2928         inputHub->AddOnHoverEvent(hoverEvent_);
2929     }
2930 
2931     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
2932         auto pattern = weak.Upgrade();
2933         if (pattern) {
2934             pattern->HandleMouseEvent(info);
2935         }
2936     };
2937     if (mouseEvent_) {
2938         inputHub->RemoveOnMouseEvent(mouseEvent_);
2939     }
2940     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
2941     inputHub->AddOnMouseEvent(mouseEvent_);
2942 }
2943 
HandleMouseEvent(const MouseInfo & info)2944 void SwiperPattern::HandleMouseEvent(const MouseInfo& info)
2945 {
2946     auto mouseOffsetX = static_cast<float>(info.GetLocalLocation().GetX());
2947     auto mouseOffsetY = static_cast<float>(info.GetLocalLocation().GetY());
2948     auto mousePoint = PointF(mouseOffsetX, mouseOffsetY);
2949     if (IsShowIndicator()) {
2950         CheckAndSetArrowHoverState(mousePoint);
2951     }
2952 }
2953 
CheckAndSetArrowHoverState(const PointF & mousePoint)2954 void SwiperPattern::CheckAndSetArrowHoverState(const PointF& mousePoint)
2955 {
2956     if (!HasLeftButtonNode() || !HasRightButtonNode() || !HasIndicatorNode()) {
2957         return;
2958     }
2959 
2960     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
2961     CHECK_NULL_VOID(layoutProperty);
2962     if (layoutProperty->GetIsSidebarMiddleValue(false)) {
2963         return;
2964     }
2965 
2966     RectF leftNodeRect;
2967     RectF rightNodeRect;
2968 
2969     leftNodeRect = GetArrowFrameRect(GetLeftButtonId());
2970     rightNodeRect = GetArrowFrameRect(GetRightButtonId());
2971 
2972     if (!IsLoop() && GetLoopIndex(currentIndex_) == 0) {
2973         leftNodeRect = GetArrowFrameRect(GetIndicatorId());
2974     }
2975 
2976     if (!IsLoop() && GetLoopIndex(currentIndex_) == TotalCount() - 1) {
2977         rightNodeRect = GetArrowFrameRect(GetIndicatorId());
2978     }
2979     RectF newNodeRect;
2980     if (GetDirection() == Axis::HORIZONTAL) {
2981         newNodeRect = RectF(leftNodeRect.Left(), leftNodeRect.Top(), rightNodeRect.Right() - leftNodeRect.Left(),
2982             std::min(rightNodeRect.Height(), leftNodeRect.Height()));
2983     } else {
2984         newNodeRect = RectF(leftNodeRect.Left(), leftNodeRect.Top(),
2985             std::min(rightNodeRect.Width(), leftNodeRect.Width()), rightNodeRect.Bottom() - leftNodeRect.Top());
2986     }
2987 
2988     isAtHotRegion_ = newNodeRect.IsInRegion(mousePoint);
2989     ArrowHover(isAtHotRegion_);
2990 }
2991 
GetArrowFrameRect(const int32_t index) const2992 RectF SwiperPattern::GetArrowFrameRect(const int32_t index) const
2993 {
2994     auto swiperNode = GetHost();
2995     CHECK_NULL_RETURN(swiperNode, RectF(0, 0, 0, 0));
2996     auto arrowNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperNode->GetChildIndexById(index)));
2997     CHECK_NULL_RETURN(arrowNode, RectF(0, 0, 0, 0));
2998     auto arrowGeometryNode = arrowNode->GetGeometryNode();
2999     CHECK_NULL_RETURN(arrowGeometryNode, RectF(0, 0, 0, 0));
3000     return arrowGeometryNode->GetFrameRect();
3001 }
3002 
GetCustomPropertyOffset() const3003 float SwiperPattern::GetCustomPropertyOffset() const
3004 {
3005     auto layoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
3006     CHECK_NULL_RETURN(layoutProperty, 0.0);
3007     auto paddingAndBorder = layoutProperty->CreatePaddingAndBorder();
3008     auto paddingAndBorderValue =
3009         GetDirection() == Axis::HORIZONTAL ? paddingAndBorder.left.value_or(0.0) : paddingAndBorder.top.value_or(0.0);
3010 
3011     auto preMarginPX = GetPrevMargin();
3012     if (layoutProperty->GetPrevMargin().has_value() && preMarginPX > 0.0) {
3013         preMarginPX += GetItemSpace();
3014     }
3015 
3016     return Dimension(paddingAndBorderValue + preMarginPX, DimensionUnit::PX).ConvertToVp();
3017 }
3018 
GetCurrentFirstIndexStartPos() const3019 float SwiperPattern::GetCurrentFirstIndexStartPos() const
3020 {
3021     if (itemPosition_.empty()) {
3022         return 0.0;
3023     }
3024 
3025     return itemPosition_.begin()->second.startPos;
3026 }
3027 
TotalDisPlayCount() const3028 int32_t SwiperPattern::TotalDisPlayCount() const
3029 {
3030     auto swiperLayoutProperty = GetLayoutProperty<SwiperLayoutProperty>();
3031     CHECK_NULL_RETURN(swiperLayoutProperty, 1);
3032     auto displayCount = GetDisplayCount();
3033     if (SwiperUtils::IsStretch(swiperLayoutProperty)) {
3034         if (Positive(swiperLayoutProperty->GetPrevMarginValue(0.0_px).ConvertToPx())) {
3035             displayCount++;
3036         }
3037         if (Positive(swiperLayoutProperty->GetNextMarginValue(0.0_px).ConvertToPx())) {
3038             displayCount++;
3039         }
3040     }
3041     return displayCount;
3042 }
3043 
ResetAndUpdateIndexOnAnimationEnd(int32_t nextIndex)3044 void SwiperPattern::ResetAndUpdateIndexOnAnimationEnd(int32_t nextIndex)
3045 {
3046     auto host = GetHost();
3047     CHECK_NULL_VOID(host);
3048     targetIndex_.reset();
3049     if (preTargetIndex_.has_value()) {
3050         preTargetIndex_.reset();
3051     }
3052 
3053     if (currentIndex_ == nextIndex) {
3054         return;
3055     }
3056 
3057     if (isFinishAnimation_) {
3058         currentDelta_ = 0.0f;
3059         itemPosition_.clear();
3060         isVoluntarilyClear_ = true;
3061         jumpIndex_ = nextIndex;
3062         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3063         auto pipeline = PipelineContext::GetCurrentContext();
3064         if (pipeline) {
3065             pipeline->FlushUITasks();
3066         }
3067         isFinishAnimation_ = false;
3068     } else {
3069         UpdateCurrentIndex(nextIndex);
3070         do {
3071             auto curChild = host->GetChildAtIndex(currentIndex_);
3072             if (!curChild) {
3073                 break;
3074             }
3075             auto curChildFrame = AceType::DynamicCast<FrameNode>(curChild);
3076             if (!curChildFrame) {
3077                 break;
3078             }
3079             FlushFocus(curChildFrame);
3080         } while (0);
3081         oldIndex_ = nextIndex;
3082         currentFirstIndex_ = GetLoopIndex(nextIndex);
3083         turnPageRate_ = 0.0f;
3084         currentIndexOffset_ = 0.0f;
3085         auto pipeline = PipelineContext::GetCurrentContext();
3086         if (pipeline) {
3087             pipeline->FlushUITasks();
3088             pipeline->FlushMessages();
3089         }
3090         FireChangeEvent();
3091         // lazyBuild feature.
3092         SetLazyLoadFeature(true);
3093     }
3094 }
3095 } // namespace OHOS::Ace::NG
3096