1 /* 2 * Copyright (c) 2023-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_NG_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_NG_H 18 19 #include <functional> 20 21 #include "base/geometry/dimension.h" 22 #include "core/animation/animator.h" 23 #include "core/animation/friction_motion.h" 24 #include "core/animation/scroll_motion.h" 25 #include "core/components_ng/base/frame_scene_status.h" 26 #include "core/components_ng/gestures/recognizers/pan_recognizer.h" 27 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 28 #include "core/components_ng/render/animation_utils.h" 29 #include "core/event/axis_event.h" 30 #include "core/event/touch_event.h" 31 #include "core/gestures/raw_recognizer.h" 32 #include "core/gestures/timeout_recognizer.h" 33 34 namespace OHOS::Ace::NG { 35 enum class NestedState { 36 GESTURE = 0, 37 CHILD_SCROLL, 38 CHILD_OVER_SCROLL, 39 }; 40 41 struct OverScrollOffset { 42 double start; 43 double end; 44 }; 45 46 struct ScrollResult { 47 double remain; 48 bool reachEdge; 49 }; 50 51 using ScrollEventCallback = std::function<void()>; 52 using OutBoundaryCallback = std::function<bool()>; 53 using ScrollOverCallback = std::function<void(double velocity)>; 54 using WatchFixCallback = std::function<double(double final, double current)>; 55 using ScrollBeginCallback = std::function<ScrollInfo(Dimension, Dimension)>; 56 using ScrollFrameBeginCallback = std::function<ScrollFrameResult(Dimension, ScrollState)>; 57 using DragEndForRefreshCallback = std::function<void()>; 58 using DragCancelRefreshCallback = std::function<void()>; 59 using MouseLeftButtonScroll = std::function<bool()>; 60 using ScrollSnapCallback = std::function<bool(double targetOffset, double velocity)>; 61 using ContinuousSlidingCallback = std::function<double()>; 62 using CalePredictSnapOffsetCallback = 63 std::function<std::optional<float>(float delta, float dragDistance, float velocity)>; 64 using NeedScrollSnapToSideCallback = std::function<bool(float delta)>; 65 using NestableScrollCallback = std::function<ScrollResult(float, int32_t, NestedState)>; 66 using DragFRCSceneCallback = std::function<void(double velocity, NG::SceneStatus sceneStatus)>; 67 using IsReverseCallback = std::function<bool()>; 68 using RemainVelocityCallback = std::function<bool(float)>; 69 70 class FrameNode; 71 class PipelineContext; 72 73 class Scrollable : public TouchEventTarget { 74 DECLARE_ACE_TYPE(Scrollable, TouchEventTarget); 75 76 public: 77 Scrollable(); 78 Scrollable(ScrollPositionCallback&& callback, Axis axis); 79 Scrollable(const ScrollPositionCallback& callback, Axis axis); 80 ~Scrollable() override; 81 82 static void SetVelocityScale(double sVelocityScale); 83 static double GetVelocityScale(); 84 static void SetFriction(double sFriction); 85 86 void Initialize(const WeakPtr<PipelineBase>& context); 87 88 void Initialize(PipelineContext* context); 89 IsMotionStop()90 bool IsMotionStop() const 91 { 92 return isSpringAnimationStop_ && isFrictionAnimationStop_ && !moved_; 93 } 94 IsSpringMotionRunning()95 bool IsSpringMotionRunning() const 96 { 97 return !isSpringAnimationStop_; 98 } 99 IsDragging()100 bool IsDragging() const 101 { 102 return isTouching_ && !isFrictionAnimationStop_; 103 } 104 105 void SetAxis(Axis axis); 106 GetMainOffset(const Offset & offset)107 double GetMainOffset(const Offset& offset) const 108 { 109 return axis_ == Axis::HORIZONTAL ? offset.GetX() : offset.GetY(); 110 } 111 GetMainSize(const Size & size)112 double GetMainSize(const Size& size) const 113 { 114 return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height(); 115 } 116 SetCallback(const ScrollPositionCallback & callback)117 void SetCallback(const ScrollPositionCallback& callback) 118 { 119 callback_ = callback; 120 } 121 SetCoordinateOffset(const Offset & offset)122 void SetCoordinateOffset(const Offset& offset) const 123 { 124 if (panRecognizerNG_) { 125 panRecognizerNG_->SetCoordinateOffset(offset); 126 } 127 } 128 129 void OnCollectTouchTarget(TouchTestResult& result, const RefPtr<FrameNode>& frameNode, 130 const RefPtr<TargetComponent>& targetComponent, ResponseLinkResult& responseLinkResult); 131 SetDragTouchRestrict(const TouchRestrict & touchRestrict)132 void SetDragTouchRestrict(const TouchRestrict& touchRestrict) 133 { 134 if (panRecognizerNG_) { 135 panRecognizerNG_->SetTouchRestrict(touchRestrict); 136 } 137 } 138 SetScrollEndCallback(const ScrollEventCallback & scrollEndCallback)139 void SetScrollEndCallback(const ScrollEventCallback& scrollEndCallback) 140 { 141 scrollEndCallback_ = scrollEndCallback; 142 } 143 SetScrollTouchUpCallback(const ScrollEventCallback & scrollTouchUpCallback)144 void SetScrollTouchUpCallback(const ScrollEventCallback& scrollTouchUpCallback) 145 { 146 scrollTouchUpCallback_ = scrollTouchUpCallback; 147 } 148 SetUnstaticFriction(double friction)149 void SetUnstaticFriction(double friction) 150 { 151 friction_ = friction; 152 } 153 154 void HandleTouchDown(); 155 void HandleTouchUp(); 156 void HandleTouchCancel(); 157 void HandleDragStart(const GestureEvent& info); 158 void HandleDragUpdate(const GestureEvent& info); 159 void HandleDragEnd(const GestureEvent& info); 160 void HandleScrollEnd(const std::optional<float>& velocity); 161 bool HandleOverScroll(double velocity); 162 ScrollResult HandleScroll(double offset, int32_t source, NestedState state); 163 void LayoutDirectionEst(double& correctVelocity); 164 SetMoved(bool value)165 void SetMoved(bool value) 166 { 167 moved_ = value; 168 } SetCanOverScroll(bool value)169 void SetCanOverScroll(bool value) 170 { 171 canOverScroll_ = value; 172 } CanOverScroll()173 bool CanOverScroll() const 174 { 175 return canOverScroll_; 176 } 177 178 void ProcessScrollMotionStop(bool StopFriction); 179 DispatchEvent(const TouchEvent & point)180 bool DispatchEvent(const TouchEvent& point) override 181 { 182 return true; 183 } HandleEvent(const TouchEvent & event)184 bool HandleEvent(const TouchEvent& event) override 185 { 186 if (!available_) { 187 return true; 188 } 189 return true; 190 } HandleEvent(const AxisEvent & event)191 bool HandleEvent(const AxisEvent& event) override 192 { 193 return false; 194 } 195 SetScrollEnd(const ScrollEventCallback & scrollEnd)196 void SetScrollEnd(const ScrollEventCallback& scrollEnd) 197 { 198 scrollEnd_ = scrollEnd; 199 } 200 SetRemainVelocityCallback(const RemainVelocityCallback & remainVelocityCallback)201 void SetRemainVelocityCallback(const RemainVelocityCallback& remainVelocityCallback) 202 { 203 remainVelocityCallback_ = remainVelocityCallback; 204 } 205 SetScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)206 void SetScrollOverCallBack(const ScrollOverCallback& scrollOverCallback) 207 { 208 scrollOverCallback_ = scrollOverCallback; 209 } 210 SetNotifyScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)211 void SetNotifyScrollOverCallBack(const ScrollOverCallback& scrollOverCallback) 212 { 213 notifyScrollOverCallback_ = scrollOverCallback; 214 } 215 SetCurrentPositionCallback(const std::function<double ()> & currentPositionCallback)216 void SetCurrentPositionCallback(const std::function<double()>& currentPositionCallback) 217 { 218 currentPositionCallback_ = currentPositionCallback; 219 } 220 SetOutBoundaryCallback(const OutBoundaryCallback & outBoundaryCallback)221 void SetOutBoundaryCallback(const OutBoundaryCallback& outBoundaryCallback) 222 { 223 outBoundaryCallback_ = outBoundaryCallback; 224 } 225 SetDragEndCallback(const DragEndForRefreshCallback & dragEndCallback)226 void SetDragEndCallback(const DragEndForRefreshCallback& dragEndCallback) 227 { 228 dragEndCallback_ = dragEndCallback; 229 } 230 SetDragCancelCallback(const DragCancelRefreshCallback & dragCancelCallback)231 void SetDragCancelCallback(const DragCancelRefreshCallback& dragCancelCallback) 232 { 233 dragCancelCallback_ = dragCancelCallback; 234 } 235 GetDragEndCallback()236 const DragEndForRefreshCallback& GetDragEndCallback() const 237 { 238 return dragEndCallback_; 239 } 240 GetDragCancelCallback()241 const DragCancelRefreshCallback& GetDragCancelCallback() const 242 { 243 return dragCancelCallback_; 244 } 245 SetWatchFixCallback(const WatchFixCallback & watchFixCallback)246 void SetWatchFixCallback(const WatchFixCallback& watchFixCallback) 247 { 248 watchFixCallback_ = watchFixCallback; 249 } 250 MarkNeedCenterFix(bool needFix)251 void MarkNeedCenterFix(bool needFix) 252 { 253 needCenterFix_ = needFix; 254 } 255 GetCurrentVelocity()256 double GetCurrentVelocity() const 257 { 258 return currentVelocity_; 259 }; 260 SetIsReverseCallback(const IsReverseCallback & isReverseCallback)261 void SetIsReverseCallback(const IsReverseCallback& isReverseCallback) 262 { 263 isReverseCallback_ = isReverseCallback; 264 } 265 266 void OnAnimateStop(); 267 void ProcessScrollSnapStop(); 268 void StartSpringMotion( 269 double mainPosition, double mainVelocity, const ExtentPair& extent, const ExtentPair& initExtent); 270 void UpdateSpringMotion(double mainPosition, const ExtentPair& extent, const ExtentPair& initExtent); 271 272 void UpdateScrollSnapStartOffset(double offset); 273 void StartScrollSnapMotion(float predictSnapOffset, float scrollSnapVelocity); 274 void UpdateScrollSnapEndWithOffset(double offset); 275 276 bool IsAnimationNotRunning() const; 277 278 bool Idle() const; 279 280 bool IsStopped() const; 281 282 bool IsSpringStopped() const; 283 284 bool IsSnapStopped() const; 285 286 void StopScrollable(); 287 Available()288 bool Available() const 289 { 290 return available_; 291 } 292 MarkAvailable(bool available)293 void MarkAvailable(bool available) 294 { 295 available_ = available; 296 } 297 GetContext()298 WeakPtr<PipelineBase> GetContext() const 299 { 300 return context_; 301 } 302 SetNodeId(int32_t nodeId)303 void SetNodeId(int32_t nodeId) 304 { 305 nodeId_ = nodeId; 306 } 307 SetNodeTag(const std::string & nodeTag)308 void SetNodeTag(const std::string& nodeTag) 309 { 310 nodeTag_ = nodeTag; 311 } 312 313 void ProcessScrollOverCallback(double velocity); 314 315 void SetSlipFactor(double SlipFactor); 316 ChangeMoveStatus(bool flag)317 void ChangeMoveStatus(bool flag) 318 { 319 moved_ = flag; 320 } 321 SetOnScrollBegin(const ScrollBeginCallback & scrollBeginCallback)322 void SetOnScrollBegin(const ScrollBeginCallback& scrollBeginCallback) 323 { 324 scrollBeginCallback_ = scrollBeginCallback; 325 } 326 SetOnContinuousSliding(const ContinuousSlidingCallback & continuousSlidingCallback)327 void SetOnContinuousSliding(const ContinuousSlidingCallback& continuousSlidingCallback) 328 { 329 continuousSlidingCallback_ = continuousSlidingCallback; 330 } 331 SetHandleScrollCallback(NestableScrollCallback && func)332 void SetHandleScrollCallback(NestableScrollCallback&& func) 333 { 334 handleScrollCallback_ = std::move(func); 335 } SetOverScrollCallback(std::function<bool (float)> && func)336 void SetOverScrollCallback(std::function<bool(float)>&& func) 337 { 338 overScrollCallback_ = std::move(func); 339 } 340 void StartScrollAnimation(float mainPosition, float velocity); SetOnScrollStartRec(std::function<void (float)> && func)341 void SetOnScrollStartRec(std::function<void(float)>&& func) 342 { 343 onScrollStartRec_ = std::move(func); 344 } SetOnScrollEndRec(std::function<void (const std::optional<float> &)> && func)345 void SetOnScrollEndRec(std::function<void(const std::optional<float>&)>&& func) 346 { 347 onScrollEndRec_ = std::move(func); 348 } 349 SetEdgeEffect(EdgeEffect effect)350 void SetEdgeEffect(EdgeEffect effect) 351 { 352 edgeEffect_ = effect; 353 } 354 SetOnScrollSnapCallback(const ScrollSnapCallback & scrollSnapCallback)355 void SetOnScrollSnapCallback(const ScrollSnapCallback& scrollSnapCallback) 356 { 357 scrollSnapCallback_ = scrollSnapCallback; 358 } SetContinuousDragStatus(bool status)359 void SetContinuousDragStatus(bool status) 360 { 361 continuousDragStatus_ = status; 362 } IncreaseContinueDragCount()363 void IncreaseContinueDragCount() 364 { 365 dragCount_++; 366 } ResetContinueDragCount()367 void ResetContinueDragCount() 368 { 369 dragCount_ = 1; 370 } SetDragStartPosition(double position)371 void SetDragStartPosition(double position) 372 { 373 dragStartPosition_ = position; 374 } SetDragEndPosition(double position)375 void SetDragEndPosition(double position) 376 { 377 dragEndPosition_ = position; 378 } GetDragOffset()379 double GetDragOffset() 380 { 381 return dragEndPosition_ - dragStartPosition_; 382 } 383 SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback && calePredictSnapOffsetCallback)384 void SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback&& calePredictSnapOffsetCallback) 385 { 386 calePredictSnapOffsetCallback_ = std::move(calePredictSnapOffsetCallback); 387 } 388 SetNeedScrollSnapToSideCallback(NeedScrollSnapToSideCallback && needScrollSnapToSideCallback)389 void SetNeedScrollSnapToSideCallback(NeedScrollSnapToSideCallback&& needScrollSnapToSideCallback) 390 { 391 needScrollSnapToSideCallback_ = std::move(needScrollSnapToSideCallback); 392 } 393 394 void ProcessScrollSnapSpringMotion(float scrollSnapDelta, float scrollSnapVelocity); 395 StopSnapController()396 void StopSnapController() 397 { 398 if (!isSnapAnimationStop_) { 399 StopSnapAnimation(); 400 } 401 } 402 GetCurrentPos()403 double GetCurrentPos() const 404 { 405 return currentPos_; 406 } 407 GetNeedScrollSnapChange()408 bool GetNeedScrollSnapChange() const 409 { 410 return needScrollSnapChange_; 411 } 412 AddPreviewMenuHandleDragEnd(GestureEventFunc && actionEnd)413 void AddPreviewMenuHandleDragEnd(GestureEventFunc&& actionEnd) 414 { 415 AddPanActionEndEvent(std::move(actionEnd)); 416 } 417 GetIsDragging()418 bool GetIsDragging() const 419 { 420 return isDragging_; 421 } 422 SetDragFRCSceneCallback(DragFRCSceneCallback && dragFRCSceneCallback)423 void SetDragFRCSceneCallback(DragFRCSceneCallback&& dragFRCSceneCallback) 424 { 425 dragFRCSceneCallback_ = std::move(dragFRCSceneCallback); 426 } 427 GetFinalPosition()428 float GetFinalPosition() 429 { 430 return finalPosition_; 431 } 432 GetSnapFinalPosition()433 float GetSnapFinalPosition() 434 { 435 return endPos_; 436 } 437 SetMaxFlingVelocity(double max)438 void SetMaxFlingVelocity(double max) 439 { 440 double density = PipelineBase::GetCurrentDensity(); 441 maxFlingVelocity_ = max * density; 442 } 443 GetMaxFlingVelocity()444 double GetMaxFlingVelocity() const 445 { 446 return maxFlingVelocity_; 447 } 448 449 void StopFrictionAnimation(); 450 void StopSpringAnimation(bool reachFinalPosition = false); 451 void StopSnapAnimation(); 452 453 RefPtr<NodeAnimatablePropertyFloat> GetFrictionProperty(); 454 RefPtr<NodeAnimatablePropertyFloat> GetSpringProperty(); 455 RefPtr<NodeAnimatablePropertyFloat> GetSnapProperty(); 456 GetPanDirection()457 Axis GetPanDirection() const 458 { 459 CHECK_NULL_RETURN(panRecognizerNG_, Axis::NONE); 460 return panRecognizerNG_->GetAxisDirection(); 461 } 462 SetNestedScrolling(bool nestedScrolling)463 void SetNestedScrolling(bool nestedScrolling) 464 { 465 nestedScrolling_ = nestedScrolling; 466 } 467 GetNestedScrolling()468 bool GetNestedScrolling() const 469 { 470 return nestedScrolling_; 471 } 472 AddPanActionEndEvent(GestureEventFunc && event)473 void AddPanActionEndEvent(GestureEventFunc&& event) 474 { 475 panActionEndEvents_.emplace_back(event); 476 } 477 478 private: 479 bool UpdateScrollPosition(double offset, int32_t source) const; 480 void ProcessSpringMotion(double position); 481 void ProcessScrollMotion(double position); 482 void ProcessScrollSnapMotion(double position); 483 void FixScrollMotion(float position, float initVelocity); 484 void ExecuteScrollBegin(double& mainDelta); 485 double ComputeCap(int dragCount); 486 double GetGain(double delta); 487 void SetDelayedTask(); 488 void MarkNeedFlushAnimationStartTime(); 489 float GetFrictionVelocityByFinalPosition( 490 float final, float position, float signum, float friction, float threshold = DEFAULT_MULTIPLIER); 491 492 /** 493 * @brief Checks if the scroll event is caused by a mouse wheel. 494 * 495 * @param info The GestureEvent containing the scroll event information. 496 * @return true if the scroll event is caused by a mouse wheel, false otherwise. 497 */ 498 static inline bool IsMouseWheelScroll(const GestureEvent& info); 499 500 ScrollPositionCallback callback_; 501 ScrollEventCallback scrollEnd_; 502 ScrollEventCallback scrollEndCallback_; 503 ScrollEventCallback scrollTouchUpCallback_; 504 ScrollOverCallback scrollOverCallback_; // scroll motion controller when edge set to spring 505 ScrollOverCallback notifyScrollOverCallback_; // scroll motion controller when edge set to spring 506 OutBoundaryCallback outBoundaryCallback_; // whether out of boundary check when edge set to spring 507 std::function<double()> currentPositionCallback_; 508 IsReverseCallback isReverseCallback_; 509 510 WatchFixCallback watchFixCallback_; 511 ScrollBeginCallback scrollBeginCallback_; 512 ScrollSnapCallback scrollSnapCallback_; 513 DragEndForRefreshCallback dragEndCallback_; 514 DragCancelRefreshCallback dragCancelCallback_; 515 ContinuousSlidingCallback continuousSlidingCallback_; 516 Axis axis_ = Axis::VERTICAL; 517 // used for ng structure. 518 RefPtr<NG::PanRecognizer> panRecognizerNG_; 519 520 WeakPtr<PipelineBase> context_; 521 double currentPos_ = 0.0; 522 double currentVelocity_ = 0.0; 523 double maxFlingVelocity_ = 0.0; 524 bool scrollPause_ = false; 525 bool touchUp_ = false; 526 bool moved_ = false; 527 bool isTouching_ = false; 528 bool isDragging_ = false; 529 bool available_ = true; 530 bool needCenterFix_ = false; 531 bool isDragUpdateStop_ = false; 532 bool isFadingAway_ = false; 533 // The accessibilityId of UINode 534 int32_t nodeId_ = 0; 535 // The tag of UINode 536 std::string nodeTag_ = "Scrollable"; 537 double slipFactor_ = 0.0; 538 static std::optional<double> sFriction_; 539 static std::optional<double> sVelocityScale_; 540 bool continuousDragStatus_ = false; 541 CancelableCallback<void()> task_; 542 int32_t dragCount_ = 0; 543 double lastPos_ = 0.0; 544 double dragStartPosition_ = 0.0; 545 double dragEndPosition_ = 0.0; 546 double lastVelocity_ = 0.0; 547 double friction_ = -1.0; 548 double velocityScale_ = 0.0; 549 double preGain_ = 1.0; 550 #ifdef OHOS_PLATFORM 551 int64_t startIncreaseTime_ = 0; 552 #endif 553 554 // ScrollablePattern::HandleScroll 555 NestableScrollCallback handleScrollCallback_; 556 // ScrollablePattern::HandleOverScroll 557 std::function<bool(float)> overScrollCallback_; 558 // ScrollablePattern::onScrollStartRecursiveInner 559 std::function<void(float)> onScrollStartRec_; 560 // ScrollablePattern::onScrollEndRecursiveInner 561 std::function<void(const std::optional<float>&)> onScrollEndRec_; 562 // ScrollablePattern::RemainVelocityToChild 563 RemainVelocityCallback remainVelocityCallback_; 564 565 EdgeEffect edgeEffect_ = EdgeEffect::NONE; 566 bool canOverScroll_ = true; 567 568 // scrollSnap 569 bool needScrollSnapChange_ = false; 570 CalePredictSnapOffsetCallback calePredictSnapOffsetCallback_; 571 NeedScrollSnapToSideCallback needScrollSnapToSideCallback_; 572 std::list<GestureEventFunc> panActionEndEvents_; 573 574 DragFRCSceneCallback dragFRCSceneCallback_; 575 576 uint64_t lastVsyncTime_ = 0; 577 RefPtr<NodeAnimatablePropertyFloat> frictionOffsetProperty_; 578 float finalPosition_ = 0.0f; 579 float lastPosition_ = 0.0f; 580 float initVelocity_ = 0.0f; 581 float frictionVelocity_ = 0.0f; 582 bool isFrictionAnimationStop_ = true; 583 584 RefPtr<NodeAnimatablePropertyFloat> springOffsetProperty_; 585 bool isSpringAnimationStop_ = true; 586 bool skipRestartSpring_ = false; // set to true when need to skip repeated spring animation 587 uint32_t updateSnapAnimationCount_ = 0; 588 uint32_t springAnimationCount_ = 0; 589 590 RefPtr<NodeAnimatablePropertyFloat> snapOffsetProperty_; 591 bool isSnapAnimationStop_ = true; 592 bool isSnapScrollAnimationStop_ = true; 593 float snapVelocity_ = 0.0f; 594 float endPos_ = 0.0; 595 bool isSnapAnimation_ = false; 596 bool nestedScrolling_ = false; 597 }; 598 599 } // namespace OHOS::Ace::NG 600 601 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_NG_H 602