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 Sets the maximum scroll distance after a finger lifts the screen. 100 * 101 * @param distance Indicates the maximum scroll distance to set. The default value is <b>0</b>, indicating that the 102 * scroll distance is not limited. 103 * @since 1.0 104 * @version 1.0 105 */ SetMaxScrollDistance(uint16_t distance)106 void SetMaxScrollDistance(uint16_t distance) 107 { 108 maxScrollDistance_ = distance; 109 } 110 111 /** 112 * @brief Sets the rebound size, which is the distance a knob moves after being released when it reaches the end of 113 * a scrollbar. 114 * 115 * @param size Indicates the rebound size to set. 116 * @since 1.0 117 * @version 1.0 118 */ SetReboundSize(uint16_t size)119 void SetReboundSize(uint16_t size) 120 { 121 reboundSize_ = size; 122 } 123 124 /** 125 * @brief Obtains the maximum scroll distance after a finger lifts the screen. 126 * 127 * @return Returns the maximum scroll distance. The default value is <b>0</b>, indicating that the scroll distance 128 * is not limited. 129 * @since 1.0 130 * @version 1.0 131 */ GetMaxScrollDistance()132 uint16_t GetMaxScrollDistance() const 133 { 134 return maxScrollDistance_; 135 } 136 137 /** 138 * @brief Sets the easing function that specifies a scroll animation after a finger lifts the screen. 139 * 140 * @param func Indicates the easing function to set. The default function is {@link EasingEquation::CubicEaseOut}. 141 * For details, see {@link EasingEquation}. 142 * @since 1.0 143 * @version 1.0 144 */ SetDragFunc(EasingFunc func)145 void SetDragFunc(EasingFunc func) 146 { 147 easingFunc_ = func; 148 } 149 150 /** 151 * @brief Sets whether to continue scrolling after a finger lifts the screen. 152 * 153 * @param throwDrag Specifies whether to continue scrolling after a finger lifts the screen. <b>true</b> indicates 154 * the scroll continues, and <b>false</b> indicates the scroll stops immediately after a finger 155 * lifts. 156 * @since 1.0 157 * @version 1.0 158 */ SetThrowDrag(bool throwDrag)159 void SetThrowDrag(bool throwDrag) 160 { 161 throwDrag_ = throwDrag; 162 } 163 164 /** 165 * @brief Moves the position of all child views. 166 * 167 * @param offsetX Indicates the offset distance by which a child view is moved on the x-axis. 168 * @param offsetY Indicates the offset distance by which a child view is moved on the y-axis. 169 * @since 1.0 170 * @version 1.0 171 */ 172 void MoveChildByOffset(int16_t offsetX, int16_t offsetY) override; 173 174 /** 175 * @brief Sets the drag acceleration. 176 * 177 * @param value Indicates the drag acceleration to set. The default value is <b>10</b>. A larger drag acceleration 178 * indicates a higher inertial scroll velocity. 179 * @since 1.0 180 * @version 1.0 181 */ SetDragACCLevel(uint16_t value)182 void SetDragACCLevel(uint16_t value) 183 { 184 if (value != 0) { 185 dragAccCoefficient_ = value; 186 } 187 } 188 189 /** 190 * @brief Obtains the drag acceleration. 191 * 192 * @return Returns the drag acceleration. 193 * @since 1.0 194 * @version 1.0 195 */ GetDragACCLevel()196 uint8_t GetDragACCLevel() const 197 { 198 return dragAccCoefficient_; 199 } 200 201 /** 202 * @brief Sets the compensation distance after a finger lifts the screen. 203 * 204 * @param value Indicates the compensation distance to set. The default value is <b>0</b>. 205 * @since 1.0 206 * @version 1.0 207 */ SetSwipeACCLevel(uint16_t value)208 void SetSwipeACCLevel(uint16_t value) 209 { 210 swipeAccCoefficient_ = value; 211 } 212 213 /** 214 * @brief Obtains the compensation distance after a finger lifts the screen. 215 * 216 * @return Returns the compensation distance. 217 * @since 1.0 218 * @version 1.0 219 */ GetSwipeACCLevel()220 uint8_t GetSwipeACCLevel() const 221 { 222 return swipeAccCoefficient_; 223 } 224 225 #if ENABLE_ROTATE_INPUT 226 /** 227 * @brief Sets coefficient for rotation dragthrow animation. The view will roll farther with larger coeffcient. 228 * 229 * @param value Indicates the coefficient to set. The default value is <b>0</b>. 230 * @since 1.0 231 * @version 1.0 232 */ SetRotateACCLevel(uint8_t value)233 void SetRotateACCLevel(uint8_t value) 234 { 235 rotateAccCoefficient_ = value; 236 } 237 238 /** 239 * @brief Obtains the coefficient for rotation drag throw animation. 240 * 241 * @return Returns the coefficient for rotation drag throw animation. 242 * @since 1.0 243 * @version 1.0 244 */ GetRotateACCLevel()245 uint8_t GetRotateACCLevel() const 246 { 247 return rotateAccCoefficient_; 248 } 249 250 /** 251 * @brief Obtains the rotation factor. 252 * 253 * @return Returns the rotation factor. 254 * @since 5.0 255 * @version 3.0 256 */ GetRotateFactor()257 float GetRotateFactor() const 258 { 259 return rotateFactor_; 260 } 261 262 /** 263 * @brief Sets the rotation factor. 264 * 265 * @param factor Indicates the rotation factor to set. 266 * @since 5.0 267 * @version 3.0 268 */ SetRotateFactor(float factor)269 void SetRotateFactor(float factor) 270 { 271 if (MATH_ABS(factor) > MAX_ROTATE_FACTOR) { 272 rotateFactor_ = (factor > 0) ? MAX_ROTATE_FACTOR : -MAX_ROTATE_FACTOR; 273 return; 274 } 275 rotateFactor_ = factor; 276 } 277 278 /** 279 * @brief Sets threshold for rotation drag throw animation. The view will roll easier with larger threshold. 280 * 281 * @param threshold Indicates the rotation factor to set. 282 * 283 * @since 6 284 */ SetRotateThrowThreshold(uint8_t threshold)285 void SetRotateThrowThreshold(uint8_t threshold) 286 { 287 if (threshold == 0) { 288 return; 289 } 290 rotateThrowthreshold_ = threshold; 291 } 292 293 bool OnRotateStartEvent(const RotateEvent& event) override; 294 295 bool OnRotateEvent(const RotateEvent& event) override; 296 297 bool OnRotateEndEvent(const RotateEvent& event) override; 298 #endif 299 300 void SetXScrollBarVisible(bool visible); 301 302 void SetYScrollBarVisible(bool visible); 303 SetScrollBarSide(uint8_t side)304 void SetScrollBarSide(uint8_t side) 305 { 306 scrollBarSide_ = side; 307 } 308 SetScrollBarCenter(const Point & center)309 void SetScrollBarCenter(const Point& center) 310 { 311 scrollBarCenter_ = center; 312 scrollBarCenterSetFlag_ = true; 313 } 314 315 /** 316 * @brief Sets the list direction. 317 * 318 * @param direction Indicates the list direction, either {@link HORIZONTAL} or {@link VERTICAL}. 319 * @since 1.0 320 * @version 1.0 321 */ SetDirection(uint8_t direction)322 void SetDirection(uint8_t direction) 323 { 324 direction_ = direction; 325 } 326 327 /** 328 * @brief Obtains the list direction. 329 * @return Returns the list direction, either {@link HORIZONTAL} or {@link VERTICAL}. 330 * @since 1.0 331 * @version 1.0 332 */ GetDirection()333 uint8_t GetDirection() const 334 { 335 return direction_; 336 } 337 338 void OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) override; 339 340 static constexpr uint8_t HORIZONTAL = 0; 341 static constexpr uint8_t VERTICAL = 1; 342 343 protected: 344 static constexpr uint8_t HORIZONTAL_AND_VERTICAL = 2; 345 static constexpr uint8_t HORIZONTAL_NOR_VERTICAL = 3; 346 /* calculate drag throw distance, last drag distance in one tick * DRAG_DISTANCE_COEFFICIENT */ 347 static constexpr uint8_t DRAG_DISTANCE_COEFFICIENT = 5; 348 /* calculate drag throw times, drag distance / DRAG_TIMES_COEFFICIENT */ 349 static constexpr uint8_t DRAG_TIMES_COEFFICIENT = 18; 350 /* the minimum duration of the swipe animator */ 351 static constexpr uint8_t MIN_DRAG_TIMES = 5; 352 /* acceleration calculation coefficient */ 353 static constexpr uint8_t DRAG_ACC_FACTOR = 10; 354 /* the maximum number of historical drag data */ 355 static constexpr uint8_t MAX_DELTA_SIZE = 3; 356 357 static constexpr uint16_t SCROLL_BAR_WIDTH = 4; 358 static constexpr uint8_t MAX_ROTATE_FACTOR = 128; 359 360 class ListAnimatorCallback : public AnimatorCallback { 361 public: ListAnimatorCallback()362 ListAnimatorCallback() 363 : curtTime_(0), 364 dragTimes_(0), 365 startValueX_(0), 366 endValueX_(0), 367 previousValueX_(0), 368 startValueY_(0), 369 endValueY_(0), 370 previousValueY_(0) 371 { 372 } 373 ~ListAnimatorCallback()374 virtual ~ListAnimatorCallback() {} 375 SetDragTimes(uint16_t times)376 void SetDragTimes(uint16_t times) 377 { 378 dragTimes_ = times; 379 } 380 SetDragStartValue(int16_t startValueX,int16_t startValueY)381 void SetDragStartValue(int16_t startValueX, int16_t startValueY) 382 { 383 startValueX_ = startValueX; 384 previousValueX_ = startValueX; 385 startValueY_ = startValueY; 386 previousValueY_ = startValueY; 387 } 388 SetDragEndValue(int16_t endValueX,int16_t endValueY)389 void SetDragEndValue(int16_t endValueX, int16_t endValueY) 390 { 391 endValueX_ = endValueX; 392 endValueY_ = endValueY; 393 } 394 ResetCallback()395 void ResetCallback() 396 { 397 curtTime_ = 0; 398 dragTimes_ = 0; 399 startValueX_ = 0; 400 endValueX_ = 0; 401 startValueY_ = 0; 402 endValueY_ = 0; 403 } 404 405 virtual void Callback(UIView* view) override; 406 407 uint16_t curtTime_; 408 uint16_t dragTimes_; 409 int16_t startValueX_; 410 int16_t endValueX_; 411 int16_t previousValueX_; 412 int16_t startValueY_; 413 int16_t endValueY_; 414 int16_t previousValueY_; 415 }; 416 417 bool DragThrowAnimator(Point currentPos, Point lastPos, uint8_t dragDirection, bool dragBack = true); 418 419 virtual void StopAnimator(); 420 421 virtual bool DragXInner(int16_t distance) = 0; 422 423 virtual bool DragYInner(int16_t distance) = 0; 424 RefreshDelta(int16_t distance)425 void RefreshDelta(int16_t distance) 426 { 427 lastDelta_[deltaIndex_ % MAX_DELTA_SIZE] = distance; 428 deltaIndex_++; 429 } 430 431 void InitDelta(); 432 RefreshRotate(int16_t distance)433 void RefreshRotate(int16_t distance) 434 { 435 lastRotate_[rotateIndex_ % MAX_DELTA_SIZE] = distance; 436 rotateIndex_++; 437 } 438 439 void InitRotate(); 440 441 virtual void CalculateDragDistance(Point currentPos, 442 Point lastPos, 443 uint8_t dragDirection, 444 int16_t& dragDistanceX, 445 int16_t& dragDistanceY); 446 447 void StartAnimator(int16_t dragDistanceX, int16_t dragDistanceY); 448 CalculateReboundDistance(int16_t & dragDistanceX,int16_t & dragDistanceY)449 virtual void CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY){}; 450 451 int16_t GetMaxDelta() const; 452 453 int16_t GetMaxRotate() const; 454 455 void RefreshAnimator(); 456 FixDistance(int16_t & distanceX,int16_t & distanceY)457 virtual void FixDistance(int16_t& distanceX, int16_t& distanceY) {} 458 459 uint16_t scrollBlankSize_ = 0; 460 uint16_t reboundSize_ = 0; 461 uint16_t maxScrollDistance_ = 0; 462 int16_t lastDelta_[MAX_DELTA_SIZE] = {0}; 463 int16_t lastRotate_[MAX_DELTA_SIZE] = {0}; 464 uint8_t dragAccCoefficient_ = DRAG_ACC_FACTOR; 465 uint8_t swipeAccCoefficient_ = 0; 466 uint8_t direction_ : 2; 467 uint8_t deltaIndex_ : 2; 468 uint8_t rotateIndex_ : 2; 469 uint8_t reserve_ : 2; 470 bool throwDrag_ = false; 471 EasingFunc easingFunc_; 472 ListAnimatorCallback animatorCallback_; 473 Animator scrollAnimator_; 474 #if ENABLE_ROTATE_INPUT 475 uint8_t rotateAccCoefficient_ = 0; 476 float rotateFactor_; 477 uint8_t rotateThrowthreshold_; 478 bool isRotating_; 479 #endif 480 bool yScrollBarVisible_ = false; 481 UIAbstractScrollBar* yScrollBar_ = nullptr; 482 bool xScrollBarVisible_ = false; 483 UIAbstractScrollBar* xScrollBar_ = nullptr; 484 uint8_t scrollBarSide_; 485 Point scrollBarCenter_; 486 bool scrollBarCenterSetFlag_; 487 bool dragBack_ = true; 488 #if DEFAULT_ANIMATION 489 friend class BarEaseInOutAnimator; 490 BarEaseInOutAnimator* barEaseInOutAnimator_ = nullptr; 491 #endif 492 }; 493 } // namespace OHOS 494 #endif // GRAPHIC_LITE_UI_ABSTRACT_SCROLL_H 495