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