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