1 /* 2 * Copyright (c) 2020-2021 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 /** 17 * @addtogroup UI_Components 18 * @{ 19 * 20 * @brief Defines UI components such as buttons, texts, images, lists, and progress bars. 21 * 22 * @since 1.0 23 * @version 1.0 24 */ 25 26 /** 27 * @file ui_abstract_scroll.h 28 * 29 * @brief Declares the base class used to define the attributes of a scroll. The <b>UIList</b>, <b>UIScrollView</b>, and 30 * <b>UISwipeView</b> inherit from this class. 31 * 32 * @since 1.0 33 * @version 1.0 34 */ 35 36 #ifndef GRAPHIC_LITE_UI_ABSTRACT_SCROLL_H 37 #define GRAPHIC_LITE_UI_ABSTRACT_SCROLL_H 38 39 #include "animator/animator.h" 40 #include "animator/easing_equation.h" 41 #include "components/ui_view_group.h" 42 43 namespace OHOS { 44 class BarEaseInOutAnimator; 45 class UIAbstractScrollBar; 46 /** 47 * @brief Defines the attributes of a scroll, including the scroll direction, blank size of a scroll view, velocity and 48 * effects of a scroll animation. 49 * 50 * @since 1.0 51 * @version 1.0 52 */ 53 class UIAbstractScroll : public UIViewGroup { 54 public: 55 /** 56 * @brief A constructor used to create a <b>UIAbstractScroll</b> instance. 57 * 58 * @since 1.0 59 * @version 1.0 60 */ 61 UIAbstractScroll(); 62 63 /** 64 * @brief A destructor used to delete the <b>UIAbstractScroll</b> instance. 65 * 66 * @since 1.0 67 * @version 1.0 68 */ 69 virtual ~UIAbstractScroll(); 70 71 /** 72 * @brief Obtains the view type. 73 * @return Returns the view type, as defined in {@link UIViewType}. 74 * @since 1.0 75 * @version 1.0 76 */ GetViewType()77 UIViewType GetViewType() const override 78 { 79 return UI_ABSTRACT_SCROLL; 80 } 81 82 /** 83 * @brief Sets the blank size for this scroll view. 84 * 85 * 86 * @param value Indicates the blank size to set. The default value is <b>0</b>. Taking a vertical scroll as an 87 * example, the value <b>0</b> indicates that the head node can only scroll downwards the top of the 88 * view and the tail node scroll upwards the bottom; the value <b>10</b> indicates that the head node 89 * can continue scrolling down by 10 pixels after it reaches the top of the view. 90 * @since 1.0 91 * @version 1.0 92 */ SetScrollBlankSize(uint16_t size)93 void SetScrollBlankSize(uint16_t size) 94 { 95 scrollBlankSize_ = size; 96 } 97 98 /** 99 * @brief Get the blank size for this scroll view. 100 * 101 * @return Returns the blank size for this scroll view 102 */ GetScrollBlankSize()103 uint16_t GetScrollBlankSize() const 104 { 105 return scrollBlankSize_; 106 } 107 108 /** 109 * @brief Sets the maximum scroll distance after a finger lifts the screen. 110 * 111 * @param distance Indicates the maximum scroll distance to set. The default value is <b>0</b>, indicating that the 112 * scroll distance is not limited. 113 * @since 1.0 114 * @version 1.0 115 */ SetMaxScrollDistance(uint16_t distance)116 void SetMaxScrollDistance(uint16_t distance) 117 { 118 maxScrollDistance_ = distance; 119 } 120 121 /** 122 * @brief Sets the rebound size, which is the distance a knob moves after being released when it reaches the end of 123 * a scrollbar. 124 * 125 * @param size Indicates the rebound size to set. 126 * @since 1.0 127 * @version 1.0 128 */ SetReboundSize(uint16_t size)129 void SetReboundSize(uint16_t size) 130 { 131 reboundSize_ = size; 132 } 133 134 /** 135 * @brief Get the rebound size, which is the distance a knob moves after being released when it reaches the end of 136 * a scrollbar. 137 * 138 * @return Returns the rebound size. 139 */ GetReboundSize()140 uint16_t GetReboundSize() const 141 { 142 return reboundSize_; 143 } 144 145 /** 146 * @brief Obtains the maximum scroll distance after a finger lifts the screen. 147 * 148 * @return Returns the maximum scroll distance. The default value is <b>0</b>, indicating that the scroll distance 149 * is not limited. 150 * @since 1.0 151 * @version 1.0 152 */ GetMaxScrollDistance()153 uint16_t GetMaxScrollDistance() const 154 { 155 return maxScrollDistance_; 156 } 157 158 /** 159 * @brief Sets the easing function that specifies a scroll animation after a finger lifts the screen. 160 * 161 * @param func Indicates the easing function to set. The default function is {@link EasingEquation::CubicEaseOut}. 162 * For details, see {@link EasingEquation}. 163 * @since 1.0 164 * @version 1.0 165 */ SetDragFunc(EasingFunc func)166 void SetDragFunc(EasingFunc func) 167 { 168 easingFunc_ = func; 169 } 170 171 /** 172 * @brief Get the easing function that specifies a scroll animation after a finger lifts the screen. 173 * 174 * @param func Returns the easing function to set. The default function is {@link EasingEquation::CubicEaseOut}. 175 * For details, see {@link EasingEquation}. 176 */ GetDragFunc()177 EasingFunc GetDragFunc() const 178 { 179 return easingFunc_; 180 } 181 182 /** 183 * @brief Sets whether to continue scrolling after a finger lifts the screen. 184 * 185 * @param throwDrag Specifies whether to continue scrolling after a finger lifts the screen. <b>true</b> indicates 186 * the scroll continues, and <b>false</b> indicates the scroll stops immediately after a finger 187 * lifts. 188 * @since 1.0 189 * @version 1.0 190 */ SetThrowDrag(bool throwDrag)191 void SetThrowDrag(bool throwDrag) 192 { 193 throwDrag_ = throwDrag; 194 } 195 196 /** 197 * @brief Moves the position of all child views. 198 * 199 * @param offsetX Indicates the offset distance by which a child view is moved on the x-axis. 200 * @param offsetY Indicates the offset distance by which a child view is moved on the y-axis. 201 * @since 1.0 202 * @version 1.0 203 */ 204 void MoveChildByOffset(int16_t offsetX, int16_t offsetY) override; 205 206 /** 207 * @brief Sets the drag acceleration. 208 * 209 * @param value Indicates the drag acceleration to set. The default value is <b>10</b>. A larger drag acceleration 210 * indicates a higher inertial scroll velocity. 211 * @since 1.0 212 * @version 1.0 213 */ SetDragACCLevel(uint16_t value)214 void SetDragACCLevel(uint16_t value) 215 { 216 if (value != 0) { 217 dragAccCoefficient_ = value; 218 } 219 } 220 221 /** 222 * @brief Obtains the drag acceleration. 223 * 224 * @return Returns the drag acceleration. 225 * @since 1.0 226 * @version 1.0 227 */ GetDragACCLevel()228 uint8_t GetDragACCLevel() const 229 { 230 return dragAccCoefficient_; 231 } 232 233 /** 234 * @brief Sets the compensation distance after a finger lifts the screen. 235 * 236 * @param value Indicates the compensation distance to set. The default value is <b>0</b>. 237 * @since 1.0 238 * @version 1.0 239 */ SetSwipeACCLevel(uint16_t value)240 void SetSwipeACCLevel(uint16_t value) 241 { 242 swipeAccCoefficient_ = value; 243 } 244 245 /** 246 * @brief Obtains the compensation distance after a finger lifts the screen. 247 * 248 * @return Returns the compensation distance. 249 * @since 1.0 250 * @version 1.0 251 */ GetSwipeACCLevel()252 uint8_t GetSwipeACCLevel() const 253 { 254 return swipeAccCoefficient_; 255 } 256 257 #if ENABLE_ROTATE_INPUT 258 /** 259 * @brief Sets coefficient for rotation dragthrow animation. The view will roll farther with larger coeffcient. 260 * 261 * @param value Indicates the coefficient to set. The default value is <b>0</b>. 262 * @since 1.0 263 * @version 1.0 264 */ SetRotateACCLevel(uint8_t value)265 void SetRotateACCLevel(uint8_t value) 266 { 267 rotateAccCoefficient_ = value; 268 } 269 270 /** 271 * @brief Obtains the coefficient for rotation drag throw animation. 272 * 273 * @return Returns the coefficient for rotation drag throw animation. 274 * @since 1.0 275 * @version 1.0 276 */ GetRotateACCLevel()277 uint8_t GetRotateACCLevel() const 278 { 279 return rotateAccCoefficient_; 280 } 281 282 /** 283 * @brief Obtains the rotation factor. 284 * 285 * @return Returns the rotation factor. 286 * @since 5.0 287 * @version 3.0 288 */ GetRotateFactor()289 float GetRotateFactor() const 290 { 291 return rotateFactor_; 292 } 293 294 /** 295 * @brief Sets the rotation factor. 296 * 297 * @param factor Indicates the rotation factor to set. 298 * @since 5.0 299 * @version 3.0 300 */ SetRotateFactor(float factor)301 void SetRotateFactor(float factor) 302 { 303 if (MATH_ABS(factor) > MAX_ROTATE_FACTOR) { 304 rotateFactor_ = (factor > 0) ? MAX_ROTATE_FACTOR : -MAX_ROTATE_FACTOR; 305 return; 306 } 307 rotateFactor_ = factor; 308 } 309 310 /** 311 * @brief Sets threshold for rotation drag throw animation. The view will roll easier with larger threshold. 312 * 313 * @param threshold Indicates the rotation factor to set. 314 * 315 * @since 6 316 */ SetRotateThrowThreshold(uint8_t threshold)317 void SetRotateThrowThreshold(uint8_t threshold) 318 { 319 if (threshold == 0) { 320 return; 321 } 322 rotateThrowthreshold_ = threshold; 323 } 324 325 /** 326 * @brief Get threshold for rotation drag throw animation. The view will roll easier with larger threshold. 327 * 328 * @param Returns the threshold for rotation drag throw animation. The view will roll easier with larger threshold. 329 * 330 */ GetRotateThrowThreshold()331 uint8_t GetRotateThrowThreshold() const 332 { 333 return rotateThrowthreshold_; 334 } 335 336 bool OnRotateStartEvent(const RotateEvent& event) override; 337 338 bool OnRotateEvent(const RotateEvent& event) override; 339 340 bool OnRotateEndEvent(const RotateEvent& event) override; 341 #endif 342 343 void SetXScrollBarVisible(bool visible); 344 345 void SetYScrollBarVisible(bool visible); 346 SetScrollBarSide(uint8_t side)347 void SetScrollBarSide(uint8_t side) 348 { 349 scrollBarSide_ = side; 350 } 351 352 /** 353 * @brief Get ScrollBarSide. 354 * 355 * @param Returns the scrollBarSide_. 356 * 357 */ GetScrollBarSide()358 uint8_t GetScrollBarSide() 359 { 360 return scrollBarSide_; 361 } 362 SetScrollBarCenter(const Point & center)363 void SetScrollBarCenter(const Point& center) 364 { 365 scrollBarCenter_ = center; 366 scrollBarCenterSetFlag_ = true; 367 } 368 369 /** 370 * @brief Get scrollBarCenter. 371 * 372 * @param Returns the scrollBarCenter_. 373 * 374 */ GetScrollBarCenter()375 Point GetScrollBarCenter() 376 { 377 return scrollBarCenter_; 378 } 379 380 /** 381 * @brief Sets the list direction. 382 * 383 * @param direction Indicates the list direction, either {@link HORIZONTAL} or {@link VERTICAL}. 384 * @since 1.0 385 * @version 1.0 386 */ SetDirection(uint8_t direction)387 void SetDirection(uint8_t direction) 388 { 389 direction_ = direction; 390 } 391 392 /** 393 * @brief Obtains the list direction. 394 * @return Returns the list direction, either {@link HORIZONTAL} or {@link VERTICAL}. 395 * @since 1.0 396 * @version 1.0 397 */ GetDirection()398 uint8_t GetDirection() const 399 { 400 return direction_; 401 } 402 403 void OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) override; 404 405 static constexpr uint8_t HORIZONTAL = 0; 406 static constexpr uint8_t VERTICAL = 1; 407 408 protected: 409 static constexpr uint8_t HORIZONTAL_AND_VERTICAL = 2; 410 static constexpr uint8_t HORIZONTAL_NOR_VERTICAL = 3; 411 /* calculate drag throw distance, last drag distance in one tick * DRAG_DISTANCE_COEFFICIENT */ 412 static constexpr uint8_t DRAG_DISTANCE_COEFFICIENT = 5; 413 /* calculate drag throw times, drag distance / DRAG_TIMES_COEFFICIENT */ 414 static constexpr uint8_t DRAG_TIMES_COEFFICIENT = 18; 415 /* the minimum duration of the swipe animator */ 416 static constexpr uint8_t MIN_DRAG_TIMES = 5; 417 /* acceleration calculation coefficient */ 418 static constexpr uint8_t DRAG_ACC_FACTOR = 10; 419 /* the maximum number of historical drag data */ 420 static constexpr uint8_t MAX_DELTA_SIZE = 3; 421 422 static constexpr uint16_t SCROLL_BAR_WIDTH = 4; 423 static constexpr uint8_t MAX_ROTATE_FACTOR = 128; 424 425 class ListAnimatorCallback : public AnimatorCallback { 426 public: ListAnimatorCallback()427 ListAnimatorCallback() 428 : curtTime_(0), 429 dragTimes_(0), 430 startValueX_(0), 431 endValueX_(0), 432 previousValueX_(0), 433 startValueY_(0), 434 endValueY_(0), 435 previousValueY_(0) 436 { 437 } 438 ~ListAnimatorCallback()439 virtual ~ListAnimatorCallback() {} 440 SetDragTimes(uint16_t times)441 void SetDragTimes(uint16_t times) 442 { 443 dragTimes_ = times; 444 } 445 SetDragStartValue(int16_t startValueX,int16_t startValueY)446 void SetDragStartValue(int16_t startValueX, int16_t startValueY) 447 { 448 startValueX_ = startValueX; 449 previousValueX_ = startValueX; 450 startValueY_ = startValueY; 451 previousValueY_ = startValueY; 452 } 453 SetDragEndValue(int16_t endValueX,int16_t endValueY)454 void SetDragEndValue(int16_t endValueX, int16_t endValueY) 455 { 456 endValueX_ = endValueX; 457 endValueY_ = endValueY; 458 } 459 ResetCallback()460 void ResetCallback() 461 { 462 curtTime_ = 0; 463 dragTimes_ = 0; 464 startValueX_ = 0; 465 endValueX_ = 0; 466 startValueY_ = 0; 467 endValueY_ = 0; 468 } 469 470 void Callback(UIView* view) override; 471 472 uint16_t curtTime_; 473 uint16_t dragTimes_; 474 int16_t startValueX_; 475 int16_t endValueX_; 476 int16_t previousValueX_; 477 int16_t startValueY_; 478 int16_t endValueY_; 479 int16_t previousValueY_; 480 }; 481 482 bool DragThrowAnimator(Point currentPos, Point lastPos, uint8_t dragDirection, bool dragBack = true); 483 484 virtual void StopAnimator(); 485 486 virtual bool DragXInner(int16_t distance) = 0; 487 488 virtual bool DragYInner(int16_t distance) = 0; 489 RefreshDelta(int16_t distance)490 void RefreshDelta(int16_t distance) 491 { 492 lastDelta_[deltaIndex_ % MAX_DELTA_SIZE] = distance; 493 deltaIndex_++; 494 } 495 496 void InitDelta(); 497 RefreshRotate(int16_t distance)498 void RefreshRotate(int16_t distance) 499 { 500 lastRotate_[rotateIndex_ % MAX_DELTA_SIZE] = distance; 501 rotateIndex_++; 502 } 503 504 void InitRotate(); 505 506 virtual void CalculateDragDistance(Point currentPos, 507 Point lastPos, 508 uint8_t dragDirection, 509 int16_t& dragDistanceX, 510 int16_t& dragDistanceY); 511 512 void StartAnimator(int16_t dragDistanceX, int16_t dragDistanceY); 513 CalculateReboundDistance(int16_t & dragDistanceX,int16_t & dragDistanceY)514 virtual void CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY) {} 515 516 int16_t GetMaxDelta() const; 517 518 int16_t GetMaxRotate() const; 519 520 void RefreshAnimator(); 521 FixDistance(int16_t & distanceX,int16_t & distanceY)522 virtual void FixDistance(int16_t& distanceX, int16_t& distanceY) {} 523 524 uint16_t scrollBlankSize_ = 0; 525 uint16_t reboundSize_ = 0; 526 uint16_t maxScrollDistance_ = 0; 527 int16_t lastDelta_[MAX_DELTA_SIZE] = {0}; 528 int16_t lastRotate_[MAX_DELTA_SIZE] = {0}; 529 uint8_t dragAccCoefficient_ = DRAG_ACC_FACTOR; 530 uint8_t swipeAccCoefficient_ = 0; 531 uint8_t direction_ : 2; 532 uint8_t deltaIndex_ : 2; 533 uint8_t rotateIndex_ : 2; 534 uint8_t reserve_ : 2; 535 bool throwDrag_ = false; 536 EasingFunc easingFunc_; 537 ListAnimatorCallback animatorCallback_; 538 Animator scrollAnimator_; 539 #if ENABLE_ROTATE_INPUT 540 uint8_t rotateAccCoefficient_ = 0; 541 float rotateFactor_; 542 uint8_t rotateThrowthreshold_; 543 bool isRotating_; 544 #endif 545 bool yScrollBarVisible_ = false; 546 UIAbstractScrollBar* yScrollBar_ = nullptr; 547 bool xScrollBarVisible_ = false; 548 UIAbstractScrollBar* xScrollBar_ = nullptr; 549 uint8_t scrollBarSide_; 550 Point scrollBarCenter_; 551 bool scrollBarCenterSetFlag_; 552 bool dragBack_ = true; 553 #if DEFAULT_ANIMATION 554 friend class BarEaseInOutAnimator; 555 BarEaseInOutAnimator* barEaseInOutAnimator_ = nullptr; 556 #endif 557 }; 558 } // namespace OHOS 559 #endif // GRAPHIC_LITE_UI_ABSTRACT_SCROLL_H 560