1a3e0fd82Sopenharmony_ci/* 2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License. 5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at 6a3e0fd82Sopenharmony_ci * 7a3e0fd82Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8a3e0fd82Sopenharmony_ci * 9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and 13a3e0fd82Sopenharmony_ci * limitations under the License. 14a3e0fd82Sopenharmony_ci */ 15a3e0fd82Sopenharmony_ci 16a3e0fd82Sopenharmony_ci#include "components/ui_abstract_scroll.h" 17a3e0fd82Sopenharmony_ci 18a3e0fd82Sopenharmony_ci#include "securec.h" 19a3e0fd82Sopenharmony_ci 20a3e0fd82Sopenharmony_ci#include "animator/interpolation.h" 21a3e0fd82Sopenharmony_ci#include "common/screen.h" 22a3e0fd82Sopenharmony_ci#include "components/ui_abstract_scroll_bar.h" 23a3e0fd82Sopenharmony_ci#include "components/ui_arc_scroll_bar.h" 24a3e0fd82Sopenharmony_ci#include "components/ui_box_scroll_bar.h" 25a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 26a3e0fd82Sopenharmony_ci#include "graphic_timer.h" 27a3e0fd82Sopenharmony_ci#endif 28a3e0fd82Sopenharmony_ci 29a3e0fd82Sopenharmony_cinamespace OHOS { 30a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 31a3e0fd82Sopenharmony_ciclass BarEaseInOutAnimator final : public AnimatorCallback { 32a3e0fd82Sopenharmony_cipublic: 33a3e0fd82Sopenharmony_ci BarEaseInOutAnimator() = delete; 34a3e0fd82Sopenharmony_ci BarEaseInOutAnimator(const BarEaseInOutAnimator&) = delete; 35a3e0fd82Sopenharmony_ci BarEaseInOutAnimator& operator=(const BarEaseInOutAnimator&) = delete; 36a3e0fd82Sopenharmony_ci BarEaseInOutAnimator(BarEaseInOutAnimator&&) = delete; 37a3e0fd82Sopenharmony_ci BarEaseInOutAnimator& operator=(BarEaseInOutAnimator&&) = delete; 38a3e0fd82Sopenharmony_ci 39a3e0fd82Sopenharmony_ci explicit BarEaseInOutAnimator(UIAbstractScroll& scrollView) 40a3e0fd82Sopenharmony_ci : scrollView_(scrollView), 41a3e0fd82Sopenharmony_ci timer_(APPEAR_PERIOD, TimerCb, this), 42a3e0fd82Sopenharmony_ci animator_(this, nullptr, ANIMATOR_DURATION, false) 43a3e0fd82Sopenharmony_ci { 44a3e0fd82Sopenharmony_ci } 45a3e0fd82Sopenharmony_ci 46a3e0fd82Sopenharmony_ci ~BarEaseInOutAnimator() 47a3e0fd82Sopenharmony_ci { 48a3e0fd82Sopenharmony_ci timer_.Stop(); 49a3e0fd82Sopenharmony_ci animator_.Stop(); 50a3e0fd82Sopenharmony_ci } 51a3e0fd82Sopenharmony_ci 52a3e0fd82Sopenharmony_ci void RefreshBar() 53a3e0fd82Sopenharmony_ci { 54a3e0fd82Sopenharmony_ci if (animator_.GetState() == Animator::START) { 55a3e0fd82Sopenharmony_ci if (!isEaseIn_) { 56a3e0fd82Sopenharmony_ci animator_.SetRunTime(ANIMATOR_DURATION - animator_.GetRunTime()); 57a3e0fd82Sopenharmony_ci } 58a3e0fd82Sopenharmony_ci } else if (scrollView_.yScrollBar_->GetOpacity() == OPA_TRANSPARENT) { 59a3e0fd82Sopenharmony_ci animator_.Start(); 60a3e0fd82Sopenharmony_ci } else { 61a3e0fd82Sopenharmony_ci timer_.Start(); // updates the start time of timer, ensuring that timer is triggered two seconds after the 62a3e0fd82Sopenharmony_ci // last operation 63a3e0fd82Sopenharmony_ci } 64a3e0fd82Sopenharmony_ci isEaseIn_ = true; 65a3e0fd82Sopenharmony_ci } 66a3e0fd82Sopenharmony_ci 67a3e0fd82Sopenharmony_ciprivate: 68a3e0fd82Sopenharmony_ci void Callback(UIView* view) override 69a3e0fd82Sopenharmony_ci { 70a3e0fd82Sopenharmony_ci uint8_t opa = OPA_OPAQUE * animator_.GetRunTime() / ANIMATOR_DURATION; 71a3e0fd82Sopenharmony_ci if (!isEaseIn_) { 72a3e0fd82Sopenharmony_ci opa = OPA_OPAQUE - opa; 73a3e0fd82Sopenharmony_ci } 74a3e0fd82Sopenharmony_ci float bezielY = opa; 75a3e0fd82Sopenharmony_ci bezielY = 76a3e0fd82Sopenharmony_ci Interpolation::GetBezierY(bezielY / OPA_OPAQUE, BEZIER_CONTROL_POINT_X_1, 0, BEZIER_CONTROL_POINT_X_2, 1); 77a3e0fd82Sopenharmony_ci opa = static_cast<uint8_t>(bezielY * opa); 78a3e0fd82Sopenharmony_ci if (scrollView_.yScrollBarVisible_) { 79a3e0fd82Sopenharmony_ci scrollView_.yScrollBar_->SetOpacity(opa); 80a3e0fd82Sopenharmony_ci } 81a3e0fd82Sopenharmony_ci if (scrollView_.xScrollBarVisible_) { 82a3e0fd82Sopenharmony_ci scrollView_.xScrollBar_->SetOpacity(opa); 83a3e0fd82Sopenharmony_ci } 84a3e0fd82Sopenharmony_ci scrollView_.Invalidate(); 85a3e0fd82Sopenharmony_ci } 86a3e0fd82Sopenharmony_ci 87a3e0fd82Sopenharmony_ci void OnStop(UIView& view) override 88a3e0fd82Sopenharmony_ci { 89a3e0fd82Sopenharmony_ci if (isEaseIn_) { 90a3e0fd82Sopenharmony_ci if (scrollView_.yScrollBarVisible_) { 91a3e0fd82Sopenharmony_ci scrollView_.yScrollBar_->SetOpacity(OPA_OPAQUE); 92a3e0fd82Sopenharmony_ci } 93a3e0fd82Sopenharmony_ci if (Screen::GetInstance().GetScreenShape() == ScreenShape::RECTANGLE && scrollView_.xScrollBarVisible_) { 94a3e0fd82Sopenharmony_ci scrollView_.xScrollBar_->SetOpacity(OPA_OPAQUE); 95a3e0fd82Sopenharmony_ci } 96a3e0fd82Sopenharmony_ci timer_.Start(); // The timer is triggered when animation stops. 97a3e0fd82Sopenharmony_ci } else { 98a3e0fd82Sopenharmony_ci if (scrollView_.yScrollBarVisible_) { 99a3e0fd82Sopenharmony_ci scrollView_.yScrollBar_->SetOpacity(OPA_TRANSPARENT); 100a3e0fd82Sopenharmony_ci } 101a3e0fd82Sopenharmony_ci if (scrollView_.xScrollBarVisible_) { 102a3e0fd82Sopenharmony_ci scrollView_.xScrollBar_->SetOpacity(OPA_TRANSPARENT); 103a3e0fd82Sopenharmony_ci } 104a3e0fd82Sopenharmony_ci } 105a3e0fd82Sopenharmony_ci scrollView_.Invalidate(); 106a3e0fd82Sopenharmony_ci } 107a3e0fd82Sopenharmony_ci 108a3e0fd82Sopenharmony_ci static void TimerCb(void* arg) 109a3e0fd82Sopenharmony_ci { 110a3e0fd82Sopenharmony_ci BarEaseInOutAnimator* barAnimator = reinterpret_cast<BarEaseInOutAnimator*>(arg); 111a3e0fd82Sopenharmony_ci barAnimator->isEaseIn_ = false; 112a3e0fd82Sopenharmony_ci barAnimator->animator_.Start(); 113a3e0fd82Sopenharmony_ci } 114a3e0fd82Sopenharmony_ci static constexpr uint16_t ANIMATOR_DURATION = 250; 115a3e0fd82Sopenharmony_ci static constexpr uint16_t APPEAR_PERIOD = 2000; 116a3e0fd82Sopenharmony_ci static constexpr float BEZIER_CONTROL_POINT_X_1 = 0.33f; 117a3e0fd82Sopenharmony_ci static constexpr float BEZIER_CONTROL_POINT_X_2 = 0.67f; 118a3e0fd82Sopenharmony_ci UIAbstractScroll& scrollView_; 119a3e0fd82Sopenharmony_ci GraphicTimer timer_; 120a3e0fd82Sopenharmony_ci Animator animator_; 121a3e0fd82Sopenharmony_ci bool isEaseIn_ = true; 122a3e0fd82Sopenharmony_ci}; 123a3e0fd82Sopenharmony_ci#endif 124a3e0fd82Sopenharmony_ci 125a3e0fd82Sopenharmony_ciUIAbstractScroll::UIAbstractScroll() 126a3e0fd82Sopenharmony_ci : direction_(VERTICAL), 127a3e0fd82Sopenharmony_ci deltaIndex_(0), 128a3e0fd82Sopenharmony_ci rotateIndex_(0), 129a3e0fd82Sopenharmony_ci reserve_(0), 130a3e0fd82Sopenharmony_ci easingFunc_(EasingEquation::CubicEaseOut), 131a3e0fd82Sopenharmony_ci scrollAnimator_(&animatorCallback_, this, 0, true), 132a3e0fd82Sopenharmony_ci scrollBarSide_(SCROLL_BAR_RIGHT_SIDE), 133a3e0fd82Sopenharmony_ci scrollBarCenter_({0, 0}), 134a3e0fd82Sopenharmony_ci scrollBarCenterSetFlag_(false) 135a3e0fd82Sopenharmony_ci{ 136a3e0fd82Sopenharmony_ci#if defined(ENABLE_FOCUS_MANAGER) && ENABLE_FOCUS_MANAGER 137a3e0fd82Sopenharmony_ci focusable_ = true; 138a3e0fd82Sopenharmony_ci#endif 139a3e0fd82Sopenharmony_ci#if defined(ENABLE_ROTATE_INPUT) && ENABLE_ROTATE_INPUT 140a3e0fd82Sopenharmony_ci rotateFactor_ = DEFAULT_SCROLL_VIEW_ROTATE_FACTOR; 141a3e0fd82Sopenharmony_ci rotateThrowthreshold_ = ABSTRACT_ROTATE_THROW_THRESHOLD; 142a3e0fd82Sopenharmony_ci rotateAccCoefficient_ = ABSTRACT_ROTATE_DISTANCE_COEFF; 143a3e0fd82Sopenharmony_ci isRotating_ = false; 144a3e0fd82Sopenharmony_ci#endif 145a3e0fd82Sopenharmony_ci isViewGroup_ = true; 146a3e0fd82Sopenharmony_ci touchable_ = true; 147a3e0fd82Sopenharmony_ci draggable_ = true; 148a3e0fd82Sopenharmony_ci dragParentInstead_ = false; 149a3e0fd82Sopenharmony_ci} 150a3e0fd82Sopenharmony_ci 151a3e0fd82Sopenharmony_ciUIAbstractScroll::~UIAbstractScroll() 152a3e0fd82Sopenharmony_ci{ 153a3e0fd82Sopenharmony_ci#if defined(DEFAULT_ANIMATION) && DEFAULT_ANIMATION 154a3e0fd82Sopenharmony_ci if (barEaseInOutAnimator_ != nullptr) { 155a3e0fd82Sopenharmony_ci delete barEaseInOutAnimator_; 156a3e0fd82Sopenharmony_ci barEaseInOutAnimator_ = nullptr; 157a3e0fd82Sopenharmony_ci } 158a3e0fd82Sopenharmony_ci#endif 159a3e0fd82Sopenharmony_ci if (xScrollBar_ != nullptr) { 160a3e0fd82Sopenharmony_ci delete xScrollBar_; 161a3e0fd82Sopenharmony_ci xScrollBar_ = nullptr; 162a3e0fd82Sopenharmony_ci } 163a3e0fd82Sopenharmony_ci if (yScrollBar_ != nullptr) { 164a3e0fd82Sopenharmony_ci delete yScrollBar_; 165a3e0fd82Sopenharmony_ci yScrollBar_ = nullptr; 166a3e0fd82Sopenharmony_ci } 167a3e0fd82Sopenharmony_ci} 168a3e0fd82Sopenharmony_ci 169a3e0fd82Sopenharmony_civoid UIAbstractScroll::MoveChildByOffset(int16_t offsetX, int16_t offsetY) 170a3e0fd82Sopenharmony_ci{ 171a3e0fd82Sopenharmony_ci if ((offsetX == 0) && (offsetY == 0)) { 172a3e0fd82Sopenharmony_ci return; 173a3e0fd82Sopenharmony_ci } 174a3e0fd82Sopenharmony_ci UIView* view = GetChildrenHead(); 175a3e0fd82Sopenharmony_ci while (view != nullptr) { 176a3e0fd82Sopenharmony_ci int16_t x = view->GetX() + offsetX; 177a3e0fd82Sopenharmony_ci int16_t y = view->GetY() + offsetY; 178a3e0fd82Sopenharmony_ci view->SetPosition(x, y); 179a3e0fd82Sopenharmony_ci view = view->GetNextSibling(); 180a3e0fd82Sopenharmony_ci } 181a3e0fd82Sopenharmony_ci Invalidate(); 182a3e0fd82Sopenharmony_ci} 183a3e0fd82Sopenharmony_ci 184a3e0fd82Sopenharmony_ciint16_t UIAbstractScroll::GetMaxDelta() const 185a3e0fd82Sopenharmony_ci{ 186a3e0fd82Sopenharmony_ci int16_t result = 0; 187a3e0fd82Sopenharmony_ci for (int16_t i = 0; i < MAX_DELTA_SIZE; i++) { 188a3e0fd82Sopenharmony_ci if (result < MATH_ABS(lastDelta_[i])) { 189a3e0fd82Sopenharmony_ci result = MATH_ABS(lastDelta_[i]); 190a3e0fd82Sopenharmony_ci } 191a3e0fd82Sopenharmony_ci } 192a3e0fd82Sopenharmony_ci return result; 193a3e0fd82Sopenharmony_ci} 194a3e0fd82Sopenharmony_ci 195a3e0fd82Sopenharmony_ciint16_t UIAbstractScroll::GetMaxRotate() const 196a3e0fd82Sopenharmony_ci{ 197a3e0fd82Sopenharmony_ci int16_t result = 0; 198a3e0fd82Sopenharmony_ci for (int16_t i = 0; i < MAX_DELTA_SIZE; i++) { 199a3e0fd82Sopenharmony_ci if (MATH_ABS(result) < MATH_ABS(lastRotate_[i])) { 200a3e0fd82Sopenharmony_ci result = lastRotate_[i]; 201a3e0fd82Sopenharmony_ci } 202a3e0fd82Sopenharmony_ci } 203a3e0fd82Sopenharmony_ci return result; 204a3e0fd82Sopenharmony_ci} 205a3e0fd82Sopenharmony_ci 206a3e0fd82Sopenharmony_civoid UIAbstractScroll::InitDelta() 207a3e0fd82Sopenharmony_ci{ 208a3e0fd82Sopenharmony_ci if (memset_s(lastDelta_, sizeof(lastDelta_), 0, sizeof(lastDelta_)) != EOK) { 209a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("memset_s error"); 210a3e0fd82Sopenharmony_ci } 211a3e0fd82Sopenharmony_ci} 212a3e0fd82Sopenharmony_ci 213a3e0fd82Sopenharmony_civoid UIAbstractScroll::InitRotate() 214a3e0fd82Sopenharmony_ci{ 215a3e0fd82Sopenharmony_ci if (memset_s(lastRotate_, sizeof(lastRotate_), 0, sizeof(lastRotate_)) != EOK) { 216a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("memset_s error"); 217a3e0fd82Sopenharmony_ci } 218a3e0fd82Sopenharmony_ci} 219a3e0fd82Sopenharmony_ci 220a3e0fd82Sopenharmony_civoid UIAbstractScroll::StopAnimator() 221a3e0fd82Sopenharmony_ci{ 222a3e0fd82Sopenharmony_ci scrollAnimator_.Stop(); 223a3e0fd82Sopenharmony_ci animatorCallback_.ResetCallback(); 224a3e0fd82Sopenharmony_ci isDragging_ = false; 225a3e0fd82Sopenharmony_ci} 226a3e0fd82Sopenharmony_ci 227a3e0fd82Sopenharmony_cibool UIAbstractScroll::DragThrowAnimator(Point currentPos, Point lastPos, uint8_t dragDirection, bool dragBack) 228a3e0fd82Sopenharmony_ci{ 229a3e0fd82Sopenharmony_ci if (!throwDrag_ && (reboundSize_ == 0)) { 230a3e0fd82Sopenharmony_ci return false; 231a3e0fd82Sopenharmony_ci } 232a3e0fd82Sopenharmony_ci int16_t dragDistanceX = 0; 233a3e0fd82Sopenharmony_ci int16_t dragDistanceY = 0; 234a3e0fd82Sopenharmony_ci if (throwDrag_) { 235a3e0fd82Sopenharmony_ci CalculateDragDistance(currentPos, lastPos, dragDirection, dragDistanceX, dragDistanceY); 236a3e0fd82Sopenharmony_ci } 237a3e0fd82Sopenharmony_ci if (reboundSize_ != 0) { 238a3e0fd82Sopenharmony_ci CalculateReboundDistance(dragDistanceX, dragDistanceY); 239a3e0fd82Sopenharmony_ci } 240a3e0fd82Sopenharmony_ci 241a3e0fd82Sopenharmony_ci if (!dragBack) { 242a3e0fd82Sopenharmony_ci FixDistance(dragDistanceX, dragDistanceY); 243a3e0fd82Sopenharmony_ci } 244a3e0fd82Sopenharmony_ci 245a3e0fd82Sopenharmony_ci StartAnimator(dragDistanceX, dragDistanceY); 246a3e0fd82Sopenharmony_ci return true; 247a3e0fd82Sopenharmony_ci} 248a3e0fd82Sopenharmony_ci 249a3e0fd82Sopenharmony_civoid UIAbstractScroll::StartAnimator(int16_t dragDistanceX, int16_t dragDistanceY) 250a3e0fd82Sopenharmony_ci{ 251a3e0fd82Sopenharmony_ci int16_t dragTimes = MATH_MAX(MATH_ABS(dragDistanceX), MATH_ABS(dragDistanceY)) / DRAG_TIMES_COEFFICIENT; 252a3e0fd82Sopenharmony_ci if (dragTimes < MIN_DRAG_TIMES) { 253a3e0fd82Sopenharmony_ci dragTimes = MIN_DRAG_TIMES; 254a3e0fd82Sopenharmony_ci } 255a3e0fd82Sopenharmony_ci animatorCallback_.ResetCallback(); 256a3e0fd82Sopenharmony_ci animatorCallback_.SetDragStartValue(0, 0); 257a3e0fd82Sopenharmony_ci animatorCallback_.SetDragEndValue(dragDistanceX, dragDistanceY); 258a3e0fd82Sopenharmony_ci animatorCallback_.SetDragTimes(dragTimes * DRAG_ACC_FACTOR / GetDragACCLevel()); 259a3e0fd82Sopenharmony_ci scrollAnimator_.Start(); 260a3e0fd82Sopenharmony_ci} 261a3e0fd82Sopenharmony_ci 262a3e0fd82Sopenharmony_civoid UIAbstractScroll::CalculateDragDistance(Point currentPos, 263a3e0fd82Sopenharmony_ci Point lastPos, 264a3e0fd82Sopenharmony_ci uint8_t dragDirection, 265a3e0fd82Sopenharmony_ci int16_t& dragDistanceX, 266a3e0fd82Sopenharmony_ci int16_t& dragDistanceY) 267a3e0fd82Sopenharmony_ci{ 268a3e0fd82Sopenharmony_ci if ((direction_ == VERTICAL) || (direction_ == HORIZONTAL_AND_VERTICAL)) { 269a3e0fd82Sopenharmony_ci dragDistanceY = currentPos.y - lastPos.y; 270a3e0fd82Sopenharmony_ci if (isRotating_) { 271a3e0fd82Sopenharmony_ci dragDistanceY *= rotateAccCoefficient_; 272a3e0fd82Sopenharmony_ci } else { 273a3e0fd82Sopenharmony_ci dragDistanceY *= DRAG_DISTANCE_COEFFICIENT; 274a3e0fd82Sopenharmony_ci if (dragDistanceY > 0 || (dragDistanceY == 0 && dragDirection == DragEvent::DIRECTION_TOP_TO_BOTTOM)) { 275a3e0fd82Sopenharmony_ci dragDistanceY += GetMaxDelta() * GetSwipeACCLevel() / DRAG_ACC_FACTOR; 276a3e0fd82Sopenharmony_ci } else if (dragDistanceY < 0 || 277a3e0fd82Sopenharmony_ci (dragDistanceY == 0 && dragDirection == DragEvent::DIRECTION_BOTTOM_TO_TOP)) { 278a3e0fd82Sopenharmony_ci dragDistanceY -= GetMaxDelta() * GetSwipeACCLevel() / DRAG_ACC_FACTOR; 279a3e0fd82Sopenharmony_ci } 280a3e0fd82Sopenharmony_ci } 281a3e0fd82Sopenharmony_ci } 282a3e0fd82Sopenharmony_ci 283a3e0fd82Sopenharmony_ci if ((direction_ == HORIZONTAL) || (direction_ == HORIZONTAL_AND_VERTICAL)) { 284a3e0fd82Sopenharmony_ci dragDistanceX = currentPos.x - lastPos.x; 285a3e0fd82Sopenharmony_ci if (isRotating_) { 286a3e0fd82Sopenharmony_ci dragDistanceX *= rotateAccCoefficient_; 287a3e0fd82Sopenharmony_ci } else { 288a3e0fd82Sopenharmony_ci dragDistanceX *= DRAG_DISTANCE_COEFFICIENT; 289a3e0fd82Sopenharmony_ci if (dragDistanceX > 0 || (dragDistanceX == 0 && dragDirection == DragEvent::DIRECTION_LEFT_TO_RIGHT)) { 290a3e0fd82Sopenharmony_ci dragDistanceX += GetMaxDelta() * GetSwipeACCLevel() / DRAG_ACC_FACTOR; 291a3e0fd82Sopenharmony_ci } else if (dragDistanceX < 0 || 292a3e0fd82Sopenharmony_ci (dragDistanceX == 0 && dragDirection == DragEvent::DIRECTION_RIGHT_TO_LEFT)) { 293a3e0fd82Sopenharmony_ci dragDistanceX -= GetMaxDelta() * GetSwipeACCLevel() / DRAG_ACC_FACTOR; 294a3e0fd82Sopenharmony_ci } 295a3e0fd82Sopenharmony_ci } 296a3e0fd82Sopenharmony_ci } 297a3e0fd82Sopenharmony_ci 298a3e0fd82Sopenharmony_ci if (maxScrollDistance_ != 0) { 299a3e0fd82Sopenharmony_ci if (MATH_ABS(dragDistanceY) > maxScrollDistance_) { 300a3e0fd82Sopenharmony_ci int16_t calculatedValue = (dragDistanceY > 0) ? 1 : -1; 301a3e0fd82Sopenharmony_ci dragDistanceY = calculatedValue * maxScrollDistance_; 302a3e0fd82Sopenharmony_ci } 303a3e0fd82Sopenharmony_ci if (MATH_ABS(dragDistanceX) > maxScrollDistance_) { 304a3e0fd82Sopenharmony_ci int16_t calculatedValue = (dragDistanceX > 0) ? 1 : -1; 305a3e0fd82Sopenharmony_ci dragDistanceX = calculatedValue * maxScrollDistance_; 306a3e0fd82Sopenharmony_ci } 307a3e0fd82Sopenharmony_ci } 308a3e0fd82Sopenharmony_ci} 309a3e0fd82Sopenharmony_ci 310a3e0fd82Sopenharmony_civoid UIAbstractScroll::ListAnimatorCallback::Callback(UIView* view) 311a3e0fd82Sopenharmony_ci{ 312a3e0fd82Sopenharmony_ci if (view == nullptr) { 313a3e0fd82Sopenharmony_ci return; 314a3e0fd82Sopenharmony_ci } 315a3e0fd82Sopenharmony_ci 316a3e0fd82Sopenharmony_ci UIAbstractScroll* scrollView = static_cast<UIAbstractScroll*>(view); 317a3e0fd82Sopenharmony_ci scrollView->isDragging_ = true; 318a3e0fd82Sopenharmony_ci curtTime_++; 319a3e0fd82Sopenharmony_ci if (curtTime_ <= dragTimes_) { 320a3e0fd82Sopenharmony_ci bool needStopX = false; 321a3e0fd82Sopenharmony_ci bool needStopY = false; 322a3e0fd82Sopenharmony_ci if (startValueY_ != endValueY_) { 323a3e0fd82Sopenharmony_ci int16_t actY = scrollView->easingFunc_(startValueY_, endValueY_, curtTime_, dragTimes_); 324a3e0fd82Sopenharmony_ci if (!scrollView->DragYInner(actY - previousValueY_)) { 325a3e0fd82Sopenharmony_ci needStopY = true; 326a3e0fd82Sopenharmony_ci } 327a3e0fd82Sopenharmony_ci previousValueY_ = actY; 328a3e0fd82Sopenharmony_ci } else { 329a3e0fd82Sopenharmony_ci needStopY = true; 330a3e0fd82Sopenharmony_ci } 331a3e0fd82Sopenharmony_ci if (startValueX_ != endValueX_) { 332a3e0fd82Sopenharmony_ci int16_t actX = scrollView->easingFunc_(startValueX_, endValueX_, curtTime_, dragTimes_); 333a3e0fd82Sopenharmony_ci if (!scrollView->DragXInner(actX - previousValueX_)) { 334a3e0fd82Sopenharmony_ci needStopX = true; 335a3e0fd82Sopenharmony_ci } 336a3e0fd82Sopenharmony_ci previousValueX_ = actX; 337a3e0fd82Sopenharmony_ci } else { 338a3e0fd82Sopenharmony_ci needStopX = true; 339a3e0fd82Sopenharmony_ci } 340a3e0fd82Sopenharmony_ci if (needStopX && needStopY) { 341a3e0fd82Sopenharmony_ci scrollView->StopAnimator(); 342a3e0fd82Sopenharmony_ci } 343a3e0fd82Sopenharmony_ci } else { 344a3e0fd82Sopenharmony_ci scrollView->StopAnimator(); 345a3e0fd82Sopenharmony_ci } 346a3e0fd82Sopenharmony_ci} 347a3e0fd82Sopenharmony_ci 348a3e0fd82Sopenharmony_ci#if ENABLE_ROTATE_INPUT 349a3e0fd82Sopenharmony_cibool UIAbstractScroll::OnRotateStartEvent(const RotateEvent& event) 350a3e0fd82Sopenharmony_ci{ 351a3e0fd82Sopenharmony_ci isRotating_ = true; 352a3e0fd82Sopenharmony_ci if (scrollAnimator_.GetState() != Animator::STOP) { 353a3e0fd82Sopenharmony_ci UIAbstractScroll::StopAnimator(); 354a3e0fd82Sopenharmony_ci } 355a3e0fd82Sopenharmony_ci return UIView::OnRotateStartEvent(event); 356a3e0fd82Sopenharmony_ci} 357a3e0fd82Sopenharmony_ci 358a3e0fd82Sopenharmony_cibool UIAbstractScroll::OnRotateEvent(const RotateEvent& event) 359a3e0fd82Sopenharmony_ci{ 360a3e0fd82Sopenharmony_ci int16_t rotateLen = static_cast<int16_t>(event.GetRotate() * rotateFactor_); 361a3e0fd82Sopenharmony_ci RefreshRotate(rotateLen); 362a3e0fd82Sopenharmony_ci if (direction_ == HORIZONTAL) { 363a3e0fd82Sopenharmony_ci DragXInner(rotateLen); 364a3e0fd82Sopenharmony_ci } else { 365a3e0fd82Sopenharmony_ci DragYInner(rotateLen); 366a3e0fd82Sopenharmony_ci } 367a3e0fd82Sopenharmony_ci return UIView::OnRotateEvent(event); 368a3e0fd82Sopenharmony_ci} 369a3e0fd82Sopenharmony_ci 370a3e0fd82Sopenharmony_cibool UIAbstractScroll::OnRotateEndEvent(const RotateEvent& event) 371a3e0fd82Sopenharmony_ci{ 372a3e0fd82Sopenharmony_ci InitDelta(); 373a3e0fd82Sopenharmony_ci 374a3e0fd82Sopenharmony_ci uint8_t dir; 375a3e0fd82Sopenharmony_ci int16_t lastRotateLen = GetMaxRotate(); 376a3e0fd82Sopenharmony_ci if (direction_ == HORIZONTAL) { 377a3e0fd82Sopenharmony_ci dir = (lastRotateLen >= 0) ? DragEvent::DIRECTION_LEFT_TO_RIGHT : DragEvent::DIRECTION_RIGHT_TO_LEFT; 378a3e0fd82Sopenharmony_ci } else { 379a3e0fd82Sopenharmony_ci dir = (lastRotateLen >= 0) ? DragEvent::DIRECTION_TOP_TO_BOTTOM : DragEvent::DIRECTION_BOTTOM_TO_TOP; 380a3e0fd82Sopenharmony_ci } 381a3e0fd82Sopenharmony_ci bool triggerAnimator = (MATH_ABS(lastRotateLen) >= rotateThrowthreshold_); 382a3e0fd82Sopenharmony_ci if (throwDrag_ && triggerAnimator) { 383a3e0fd82Sopenharmony_ci Point current; 384a3e0fd82Sopenharmony_ci if (direction_ == HORIZONTAL) { 385a3e0fd82Sopenharmony_ci current = {lastRotateLen, 0}; 386a3e0fd82Sopenharmony_ci } else { 387a3e0fd82Sopenharmony_ci current = {0, lastRotateLen}; 388a3e0fd82Sopenharmony_ci } 389a3e0fd82Sopenharmony_ci DragThrowAnimator(current, {0, 0}, dir, dragBack_); 390a3e0fd82Sopenharmony_ci } else { 391a3e0fd82Sopenharmony_ci DragThrowAnimator({0, 0}, {0, 0}, dir, dragBack_); 392a3e0fd82Sopenharmony_ci } 393a3e0fd82Sopenharmony_ci isRotating_ = false; 394a3e0fd82Sopenharmony_ci InitRotate(); 395a3e0fd82Sopenharmony_ci return UIView::OnRotateEndEvent(event); 396a3e0fd82Sopenharmony_ci} 397a3e0fd82Sopenharmony_ci#endif 398a3e0fd82Sopenharmony_ci 399a3e0fd82Sopenharmony_civoid UIAbstractScroll::SetXScrollBarVisible(bool visible) 400a3e0fd82Sopenharmony_ci{ 401a3e0fd82Sopenharmony_ci if (Screen::GetInstance().GetScreenShape() == ScreenShape::CIRCLE) { 402a3e0fd82Sopenharmony_ci return; 403a3e0fd82Sopenharmony_ci } else if (visible && xScrollBar_ == nullptr) { 404a3e0fd82Sopenharmony_ci xScrollBar_ = new UIBoxScrollBar(); 405a3e0fd82Sopenharmony_ci } 406a3e0fd82Sopenharmony_ci xScrollBarVisible_ = visible; 407a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 408a3e0fd82Sopenharmony_ci if (xScrollBarVisible_ && barEaseInOutAnimator_ == nullptr) { 409a3e0fd82Sopenharmony_ci barEaseInOutAnimator_ = new BarEaseInOutAnimator(*this); 410a3e0fd82Sopenharmony_ci } 411a3e0fd82Sopenharmony_ci#endif 412a3e0fd82Sopenharmony_ci} 413a3e0fd82Sopenharmony_ci 414a3e0fd82Sopenharmony_civoid UIAbstractScroll::SetYScrollBarVisible(bool visible) 415a3e0fd82Sopenharmony_ci{ 416a3e0fd82Sopenharmony_ci yScrollBarVisible_ = visible; 417a3e0fd82Sopenharmony_ci if (yScrollBarVisible_ && yScrollBar_ == nullptr) { 418a3e0fd82Sopenharmony_ci if (Screen::GetInstance().GetScreenShape() == ScreenShape::CIRCLE) { 419a3e0fd82Sopenharmony_ci yScrollBar_ = new UIArcScrollBar(); 420a3e0fd82Sopenharmony_ci } else { 421a3e0fd82Sopenharmony_ci yScrollBar_ = new UIBoxScrollBar(); 422a3e0fd82Sopenharmony_ci } 423a3e0fd82Sopenharmony_ci } 424a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 425a3e0fd82Sopenharmony_ci if (yScrollBarVisible_ && barEaseInOutAnimator_ == nullptr) { 426a3e0fd82Sopenharmony_ci barEaseInOutAnimator_ = new BarEaseInOutAnimator(*this); 427a3e0fd82Sopenharmony_ci } 428a3e0fd82Sopenharmony_ci#endif 429a3e0fd82Sopenharmony_ci} 430a3e0fd82Sopenharmony_ci 431a3e0fd82Sopenharmony_civoid UIAbstractScroll::OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) 432a3e0fd82Sopenharmony_ci{ 433a3e0fd82Sopenharmony_ci Rect scrollRect = GetRect(); 434a3e0fd82Sopenharmony_ci uint8_t opa = GetMixOpaScale(); 435a3e0fd82Sopenharmony_ci if (Screen::GetInstance().GetScreenShape() == ScreenShape::RECTANGLE) { 436a3e0fd82Sopenharmony_ci if (yScrollBarVisible_) { 437a3e0fd82Sopenharmony_ci if (scrollBarSide_ == SCROLL_BAR_RIGHT_SIDE) { 438a3e0fd82Sopenharmony_ci yScrollBar_->SetPosition(scrollRect.GetRight() - SCROLL_BAR_WIDTH + 1, scrollRect.GetTop(), 439a3e0fd82Sopenharmony_ci SCROLL_BAR_WIDTH, scrollRect.GetHeight()); 440a3e0fd82Sopenharmony_ci } else { 441a3e0fd82Sopenharmony_ci yScrollBar_->SetPosition(scrollRect.GetLeft(), scrollRect.GetTop(), SCROLL_BAR_WIDTH, 442a3e0fd82Sopenharmony_ci scrollRect.GetHeight()); 443a3e0fd82Sopenharmony_ci } 444a3e0fd82Sopenharmony_ci yScrollBar_->OnDraw(gfxDstBuffer, invalidatedArea, opa); 445a3e0fd82Sopenharmony_ci } 446a3e0fd82Sopenharmony_ci if (xScrollBarVisible_) { 447a3e0fd82Sopenharmony_ci if (scrollBarSide_ == SCROLL_BAR_RIGHT_SIDE) { 448a3e0fd82Sopenharmony_ci xScrollBar_->SetPosition(scrollRect.GetLeft(), scrollRect.GetBottom() - SCROLL_BAR_WIDTH + 1, 449a3e0fd82Sopenharmony_ci scrollRect.GetWidth() - SCROLL_BAR_WIDTH, SCROLL_BAR_WIDTH); 450a3e0fd82Sopenharmony_ci } else { 451a3e0fd82Sopenharmony_ci xScrollBar_->SetPosition(scrollRect.GetLeft() + SCROLL_BAR_WIDTH, 452a3e0fd82Sopenharmony_ci scrollRect.GetBottom() - SCROLL_BAR_WIDTH + 1, 453a3e0fd82Sopenharmony_ci scrollRect.GetWidth() - SCROLL_BAR_WIDTH, SCROLL_BAR_WIDTH); 454a3e0fd82Sopenharmony_ci } 455a3e0fd82Sopenharmony_ci xScrollBar_->OnDraw(gfxDstBuffer, invalidatedArea, opa); 456a3e0fd82Sopenharmony_ci } 457a3e0fd82Sopenharmony_ci } else { 458a3e0fd82Sopenharmony_ci if (yScrollBarVisible_) { 459a3e0fd82Sopenharmony_ci yScrollBar_->SetScrollBarSide(scrollBarSide_); 460a3e0fd82Sopenharmony_ci int16_t x; 461a3e0fd82Sopenharmony_ci int16_t y; 462a3e0fd82Sopenharmony_ci if (scrollBarCenterSetFlag_) { 463a3e0fd82Sopenharmony_ci x = scrollRect.GetX() + scrollBarCenter_.x; 464a3e0fd82Sopenharmony_ci y = scrollRect.GetY() + scrollBarCenter_.y; 465a3e0fd82Sopenharmony_ci } else { 466a3e0fd82Sopenharmony_ci x = scrollRect.GetX() + (GetWidth() / 2); // 2: half 467a3e0fd82Sopenharmony_ci y = scrollRect.GetY() + (GetHeight() / 2); // 2: half 468a3e0fd82Sopenharmony_ci } 469a3e0fd82Sopenharmony_ci yScrollBar_->SetPosition(x, y, SCROLL_BAR_WIDTH, GetWidth() / 2); // 2: half 470a3e0fd82Sopenharmony_ci yScrollBar_->OnDraw(gfxDstBuffer, invalidatedArea, opa); 471a3e0fd82Sopenharmony_ci } 472a3e0fd82Sopenharmony_ci } 473a3e0fd82Sopenharmony_ci UIView::OnPostDraw(gfxDstBuffer, invalidatedArea); 474a3e0fd82Sopenharmony_ci} 475a3e0fd82Sopenharmony_ci 476a3e0fd82Sopenharmony_civoid UIAbstractScroll::RefreshAnimator() 477a3e0fd82Sopenharmony_ci{ 478a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 479a3e0fd82Sopenharmony_ci barEaseInOutAnimator_->RefreshBar(); 480a3e0fd82Sopenharmony_ci#endif 481a3e0fd82Sopenharmony_ci} 482a3e0fd82Sopenharmony_ci} // namespace OHOS 483