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