1 /*
2 * Copyright (c) 2024 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_indicator/dot_indicator/overlength_dot_indicator_modifier.h"
17 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
18
19 namespace OHOS::Ace::NG {
20 namespace {
21 constexpr Dimension INDICATOR_PADDING_DEFAULT = 12.0_vp;
22 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.2f;
23 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
24 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 0.2f;
25 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
26 constexpr float SMALLEST_POINT_RATIO = 1.0f / 3.0f;
27 constexpr float SECOND_SMALLEST_POINT_RATIO = 2.0f / 3.0f;
28 constexpr float NORMAL_FADING_RATIO = 1.0f;
29 constexpr double FULL_ALPHA = 255.0;
30 constexpr int32_t BLACK_POINT_DURATION = 400;
31 constexpr int32_t LEFT_FIRST_POINT_INDEX = 0;
32 constexpr int32_t SECOND_POINT_INDEX = 1;
33 constexpr int32_t THIRD_POINT_INDEX = 2;
34 constexpr uint32_t ITEM_HALF_WIDTH = 0;
35 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
36 constexpr float HALF_FLOAT = 0.5f;
37 constexpr int32_t OVERLONG_SMALL_COUNT = 2;
38 constexpr int32_t DOUBLE_INT = 2;
39 } // namespace
40
onDraw(DrawingContext & context)41 void OverlengthDotIndicatorModifier::onDraw(DrawingContext& context)
42 {
43 ContentProperty contentProperty;
44 contentProperty.backgroundColor = backgroundColor_->Get().ToColor();
45 contentProperty.unselectedIndicatorWidth = unselectedIndicatorWidth_->Get();
46 contentProperty.unselectedIndicatorHeight = unselectedIndicatorHeight_->Get();
47 contentProperty.vectorBlackPointCenterX = vectorBlackPointCenterX_->Get();
48 contentProperty.longPointLeftCenterX = longPointLeftCenterX_->Get();
49 contentProperty.longPointRightCenterX = longPointRightCenterX_->Get();
50 contentProperty.normalToHoverPointDilateRatio = normalToHoverPointDilateRatio_->Get();
51 contentProperty.hoverToNormalPointDilateRatio = hoverToNormalPointDilateRatio_->Get();
52 contentProperty.longPointDilateRatio = longPointDilateRatio_->Get();
53 contentProperty.indicatorPadding = indicatorPadding_->Get();
54 contentProperty.indicatorMargin = indicatorMargin_->Get();
55 contentProperty.itemHalfSizes = itemHalfSizes_->Get();
56 contentProperty.firstPointOpacity = firstPointOpacity_->Get();
57 contentProperty.newPointOpacity = newPointOpacity_->Get();
58
59 PaintBackground(context, contentProperty, maxDisplayCount_, isBindIndicator_);
60 PaintContent(context, contentProperty);
61 }
62
GetTouchBottomCenterX(ContentProperty & contentProperty)63 std::pair<float, float> OverlengthDotIndicatorModifier::GetTouchBottomCenterX(ContentProperty& contentProperty)
64 {
65 float leftCenterX = contentProperty.longPointLeftCenterX;
66 float rightCenterX = contentProperty.longPointRightCenterX;
67
68 if (isCustomSize_ || contentProperty.vectorBlackPointCenterX.empty() ||
69 static_cast<int32_t>(contentProperty.vectorBlackPointCenterX.size()) < maxDisplayCount_) {
70 return { leftCenterX, rightCenterX };
71 }
72
73 auto currentIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - currentIndex_ : currentIndex_;
74 bool isLeftTouchBottom = (currentIndex == realItemCount_ - 1);
75 bool isRightTouchBottom = (currentIndex == 0);
76 float radius = (rightCenterX - leftCenterX) * HALF_FLOAT;
77 if ((animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isLeftTouchBottom) ||
78 (animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isRightTouchBottom)) {
79 leftCenterX = contentProperty.vectorBlackPointCenterX[0] - radius;
80 rightCenterX = contentProperty.vectorBlackPointCenterX[0] + radius;
81 } else if ((animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isLeftTouchBottom) ||
82 (animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isRightTouchBottom)) {
83 leftCenterX = contentProperty.vectorBlackPointCenterX[maxDisplayCount_ - 1] - radius;
84 rightCenterX = contentProperty.vectorBlackPointCenterX[maxDisplayCount_ - 1] + radius;
85 }
86
87 return { leftCenterX, rightCenterX };
88 }
89
PaintContent(DrawingContext & context,ContentProperty & contentProperty)90 void OverlengthDotIndicatorModifier::PaintContent(DrawingContext& context, ContentProperty& contentProperty)
91 {
92 PaintBlackPoint(context, contentProperty);
93 RSCanvas& canvas = context.canvas;
94 auto [leftCenterX, rightCenterX] = GetTouchBottomCenterX(contentProperty);
95
96 OffsetF leftCenter = { leftCenterX, centerY_ };
97 OffsetF rightCenter = { rightCenterX, centerY_ };
98 OffsetF centerDistance = rightCenter - leftCenter;
99 OffsetF centerDilateDistance = centerDistance * contentProperty.longPointDilateRatio;
100 leftCenter -= (centerDilateDistance - centerDistance) * HALF_FLOAT;
101 rightCenter += (centerDilateDistance - centerDistance) * HALF_FLOAT;
102 PaintSelectedIndicator(
103 canvas, leftCenter, rightCenter, contentProperty.itemHalfSizes * contentProperty.longPointDilateRatio, true);
104 }
105
PaintBlackPoint(DrawingContext & context,ContentProperty & contentProperty)106 void OverlengthDotIndicatorModifier::PaintBlackPoint(DrawingContext& context, ContentProperty& contentProperty)
107 {
108 RSCanvas& canvas = context.canvas;
109 auto totalCount = contentProperty.vectorBlackPointCenterX.size();
110 for (size_t i = 0; i < totalCount; ++i) {
111 if (i >= contentProperty.unselectedIndicatorWidth.size() ||
112 i >= contentProperty.unselectedIndicatorHeight.size()) {
113 break;
114 }
115
116 OffsetF center = { contentProperty.vectorBlackPointCenterX[i], centerY_ };
117 float width = contentProperty.unselectedIndicatorWidth[i];
118 float height = contentProperty.unselectedIndicatorHeight[i];
119
120 auto paintColor = unselectedColor_->Get();
121 bool isFirstPoint = (i == 0 && moveDirection_ == OverlongIndicatorMove::MOVE_BACKWARD) ||
122 (i == totalCount - 2 && moveDirection_ == OverlongIndicatorMove::MOVE_FORWARD);
123 if (isFirstPoint) {
124 // first point color
125 paintColor = paintColor.BlendOpacity(contentProperty.firstPointOpacity / FULL_ALPHA);
126 } else if (i == totalCount - 1 && moveDirection_ != OverlongIndicatorMove::NONE) {
127 // new point color
128 paintColor = paintColor.BlendOpacity(contentProperty.newPointOpacity / FULL_ALPHA);
129 }
130
131 PaintUnselectedIndicator(canvas, center, width, height, LinearColor(paintColor));
132 }
133 }
134
PaintUnselectedIndicator(RSCanvas & canvas,const OffsetF & center,float width,float height,const LinearColor & indicatorColor)135 void OverlengthDotIndicatorModifier::PaintUnselectedIndicator(
136 RSCanvas& canvas, const OffsetF& center, float width, float height, const LinearColor& indicatorColor)
137 {
138 RSBrush brush;
139 brush.SetAntiAlias(true);
140 brush.SetColor(ToRSColor(indicatorColor));
141 canvas.AttachBrush(brush);
142 if (!NearEqual(width, height) || !isCustomSize_) {
143 float rectLeft =
144 (axis_ == Axis::HORIZONTAL ? center.GetX() - width * HALF_FLOAT : center.GetY() - height * HALF_FLOAT);
145 float rectTop =
146 (axis_ == Axis::HORIZONTAL ? center.GetY() - height * HALF_FLOAT : center.GetX() - width * HALF_FLOAT);
147 float rectRight =
148 (axis_ == Axis::HORIZONTAL ? center.GetX() + width * HALF_FLOAT : center.GetY() + height * HALF_FLOAT);
149 float rectBottom =
150 (axis_ == Axis::HORIZONTAL ? center.GetY() + height * HALF_FLOAT : center.GetX() + width * HALF_FLOAT);
151
152 if (height > width || !isCustomSize_) {
153 canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, width, width });
154 } else if (height < width) {
155 canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, height, height });
156 } else {
157 float customPointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
158 float customPointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
159 canvas.DrawCircle({ customPointX, customPointY }, height * HALF_FLOAT);
160 }
161 } else {
162 float pointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
163 float pointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
164 canvas.DrawCircle({ pointX, pointY }, width * HALF_FLOAT);
165 }
166 canvas.DetachBrush();
167 }
168
UpdateShrinkPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const std::pair<float,float> & longPointCenterX)169 void OverlengthDotIndicatorModifier::UpdateShrinkPaintProperty(const OffsetF& margin,
170 const LinearVector<float>& normalItemHalfSizes, const std::pair<float, float>& longPointCenterX)
171 {
172 indicatorMargin_->Set(margin);
173 indicatorPadding_->Set(static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx()));
174
175 if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
176 longPointLeftCenterX_->Set(longPointCenterX.first);
177 longPointRightCenterX_->Set(longPointCenterX.second);
178 }
179
180 vectorBlackPointCenterX_->Set(animationEndCenterX_);
181 unselectedIndicatorWidth_->Set(animationEndIndicatorWidth_);
182 unselectedIndicatorHeight_->Set(animationEndIndicatorHeight_);
183 itemHalfSizes_->Set(normalItemHalfSizes);
184 normalToHoverPointDilateRatio_->Set(NORMAL_FADING_RATIO);
185 hoverToNormalPointDilateRatio_->Set(NORMAL_FADING_RATIO);
186 longPointDilateRatio_->Set(NORMAL_FADING_RATIO);
187 backgroundWidthDilateRatio_->Set(NORMAL_FADING_RATIO);
188 backgroundHeightDilateRatio_->Set(NORMAL_FADING_RATIO);
189
190 if (blackPointsAnimEnd_) {
191 currentSelectedIndex_ = targetSelectedIndex_;
192 currentOverlongType_ = targetOverlongType_;
193 }
194 }
195
UpdateNormalPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const std::pair<float,float> & longPointCenterX)196 void OverlengthDotIndicatorModifier::UpdateNormalPaintProperty(const OffsetF& margin,
197 const LinearVector<float>& normalItemHalfSizes, const std::pair<float, float>& longPointCenterX)
198 {
199 normalMargin_ = margin;
200 CalcAnimationEndCenterX(normalItemHalfSizes);
201 auto swiperTheme = GetSwiperIndicatorTheme();
202 CHECK_NULL_VOID(swiperTheme);
203 auto backgroundColor =
204 indicatorMask_ ? swiperTheme->GetPressedColor() : swiperTheme->GetHoverColor().ChangeOpacity(0);
205 UpdateShrinkPaintProperty(margin, normalItemHalfSizes, overlongSelectedEndCenterX_);
206 UpdateBackgroundColor(backgroundColor);
207 }
208
CalcLongPointEndCenterXWithBlack(size_t index,const LinearVector<float> & itemHalfSizes)209 std::pair<float, float> OverlengthDotIndicatorModifier::CalcLongPointEndCenterXWithBlack(
210 size_t index, const LinearVector<float>& itemHalfSizes)
211 {
212 if (isHorizontalAndRTL_) {
213 index = static_cast<size_t>(maxDisplayCount_ - 1 - static_cast<int32_t>(index));
214 }
215
216 if (index >= animationEndCenterX_.size()) {
217 return std::make_pair(0.0f, 0.0f);
218 }
219
220 auto selectedIndicatorRadius = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
221 if (!isCustomSizeValue_) {
222 selectedIndicatorRadius *= 2.0f;
223 }
224
225 auto longPointLeftEndCenterX = animationEndCenterX_[index] - selectedIndicatorRadius * HALF_FLOAT;
226 auto longPointRightEndCenterX = animationEndCenterX_[index] + selectedIndicatorRadius * HALF_FLOAT;
227 return std::make_pair(longPointLeftEndCenterX, longPointRightEndCenterX);
228 }
229
GetBlackPointsAnimationDuration() const230 int32_t OverlengthDotIndicatorModifier::GetBlackPointsAnimationDuration() const
231 {
232 if (InstanceOf<InterpolatingSpring>(headCurve_)) {
233 return BLACK_POINT_DURATION;
234 }
235
236 return animationDuration_;
237 }
238
NeedUpdateWhenAnimationFinish() const239 bool OverlengthDotIndicatorModifier::NeedUpdateWhenAnimationFinish() const
240 {
241 if (NearZero(forceStopPageRate_) || NearEqual(forceStopPageRate_, -1.0f) ||
242 NearEqual(forceStopPageRate_, FLT_MAX)) {
243 return true;
244 }
245
246 if ((currentSelectedIndex_ == 0 && targetSelectedIndex_ == maxDisplayCount_ - 1) ||
247 (currentSelectedIndex_ == maxDisplayCount_ - 1 && targetSelectedIndex_ == 0)) {
248 return true;
249 }
250
251 if (std::abs(forceStopPageRate_) < HALF_FLOAT && currentSelectedIndex_ < targetSelectedIndex_) {
252 return false;
253 }
254
255 if (std::abs(forceStopPageRate_) >= HALF_FLOAT && currentSelectedIndex_ > targetSelectedIndex_) {
256 return false;
257 }
258
259 return true;
260 }
261
PlayBlackPointsAnimation(const LinearVector<float> & itemHalfSizes)262 void OverlengthDotIndicatorModifier::PlayBlackPointsAnimation(const LinearVector<float>& itemHalfSizes)
263 {
264 AnimationOption blackPointOption;
265 auto pointMoveCurve = AceType::MakeRefPtr<CubicCurve>(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY,
266 CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING);
267 blackPointOption.SetCurve(pointMoveCurve);
268 blackPointOption.SetDuration(GetBlackPointsAnimationDuration());
269
270 vectorBlackPointCenterX_->Set(animationStartCenterX_);
271 unselectedIndicatorWidth_->Set(animationStartIndicatorWidth_);
272 unselectedIndicatorHeight_->Set(animationStartIndicatorHeight_);
273 firstPointOpacity_->Set(UINT8_MAX);
274 newPointOpacity_->Set(0);
275 isSelectedColorAnimEnd_ = false;
276 isTouchBottomLoop_ = true;
277 auto longPointEndCenterX =
278 CalcLongPointEndCenterXWithBlack(static_cast<size_t>(targetSelectedIndex_), itemHalfSizes);
279 blackPointsAnimEnd_ = false;
280 AnimationUtils::StartAnimation(blackPointOption, [&]() {
281 vectorBlackPointCenterX_->Set(animationEndCenterX_);
282 unselectedIndicatorWidth_->Set(animationEndIndicatorWidth_);
283 unselectedIndicatorHeight_->Set(animationEndIndicatorHeight_);
284
285 if (moveDirection_ != OverlongIndicatorMove::NONE) {
286 firstPointOpacity_->Set(0);
287 newPointOpacity_->Set(UINT8_MAX);
288 longPointLeftCenterX_->Set(longPointEndCenterX.first);
289 longPointRightCenterX_->Set(longPointEndCenterX.second);
290 }
291 }, [weak = WeakClaim(this)]() {
292 auto modifier = weak.Upgrade();
293 CHECK_NULL_VOID(modifier);
294
295 if (!modifier->NeedUpdateWhenAnimationFinish()) {
296 return;
297 }
298
299 if (!modifier->blackPointsAnimEnd_ && (modifier->needUpdate_ || !modifier->isAutoPlay_)) {
300 modifier->currentSelectedIndex_ = modifier->targetSelectedIndex_;
301 modifier->currentOverlongType_ = modifier->targetOverlongType_;
302 modifier->blackPointsAnimEnd_ = true;
303 modifier->needUpdate_ = false;
304 }
305 });
306 }
307
RevertOverlongType(OverlongType overlongType) const308 OverlongType OverlengthDotIndicatorModifier::RevertOverlongType(OverlongType overlongType) const
309 {
310 if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
311 return OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
312 } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
313 return OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
314 }
315
316 return overlongType;
317 }
318
CalcIndicatorSize(const LinearVector<float> & itemHalfSizes,OverlongType overlongType,bool isWidth)319 LinearVector<float> OverlengthDotIndicatorModifier::CalcIndicatorSize(
320 const LinearVector<float>& itemHalfSizes, OverlongType overlongType, bool isWidth)
321 {
322 if (isHorizontalAndRTL_) {
323 overlongType = RevertOverlongType(overlongType);
324 }
325
326 auto unselectedIndicatorRadius = isWidth ? itemHalfSizes[0] : itemHalfSizes[1];
327 LinearVector<float> indicatorSize(maxDisplayCount_ + 1);
328
329 auto secondSmallestRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
330 auto smallestRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
331
332 for (int32_t i = 0; i < maxDisplayCount_; i++) {
333 if (i == LEFT_FIRST_POINT_INDEX) {
334 if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
335 indicatorSize[i] = unselectedIndicatorRadius * 2;
336 } else {
337 indicatorSize[i] = smallestRadius * 2;
338 }
339 continue;
340 }
341
342 if (i == SECOND_POINT_INDEX) {
343 if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
344 indicatorSize[i] = unselectedIndicatorRadius * 2;
345 } else {
346 indicatorSize[i] = secondSmallestRadius * 2;
347 }
348 continue;
349 }
350
351 if (i >= THIRD_POINT_INDEX && i <= maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
352 indicatorSize[i] = unselectedIndicatorRadius * 2;
353 continue;
354 }
355
356 if (i == maxDisplayCount_ - 1 - SECOND_POINT_INDEX) {
357 if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
358 indicatorSize[i] = unselectedIndicatorRadius * 2;
359 } else {
360 indicatorSize[i] = secondSmallestRadius * 2;
361 }
362 continue;
363 }
364
365 if (i == maxDisplayCount_ - 1) {
366 if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
367 indicatorSize[i] = unselectedIndicatorRadius * 2;
368 } else {
369 indicatorSize[i] = smallestRadius * 2;
370 }
371 continue;
372 }
373 }
374
375 return indicatorSize;
376 }
377
UpdateSelectedCenterXOnDrag(const LinearVector<float> & itemHalfSizes)378 void OverlengthDotIndicatorModifier::UpdateSelectedCenterXOnDrag(const LinearVector<float>& itemHalfSizes)
379 {
380 if (gestureState_ != GestureState::GESTURE_STATE_FOLLOW_LEFT &&
381 gestureState_ != GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
382 return;
383 }
384
385 auto leftMoveRate = longPointLeftCenterMoveRate_;
386 auto rightMoveRate = longPointRightCenterMoveRate_;
387 if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
388 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
389 leftMoveRate = 1.0f - longPointLeftCenterMoveRate_;
390 rightMoveRate = 1.0f - longPointRightCenterMoveRate_;
391 }
392
393 auto targetIndex = isHorizontalAndRTL_ ? currentSelectedIndex_ - 1 : currentSelectedIndex_ + 1;
394 if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
395 targetIndex = isHorizontalAndRTL_ ? currentSelectedIndex_ + 1 : currentSelectedIndex_ - 1;
396 }
397
398 auto longPointEndCenterX = CalcLongPointEndCenterXWithBlack(static_cast<size_t>(targetIndex), itemHalfSizes);
399 if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
400 auto dragTargetCenterX = (overlongSelectedEndCenterX_.second + overlongSelectedEndCenterX_.first) * HALF_FLOAT;
401 overlongSelectedEndCenterX_.first = overlongSelectedStartCenterX_.first +
402 (dragTargetCenterX - overlongSelectedStartCenterX_.first) * leftMoveRate;
403
404 overlongSelectedEndCenterX_.second = overlongSelectedStartCenterX_.second +
405 (dragTargetCenterX - overlongSelectedStartCenterX_.second) * rightMoveRate;
406 } else {
407 auto leftDistance = overlongSelectedEndCenterX_.first - overlongSelectedStartCenterX_.first;
408 auto rightDistance = overlongSelectedEndCenterX_.second - overlongSelectedStartCenterX_.second;
409 if (currentSelectedIndex_ == targetSelectedIndex_ && isSwiperTouchDown_) {
410 leftDistance = longPointEndCenterX.first - overlongSelectedStartCenterX_.first;
411 rightDistance = longPointEndCenterX.second - overlongSelectedStartCenterX_.second;
412 }
413
414 overlongSelectedEndCenterX_.first = overlongSelectedStartCenterX_.first + leftDistance * leftMoveRate;
415 overlongSelectedEndCenterX_.second = overlongSelectedStartCenterX_.second + rightDistance * rightMoveRate;
416 }
417 }
418
GetMoveRateOnAllMove() const419 float OverlengthDotIndicatorModifier::GetMoveRateOnAllMove() const
420 {
421 float blackPointCenterMoveRate = CubicCurve(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
422 CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING)
423 .MoveInternal(std::abs(turnPageRate_));
424 if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
425 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
426 blackPointCenterMoveRate = 1.0f;
427 }
428
429 return blackPointCenterMoveRate;
430 }
431
UpdateUnselectedCenterXOnDrag()432 void OverlengthDotIndicatorModifier::UpdateUnselectedCenterXOnDrag()
433 {
434 if (gestureState_ != GestureState::GESTURE_STATE_FOLLOW_LEFT &&
435 gestureState_ != GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
436 return;
437 }
438
439 auto moveRate = blackPointCenterMoveRate_;
440 if (currentOverlongType_ != targetOverlongType_ || currentSelectedIndex_ == targetSelectedIndex_) {
441 moveRate = GetMoveRateOnAllMove();
442 }
443
444 if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
445 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
446 moveRate = 1.0f - moveRate;
447 }
448
449 for (size_t i = 0; i < animationEndIndicatorWidth_.size(); i++) {
450 animationEndIndicatorWidth_[i] = animationStartIndicatorWidth_[i] +
451 (animationEndIndicatorWidth_[i] - animationStartIndicatorWidth_[i]) * moveRate;
452 }
453
454 for (size_t i = 0; i < animationEndIndicatorHeight_.size(); i++) {
455 animationEndIndicatorHeight_[i] =
456 animationStartIndicatorHeight_[i] +
457 (animationEndIndicatorHeight_[i] - animationStartIndicatorHeight_[i]) * moveRate;
458 }
459
460 for (size_t i = 0; i < animationEndCenterX_.size(); i++) {
461 animationEndCenterX_[i] =
462 animationStartCenterX_[i] + (animationEndCenterX_[i] - animationStartCenterX_[i]) * moveRate;
463 }
464 }
465
CalcTargetIndexOnDrag() const466 int32_t OverlengthDotIndicatorModifier::CalcTargetIndexOnDrag() const
467 {
468 if (NearEqual(turnPageRate_, 0.0f)) {
469 return animationEndIndex_;
470 }
471
472 auto startIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - animationStartIndex_ : animationStartIndex_;
473 auto endIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - animationEndIndex_ : animationEndIndex_;
474 if (startIndex == endIndex) {
475 if (startIndex == realItemCount_ - 1) {
476 return animationStartIndex_;
477 }
478 return isHorizontalAndRTL_ ? animationStartIndex_ - 1 : animationStartIndex_ + 1;
479 }
480
481 if (startIndex == 0 && endIndex == realItemCount_ - 1) {
482 return animationStartIndex_;
483 }
484
485 return animationEndIndex_;
486 }
487
CalcTargetStatusOnLongPointMove(const LinearVector<float> & itemHalfSizes)488 void OverlengthDotIndicatorModifier::CalcTargetStatusOnLongPointMove(const LinearVector<float>& itemHalfSizes)
489 {
490 auto endCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
491 animationEndCenterX_ = endCenterX.first;
492 overlongSelectedEndCenterX_ = endCenterX.second;
493 animationStartIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, true);
494 animationStartIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, false);
495
496 animationEndIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
497 animationEndIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
498
499 if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
500 animationStartCenterX_.resize(maxDisplayCount_);
501 animationEndCenterX_.resize(maxDisplayCount_);
502 animationStartIndicatorWidth_.resize(maxDisplayCount_);
503 animationStartIndicatorHeight_.resize(maxDisplayCount_);
504 animationEndIndicatorWidth_.resize(maxDisplayCount_);
505 animationEndIndicatorHeight_.resize(maxDisplayCount_);
506 }
507
508 if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
509 gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
510 if (NearZero(turnPageRate_) && touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
511 return;
512 }
513
514 UpdateUnselectedCenterXOnDrag();
515 UpdateSelectedCenterXOnDrag(itemHalfSizes);
516 targetSelectedIndex_ = currentSelectedIndex_;
517 targetOverlongType_ = currentOverlongType_;
518 }
519 }
520
CalcTargetStatusOnAllPointMoveForward(const LinearVector<float> & itemHalfSizes)521 void OverlengthDotIndicatorModifier::CalcTargetStatusOnAllPointMoveForward(const LinearVector<float>& itemHalfSizes)
522 {
523 auto targetCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
524 overlongSelectedEndCenterX_ = targetCenterX.second;
525 auto targetIndicatorWidth = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
526 auto targetIndicatorHeight = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
527
528 float itemSpacePx = static_cast<float>(GetIndicatorDotItemSpace().ConvertToPx());
529 // calc new point current position
530 animationStartCenterX_[maxDisplayCount_] =
531 animationStartCenterX_[0] - animationStartIndicatorWidth_[0] - itemSpacePx;
532 animationStartIndicatorWidth_[maxDisplayCount_] = animationStartIndicatorWidth_[0];
533 animationStartIndicatorHeight_[maxDisplayCount_] = animationStartIndicatorHeight_[0];
534
535 // calc new point target position
536 animationEndCenterX_[maxDisplayCount_] = targetCenterX.first[0];
537 animationEndIndicatorWidth_[maxDisplayCount_] = targetIndicatorWidth[0];
538 animationEndIndicatorHeight_[maxDisplayCount_] = targetIndicatorHeight[0];
539
540 for (int32_t i = 0; i < maxDisplayCount_ - 1; i++) {
541 animationEndCenterX_[i] = targetCenterX.first[i + 1];
542 animationEndIndicatorWidth_[i] = targetIndicatorWidth[i + 1];
543 animationEndIndicatorHeight_[i] = targetIndicatorHeight[i + 1];
544 }
545
546 animationEndCenterX_[maxDisplayCount_ - 1] =
547 targetCenterX.first[maxDisplayCount_ - 1] + targetIndicatorWidth[maxDisplayCount_ - 1] + itemSpacePx;
548 animationEndIndicatorWidth_[maxDisplayCount_ - 1] = targetIndicatorWidth[maxDisplayCount_ - 1];
549 animationEndIndicatorHeight_[maxDisplayCount_ - 1] = targetIndicatorHeight[maxDisplayCount_ - 1];
550
551 UpdateUnselectedCenterXOnDrag();
552 UpdateSelectedCenterXOnDrag(itemHalfSizes);
553
554 if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
555 gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
556 targetSelectedIndex_ = currentSelectedIndex_;
557 targetOverlongType_ = currentOverlongType_;
558
559 auto opacityMoveRate = GetMoveRateOnAllMove();
560 auto firstPointOpacity = static_cast<uint8_t>(UINT8_MAX * opacityMoveRate);
561 auto newPointOpacity = static_cast<uint8_t>(UINT8_MAX * (1.0f - opacityMoveRate));
562 firstPointOpacity_->Set(firstPointOpacity);
563 newPointOpacity_->Set(newPointOpacity);
564 }
565 }
566
CalcTargetStatusOnAllPointMoveBackward(const LinearVector<float> & itemHalfSizes)567 void OverlengthDotIndicatorModifier::CalcTargetStatusOnAllPointMoveBackward(const LinearVector<float>& itemHalfSizes)
568 {
569 auto targetCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
570 overlongSelectedEndCenterX_ = targetCenterX.second;
571 auto targetIndicatorWidth = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
572 auto targetIndicatorHeight = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
573
574 float itemSpacePx = static_cast<float>(GetIndicatorDotItemSpace().ConvertToPx());
575 // calc new point current position
576 animationStartCenterX_[maxDisplayCount_] = animationStartCenterX_[maxDisplayCount_ - 1] +
577 animationStartIndicatorWidth_[maxDisplayCount_ - 1] + itemSpacePx;
578 animationStartIndicatorWidth_[maxDisplayCount_] = animationStartIndicatorWidth_[maxDisplayCount_ - 1];
579 animationStartIndicatorHeight_[maxDisplayCount_] = animationStartIndicatorHeight_[maxDisplayCount_ - 1];
580
581 // calc first point target position
582 auto distance = std::abs(targetCenterX.first[1] - targetCenterX.first[0]);
583 animationEndCenterX_[0] = targetCenterX.first[0] - distance;
584 animationEndIndicatorWidth_[0] = targetIndicatorWidth[0];
585 animationEndIndicatorHeight_[0] = targetIndicatorHeight[0];
586
587 for (int32_t i = 1; i <= maxDisplayCount_; i++) {
588 animationEndCenterX_[i] = targetCenterX.first[i - 1];
589 animationEndIndicatorWidth_[i] = targetIndicatorWidth[i - 1];
590 animationEndIndicatorHeight_[i] = targetIndicatorHeight[i - 1];
591 }
592
593 UpdateUnselectedCenterXOnDrag();
594 UpdateSelectedCenterXOnDrag(itemHalfSizes);
595
596 if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
597 gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
598 targetSelectedIndex_ = currentSelectedIndex_;
599 targetOverlongType_ = currentOverlongType_;
600
601 auto opacityMoveRate = GetMoveRateOnAllMove();
602 auto firstPointOpacity = static_cast<uint8_t>(UINT8_MAX * (1.0f - opacityMoveRate));
603 auto newPointOpacity = static_cast<uint8_t>(UINT8_MAX * opacityMoveRate);
604 firstPointOpacity_->Set(firstPointOpacity);
605 newPointOpacity_->Set(newPointOpacity);
606 }
607 }
608
CalcAnimationEndCenterX(const LinearVector<float> & itemHalfSizes)609 void OverlengthDotIndicatorModifier::CalcAnimationEndCenterX(const LinearVector<float>& itemHalfSizes)
610 {
611 if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
612 gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
613 animationEndIndex_ = CalcTargetIndexOnDrag();
614 }
615
616 CalcTargetOverlongStatus(animationStartIndex_, animationEndIndex_);
617
618 auto startCenterX = CalcIndicatorCenterX(itemHalfSizes, currentSelectedIndex_, currentOverlongType_);
619 animationStartCenterX_ = startCenterX.first;
620 overlongSelectedStartCenterX_ = startCenterX.second;
621
622 // long point move or no move
623 if (currentSelectedIndex_ != targetSelectedIndex_ || animationStartIndex_ == animationEndIndex_) {
624 moveDirection_ = OverlongIndicatorMove::NONE;
625 CalcTargetStatusOnLongPointMove(itemHalfSizes);
626 return;
627 }
628
629 animationStartIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, true);
630 animationStartIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, false);
631 animationEndCenterX_.resize(maxDisplayCount_ + 1);
632 animationEndIndicatorWidth_.resize(maxDisplayCount_ + 1);
633 animationEndIndicatorHeight_.resize(maxDisplayCount_ + 1);
634
635 auto isBackward =
636 isHorizontalAndRTL_ ? animationStartIndex_ > animationEndIndex_ : animationStartIndex_ < animationEndIndex_;
637 if (isBackward) {
638 moveDirection_ = OverlongIndicatorMove::MOVE_BACKWARD;
639 CalcTargetStatusOnAllPointMoveBackward(itemHalfSizes);
640 return;
641 }
642
643 moveDirection_ = OverlongIndicatorMove::MOVE_FORWARD;
644 CalcTargetStatusOnAllPointMoveForward(itemHalfSizes);
645 }
646
PlayIndicatorAnimation(const OffsetF & margin,const LinearVector<float> & itemHalfSizes,GestureState gestureState,TouchBottomTypeLoop touchBottomTypeLoop)647 void OverlengthDotIndicatorModifier::PlayIndicatorAnimation(const OffsetF& margin,
648 const LinearVector<float>& itemHalfSizes, GestureState gestureState, TouchBottomTypeLoop touchBottomTypeLoop)
649 {
650 StopBlackAnimation();
651
652 needUpdate_ = false;
653 blackPointsAnimEnd_ = true;
654 currentSelectedIndex_ = targetSelectedIndex_;
655 currentOverlongType_ = targetOverlongType_;
656 isTouchBottomLoop_ = false;
657 animationState_ = TouchBottomAnimationStage::STAGE_NONE;
658 normalMargin_ = margin;
659 CalcAnimationEndCenterX(itemHalfSizes);
660 PlayBlackPointsAnimation(itemHalfSizes);
661
662 std::vector<std::pair<float, float>> pointCenterX;
663 if ((currentSelectedIndex_ == 0 && targetSelectedIndex_ == maxDisplayCount_ - 1) ||
664 (currentSelectedIndex_ == maxDisplayCount_ - 1 && targetSelectedIndex_ == 0)) {
665 auto currentSelectedIndex =
666 isHorizontalAndRTL_ ? maxDisplayCount_ - 1 - currentSelectedIndex_ : currentSelectedIndex_;
667 overlongSelectedStartCenterX_.first = animationEndCenterX_[currentSelectedIndex];
668 overlongSelectedStartCenterX_.second = animationEndCenterX_[currentSelectedIndex];
669 pointCenterX.emplace_back(overlongSelectedStartCenterX_);
670 pointCenterX.emplace_back(overlongSelectedEndCenterX_);
671 } else {
672 pointCenterX.emplace_back(overlongSelectedEndCenterX_);
673 }
674
675 PlayLongPointAnimation(pointCenterX, gestureState, touchBottomTypeLoop, animationEndCenterX_, false);
676 }
677
StopBlackAnimation()678 void OverlengthDotIndicatorModifier::StopBlackAnimation()
679 {
680 AnimationOption option;
681 option.SetDuration(0);
682 option.SetCurve(Curves::LINEAR);
683 AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
684 auto modifier = weak.Upgrade();
685 CHECK_NULL_VOID(modifier);
686 modifier->vectorBlackPointCenterX_->Set(modifier->vectorBlackPointCenterX_->Get());
687 modifier->firstPointOpacity_->Set(modifier->firstPointOpacity_->Get());
688 modifier->newPointOpacity_->Set(modifier->newPointOpacity_->Get());
689 modifier->unselectedIndicatorWidth_->Set(modifier->unselectedIndicatorWidth_->Get());
690 modifier->unselectedIndicatorHeight_->Set(modifier->unselectedIndicatorHeight_->Get());
691 });
692
693 longPointLeftAnimEnd_ = true;
694 longPointRightAnimEnd_ = true;
695 ifNeedFinishCallback_ = false;
696 }
697
StopAnimation(bool ifImmediately)698 void OverlengthDotIndicatorModifier::StopAnimation(bool ifImmediately)
699 {
700 if (ifImmediately) {
701 AnimationOption option;
702 option.SetDuration(0);
703 option.SetCurve(Curves::LINEAR);
704 AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
705 auto modifier = weak.Upgrade();
706 CHECK_NULL_VOID(modifier);
707 modifier->longPointLeftCenterX_->Set(modifier->longPointLeftCenterX_->Get());
708 modifier->longPointRightCenterX_->Set(modifier->longPointRightCenterX_->Get());
709 });
710 }
711
712 StopBlackAnimation();
713 }
714
InitOverlongSelectedIndex(int32_t pageIndex)715 void OverlengthDotIndicatorModifier::InitOverlongSelectedIndex(int32_t pageIndex)
716 {
717 if (pageIndex < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
718 targetSelectedIndex_ = pageIndex;
719 return;
720 }
721
722 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
723 targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
724 return;
725 }
726
727 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
728 targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
729 return;
730 }
731
732 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
733 targetSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
734 return;
735 }
736
737 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1) {
738 targetSelectedIndex_ = maxDisplayCount_ - 1;
739 return;
740 }
741 }
742
InitOverlongStatus(int32_t pageIndex)743 void OverlengthDotIndicatorModifier::InitOverlongStatus(int32_t pageIndex)
744 {
745 if (pageIndex < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
746 currentSelectedIndex_ = pageIndex;
747 currentOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
748
749 targetSelectedIndex_ = currentSelectedIndex_;
750 targetOverlongType_ = currentOverlongType_;
751 return;
752 }
753
754 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
755 currentSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
756 currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
757
758 targetSelectedIndex_ = currentSelectedIndex_;
759 targetOverlongType_ = currentOverlongType_;
760 return;
761 }
762
763 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
764 currentSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
765 currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
766
767 targetSelectedIndex_ = currentSelectedIndex_;
768 targetOverlongType_ = currentOverlongType_;
769 return;
770 }
771
772 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
773 currentSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
774 currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
775
776 targetSelectedIndex_ = currentSelectedIndex_;
777 targetOverlongType_ = currentOverlongType_;
778 return;
779 }
780
781 if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1) {
782 currentSelectedIndex_ = maxDisplayCount_ - 1;
783 currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
784
785 targetSelectedIndex_ = currentSelectedIndex_;
786 targetOverlongType_ = currentOverlongType_;
787 return;
788 }
789 }
790
CalcTargetSelectedIndex(int32_t currentPageIndex,int32_t targetPageIndex)791 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndex(int32_t currentPageIndex, int32_t targetPageIndex)
792 {
793 if (currentPageIndex == targetPageIndex || keepStatus_) {
794 return;
795 }
796
797 if (currentPageIndex < targetPageIndex) {
798 CalcTargetSelectedIndexOnForward(currentPageIndex, targetPageIndex);
799 return;
800 }
801
802 CalcTargetSelectedIndexOnBackward(currentPageIndex, targetPageIndex);
803 }
804
CalcTargetOverlongStatus(int32_t currentPageIndex,int32_t targetPageIndex)805 void OverlengthDotIndicatorModifier::CalcTargetOverlongStatus(int32_t currentPageIndex, int32_t targetPageIndex)
806 {
807 if (currentPageIndex == targetPageIndex || currentOverlongType_ == OverlongType::NONE || keepStatus_) {
808 AdjustTargetStatus(targetPageIndex);
809 return;
810 }
811
812 if (currentPageIndex == realItemCount_ - 1 && targetPageIndex == 0) {
813 targetSelectedIndex_ = 0;
814 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
815 return;
816 }
817
818 if (currentPageIndex == 0 && targetPageIndex == realItemCount_ - 1) {
819 targetSelectedIndex_ = maxDisplayCount_ - 1;
820 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
821 return;
822 }
823
824 CalcTargetSelectedIndex(currentPageIndex, targetPageIndex);
825
826 if (currentPageIndex < targetPageIndex) {
827 if (currentOverlongType_ == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
828 if (targetSelectedIndex_ < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
829 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
830 } else if (targetSelectedIndex_ == maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
831 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
832 }
833 } else if (currentOverlongType_ == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
834 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
835 } else {
836 if (targetSelectedIndex_ < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
837 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
838 } else if (targetSelectedIndex_ == maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
839 if (targetPageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
840 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
841 } else {
842 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
843 }
844 } else {
845 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
846 }
847 }
848
849 return;
850 }
851
852 if (currentOverlongType_ == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
853 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
854 } else if (currentOverlongType_ == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
855 if (targetSelectedIndex_ > THIRD_POINT_INDEX) {
856 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
857 } else if (targetSelectedIndex_ == THIRD_POINT_INDEX) {
858 if (targetPageIndex > THIRD_POINT_INDEX) {
859 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
860 } else {
861 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
862 }
863 } else {
864 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
865 }
866 } else {
867 if (targetSelectedIndex_ > THIRD_POINT_INDEX) {
868 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
869 } else if (targetSelectedIndex_ == THIRD_POINT_INDEX) {
870 if (targetPageIndex > THIRD_POINT_INDEX) {
871 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
872 } else {
873 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
874 }
875 } else {
876 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
877 }
878 }
879 }
880
CalcRealPadding(float unselectedIndicatorRadius,float selectedIndicatorRadius,OverlongType overlongType) const881 float OverlengthDotIndicatorModifier::CalcRealPadding(
882 float unselectedIndicatorRadius, float selectedIndicatorRadius, OverlongType overlongType) const
883 {
884 auto padding = static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
885 if (!isBindIndicator_) {
886 return padding;
887 }
888
889 auto indicatorTheme = GetSwiperIndicatorTheme();
890 CHECK_NULL_RETURN(indicatorTheme, padding);
891 auto indicatorDotItemSpace = indicatorTheme->GetIndicatorDotItemSpace();
892 auto userItemWidth = unselectedIndicatorRadius * DOUBLE_INT;
893 auto userSelectedItemWidth = selectedIndicatorRadius * DOUBLE_INT;
894 auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (maxDisplayCount_ - 1);
895 auto allPointDiameterSum = userItemWidth * (maxDisplayCount_ - OVERLONG_SMALL_COUNT - 1) + userSelectedItemWidth +
896 userItemWidth * SECOND_SMALLEST_POINT_RATIO + userItemWidth * SMALLEST_POINT_RATIO;
897
898 auto paddingSide = indicatorTheme->GetIndicatorPaddingDot();
899 auto indicatorPaddingSide = static_cast<float>(paddingSide.ConvertToPx());
900 auto maxContentWidth = indicatorPaddingSide + allPointDiameterSum + allPointSpaceSum + indicatorPaddingSide;
901 if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT) {
902 allPointDiameterSum = userItemWidth * (maxDisplayCount_ - OVERLONG_SMALL_COUNT * DOUBLE_INT - 1) +
903 userSelectedItemWidth + userItemWidth * SECOND_SMALLEST_POINT_RATIO * DOUBLE_INT +
904 userItemWidth * SMALLEST_POINT_RATIO * DOUBLE_INT;
905 }
906
907 auto realContentWidth = indicatorPaddingSide + allPointDiameterSum + allPointSpaceSum + indicatorPaddingSide;
908 return padding + (maxContentWidth - realContentWidth) * HALF_FLOAT;
909 }
910
CalcIndicatorCenterX(const LinearVector<float> & itemHalfSizes,int32_t selectedIndex,OverlongType overlongType)911 std::pair<LinearVector<float>, std::pair<float, float>> OverlengthDotIndicatorModifier::CalcIndicatorCenterX(
912 const LinearVector<float>& itemHalfSizes, int32_t selectedIndex, OverlongType overlongType)
913 {
914 if (isHorizontalAndRTL_) {
915 selectedIndex = maxDisplayCount_ - 1 - selectedIndex;
916 overlongType = RevertOverlongType(overlongType);
917 }
918
919 auto unselectedIndicatorRadius = itemHalfSizes[ITEM_HALF_WIDTH];
920 auto selectedIndicatorRadius = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
921 if (!isCustomSizeValue_) {
922 selectedIndicatorRadius *= 2.0f;
923 }
924
925 LinearVector<float> indicatorCenterX(maxDisplayCount_ + 1);
926 std::pair<float, float> longPointCenterX;
927 float itemSpacePx = static_cast<float>(GetIndicatorDotItemSpace().ConvertToPx());
928 auto leftFirstRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
929 auto leftSecondRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
930 auto rightFirstRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
931 auto rightSecondRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
932
933 auto realPadding = CalcRealPadding(unselectedIndicatorRadius, selectedIndicatorRadius, overlongType);
934 auto startIndicatorCenterX = normalMargin_.GetX() + realPadding;
935 for (int32_t i = 0; i < maxDisplayCount_; i++) {
936 if (i == LEFT_FIRST_POINT_INDEX) {
937 if (i == selectedIndex) {
938 startIndicatorCenterX += selectedIndicatorRadius;
939 indicatorCenterX[i] = startIndicatorCenterX;
940 startIndicatorCenterX += selectedIndicatorRadius;
941
942 longPointCenterX.first =
943 indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
944 longPointCenterX.second =
945 indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
946 } else if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
947 startIndicatorCenterX += unselectedIndicatorRadius;
948 indicatorCenterX[i] = startIndicatorCenterX;
949 startIndicatorCenterX += unselectedIndicatorRadius;
950 } else {
951 startIndicatorCenterX += leftFirstRadius;
952 indicatorCenterX[i] = startIndicatorCenterX;
953 startIndicatorCenterX += leftFirstRadius;
954 }
955 continue;
956 }
957
958 if (i == SECOND_POINT_INDEX) {
959 if (i == selectedIndex) {
960 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
961 indicatorCenterX[i] = startIndicatorCenterX;
962 startIndicatorCenterX += selectedIndicatorRadius;
963
964 longPointCenterX.first =
965 indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
966 longPointCenterX.second =
967 indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
968 } else if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
969 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
970 indicatorCenterX[i] = startIndicatorCenterX;
971 startIndicatorCenterX += unselectedIndicatorRadius;
972 } else {
973 startIndicatorCenterX += itemSpacePx + leftSecondRadius;
974 indicatorCenterX[i] = startIndicatorCenterX;
975 startIndicatorCenterX += leftSecondRadius;
976 }
977 continue;
978 }
979
980 if (i >= THIRD_POINT_INDEX && i <= maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
981 if (i == selectedIndex) {
982 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
983 indicatorCenterX[i] = startIndicatorCenterX;
984 startIndicatorCenterX += selectedIndicatorRadius;
985
986 longPointCenterX.first =
987 indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
988 longPointCenterX.second =
989 indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
990 } else {
991 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
992 indicatorCenterX[i] = startIndicatorCenterX;
993 startIndicatorCenterX += unselectedIndicatorRadius;
994 }
995 continue;
996 }
997
998 if (i == maxDisplayCount_ - 1 - SECOND_POINT_INDEX) {
999 if (i == selectedIndex) {
1000 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
1001 indicatorCenterX[i] = startIndicatorCenterX;
1002 startIndicatorCenterX += selectedIndicatorRadius;
1003
1004 longPointCenterX.first =
1005 indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
1006 longPointCenterX.second =
1007 indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
1008 } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
1009 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
1010 indicatorCenterX[i] = startIndicatorCenterX;
1011 startIndicatorCenterX += unselectedIndicatorRadius;
1012 } else {
1013 startIndicatorCenterX += itemSpacePx + rightSecondRadius;
1014 indicatorCenterX[i] = startIndicatorCenterX;
1015 startIndicatorCenterX += rightSecondRadius;
1016 }
1017 continue;
1018 }
1019
1020 if (i == maxDisplayCount_ - 1) {
1021 if (i == selectedIndex) {
1022 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
1023 indicatorCenterX[i] = startIndicatorCenterX;
1024 startIndicatorCenterX += selectedIndicatorRadius;
1025
1026 longPointCenterX.first =
1027 indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
1028 longPointCenterX.second =
1029 indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
1030 } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
1031 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
1032 indicatorCenterX[i] = startIndicatorCenterX;
1033 startIndicatorCenterX += unselectedIndicatorRadius;
1034 } else {
1035 startIndicatorCenterX += itemSpacePx + rightFirstRadius;
1036 indicatorCenterX[i] = startIndicatorCenterX;
1037 startIndicatorCenterX += rightFirstRadius;
1038 }
1039 continue;
1040 }
1041 }
1042
1043 return std::make_pair(indicatorCenterX, longPointCenterX);
1044 }
1045
AdjustTargetStatus(int32_t targetPageIndex)1046 void OverlengthDotIndicatorModifier::AdjustTargetStatus(int32_t targetPageIndex)
1047 {
1048 targetSelectedIndex_ = SwiperIndicatorUtils::GetLoopIndex(targetSelectedIndex_, maxDisplayCount_);
1049 if (targetPageIndex == 0 || targetPageIndex == SECOND_POINT_INDEX || targetPageIndex == THIRD_POINT_INDEX) {
1050 targetSelectedIndex_ = targetPageIndex;
1051 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
1052 return;
1053 }
1054
1055 if (targetPageIndex == realItemCount_ - 1) {
1056 targetSelectedIndex_ = maxDisplayCount_ - 1;
1057 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
1058 return;
1059 }
1060
1061 if (targetPageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
1062 targetSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
1063 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
1064 return;
1065 }
1066
1067 if (targetPageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
1068 targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
1069 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
1070 return;
1071 }
1072
1073 if (targetPageIndex > THIRD_POINT_INDEX && targetSelectedIndex_ < THIRD_POINT_INDEX) {
1074 InitOverlongSelectedIndex(targetPageIndex);
1075 return;
1076 }
1077
1078 if (targetPageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX &&
1079 targetSelectedIndex_ > maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
1080 InitOverlongSelectedIndex(targetPageIndex);
1081 return;
1082 }
1083 }
1084
CalcTargetSelectedIndexOnForward(int32_t currentPageIndex,int32_t targetPageIndex)1085 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndexOnForward(int32_t currentPageIndex, int32_t targetPageIndex)
1086 {
1087 auto step = std::abs(targetPageIndex - currentPageIndex);
1088 auto rightThirdIndicatorIndex = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
1089 auto rightSecondPageIndex = realItemCount_ - 1 - SECOND_POINT_INDEX;
1090 if (currentSelectedIndex_ == rightThirdIndicatorIndex) {
1091 if (targetPageIndex < rightSecondPageIndex) {
1092 step = 0;
1093 } else {
1094 step = targetPageIndex - currentPageIndex;
1095 }
1096 } else if (currentSelectedIndex_ < rightThirdIndicatorIndex) {
1097 if (targetPageIndex < rightSecondPageIndex) {
1098 step = std::min(targetPageIndex - currentPageIndex, rightThirdIndicatorIndex - currentSelectedIndex_);
1099 } else if (targetPageIndex == rightSecondPageIndex) {
1100 step = rightThirdIndicatorIndex - currentSelectedIndex_ + 1;
1101 } else {
1102 step = rightThirdIndicatorIndex - currentSelectedIndex_ + THIRD_POINT_INDEX;
1103 }
1104 } else {
1105 step = targetPageIndex - currentPageIndex;
1106 }
1107
1108 targetSelectedIndex_ = currentSelectedIndex_ + step;
1109 AdjustTargetStatus(targetPageIndex);
1110 }
1111
CalcTargetSelectedIndexOnBackward(int32_t currentPageIndex,int32_t targetPageIndex)1112 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndexOnBackward(
1113 int32_t currentPageIndex, int32_t targetPageIndex)
1114 {
1115 auto step = std::abs(targetPageIndex - currentPageIndex);
1116 if (currentSelectedIndex_ > THIRD_POINT_INDEX) {
1117 if (targetPageIndex > SECOND_POINT_INDEX) {
1118 step = std::min(currentPageIndex - targetPageIndex, currentSelectedIndex_ - THIRD_POINT_INDEX);
1119 } else if (targetPageIndex == SECOND_POINT_INDEX) {
1120 step = currentSelectedIndex_ - SECOND_POINT_INDEX;
1121 } else {
1122 step = currentSelectedIndex_ - LEFT_FIRST_POINT_INDEX;
1123 }
1124 } else if (currentSelectedIndex_ == THIRD_POINT_INDEX) {
1125 if (targetPageIndex > SECOND_POINT_INDEX) {
1126 step = 0;
1127 } else if (targetPageIndex == SECOND_POINT_INDEX) {
1128 step = SECOND_POINT_INDEX;
1129 } else {
1130 step = THIRD_POINT_INDEX;
1131 }
1132 } else {
1133 step = currentPageIndex - targetPageIndex;
1134 }
1135
1136 targetSelectedIndex_ = currentSelectedIndex_ - step;
1137 AdjustTargetStatus(targetPageIndex);
1138 }
1139
1140 } // namespace OHOS::Ace::NG
1141