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_NG_PATTERNS_SCROLLABLE_SCROLLABLE_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLLABLE_SCROLLABLE_PATTERN_H 18 19 #include <cmath> 20 #include <vector> 21 22 #include "base/geometry/axis.h" 23 #include "core/animation/select_motion.h" 24 #include "core/animation/spring_curve.h" 25 #include "core/animation/bezier_variable_velocity_motion.h" 26 #include "core/animation/velocity_motion.h" 27 #include "core/components_ng/base/frame_scene_status.h" 28 #include "core/components_ng/event/drag_event.h" 29 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h" 30 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h" 31 #include "core/components_ng/pattern/pattern.h" 32 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h" 33 #include "core/components_ng/pattern/scroll/inner/scroll_bar_overlay_modifier.h" 34 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h" 35 #include "core/components_ng/pattern/scrollable/nestable_scroll_container.h" 36 #include "core/components_ng/pattern/scrollable/refresh_coordination.h" 37 #include "core/components_ng/pattern/scrollable/scrollable_controller.h" 38 #include "core/components_ng/pattern/scrollable/scrollable_coordination_event.h" 39 #include "core/components_ng/pattern/scrollable/scrollable_paint_method.h" 40 #include "core/components_ng/pattern/scrollable/scrollable_paint_property.h" 41 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 42 #include "core/components_ng/render/animation_utils.h" 43 #include "core/event/mouse_event.h" 44 #include "core/components_ng/event/scrollable_event.h" 45 namespace OHOS::Ace::NG { 46 class InspectorFilter; 47 #ifndef WEARABLE_PRODUCT 48 constexpr double FRICTION = 0.6; 49 constexpr double API11_FRICTION = 0.7; 50 constexpr double API12_FRICTION = 0.75; 51 constexpr double MAX_VELOCITY = 9000.0; 52 #else 53 constexpr double FRICTION = 0.9; 54 constexpr double MAX_VELOCITY = 5000.0; 55 #endif 56 constexpr float SPRING_ACCURACY = 0.1f; 57 enum class ModalSheetCoordinationMode : char { 58 UNKNOWN = 0, 59 SHEET_SCROLL = 1, 60 SCROLLABLE_SCROLL = 2, 61 }; 62 struct ScrollOffsetAbility { 63 std::function<bool(float)> scrollFunc = nullptr; 64 Axis axis = Axis::VERTICAL; 65 float contentStartOffset = 0.0f; 66 float contentEndOffset = 0.0f; 67 }; 68 class ScrollablePattern : public NestableScrollContainer { 69 DECLARE_ACE_TYPE(ScrollablePattern, NestableScrollContainer); 70 71 public: 72 ScrollablePattern(); 73 ScrollablePattern(EdgeEffect edgeEffect, bool alwaysEnabled); 74 ~ScrollablePattern()75 ~ScrollablePattern() 76 { 77 UnRegister2DragDropManager(); 78 if (scrollBarProxy_) { 79 scrollBarProxy_->UnRegisterNestScrollableNode(AceType::WeakClaim(this)); 80 } 81 } 82 IsAtomicNode()83 bool IsAtomicNode() const override 84 { 85 return false; 86 } 87 88 RefPtr<PaintProperty> CreatePaintProperty() override; 89 90 void CreateAnalyzerOverlay(const RefPtr<FrameNode> node); 91 92 void UpdateFadingEdge(const RefPtr<ScrollablePaintMethod>& paint); 93 94 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 95 void OnWindowHide() override; 96 97 // scrollable GetAxis()98 Axis GetAxis() const override 99 { 100 return axis_; 101 } 102 IsReverse()103 virtual bool IsReverse() const 104 { 105 if (GetAxis() != Axis::HORIZONTAL) { 106 return false; 107 } 108 auto host = GetHost(); 109 CHECK_NULL_RETURN(host, false); 110 auto layoutProperty = host->GetLayoutProperty<LayoutProperty>(); 111 CHECK_NULL_RETURN(layoutProperty, false); 112 auto layoutDirection = layoutProperty->GetNonAutoLayoutDirection(); 113 return (layoutDirection == TextDirection::RTL); 114 }; 115 ShouldDelayChildPressedState()116 virtual bool ShouldDelayChildPressedState() const override 117 { 118 return true; 119 } 120 121 void RegisterScrollingListener(const RefPtr<ScrollingListener> listener) override; 122 void FireAndCleanScrollingListener() override; 123 void CleanScrollingListener() override; 124 125 void SetAxis(Axis axis); 126 virtual bool UpdateCurrentOffset(float delta, int32_t source) = 0; IsScrollable()127 virtual bool IsScrollable() const 128 { 129 return false; 130 } 131 virtual bool IsAtTop() const = 0; 132 virtual bool IsAtBottom() const = 0; IsFadingBottom()133 virtual bool IsFadingBottom() const 134 { 135 return !IsAtBottom(); 136 } OutBoundaryCallback()137 virtual bool OutBoundaryCallback() 138 { 139 return IsOutOfBoundary(); 140 } 141 142 virtual bool IsOutOfBoundary(bool useCurrentDelta = true) 143 { 144 return false; 145 } 146 147 virtual void OnTouchDown(const TouchEventInfo& info); 148 149 void AddScrollEvent(); GetScrollableEvent()150 RefPtr<ScrollableEvent> GetScrollableEvent() 151 { 152 return scrollableEvent_; 153 } 154 virtual bool OnScrollCallback(float offset, int32_t source); 155 virtual void OnScrollStartCallback(); 156 virtual void FireOnScrollStart(); FireOnReachStart(const OnReachEvent & onReachStart)157 virtual void FireOnReachStart(const OnReachEvent& onReachStart) {} FireOnReachEnd(const OnReachEvent & onReachEnd)158 virtual void FireOnReachEnd(const OnReachEvent& onReachEnd) {} ScrollableIdle()159 bool ScrollableIdle() 160 { 161 return !scrollableEvent_ || scrollableEvent_->Idle(); 162 } SetScrollEnabled(bool enabled)163 void SetScrollEnabled(bool enabled) 164 { 165 CHECK_NULL_VOID(scrollableEvent_); 166 bool bNest = false; 167 if (scrollBarProxy_) { 168 bNest = scrollBarProxy_->IsNestScroller(); 169 } 170 171 if (enabled || bNest) { 172 enabled = true; 173 scrollableEvent_->SetAxis(axis_); 174 } else { 175 scrollableEvent_->SetAxis(Axis::NONE); 176 } 177 scrollableEvent_->SetEnabled(enabled); 178 179 if (scrollBarProxy_) { 180 scrollBarProxy_->SetScrollEnabled(enabled, AceType::WeakClaim(this)); 181 } 182 } 183 GetScrollEnabled()184 bool GetScrollEnabled() const 185 { 186 CHECK_NULL_RETURN(scrollableEvent_, false); 187 return scrollableEvent_->GetEnabled(); 188 } 189 190 RefPtr<GestureEventHub> GetGestureHub(); 191 RefPtr<InputEventHub> GetInputHub(); 192 193 // edgeEffect GetScrollEdgeEffect()194 const RefPtr<ScrollEdgeEffect>& GetScrollEdgeEffect() const 195 { 196 return scrollEffect_; 197 } 198 bool HandleEdgeEffect(float offset, int32_t source, const SizeF& size); 199 void HandleFadeEffect(float offset, int32_t source, const SizeF& size, 200 bool isNotPositiveScrollableDistance); SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect> & scrollEffect)201 virtual void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) {} IsRestrictBoundary()202 bool IsRestrictBoundary() 203 { 204 return !scrollEffect_ || scrollEffect_->IsRestrictBoundary(); 205 } 206 207 // scrollBar 208 virtual void UpdateScrollBarOffset() = 0; 209 void SetScrollBar(const std::unique_ptr<ScrollBarProperty>& property); 210 void SetScrollBar(DisplayMode displayMode); 211 void SetScrollBarProxy(const RefPtr<ScrollBarProxy>& scrollBarProxy); 212 void CreateScrollBarOverlayModifier(); 213 GetScrollableDistance()214 float GetScrollableDistance() const 215 { 216 return estimatedHeight_; 217 } 218 GetBarOffset()219 float GetBarOffset() const 220 { 221 return barOffset_; 222 } 223 GetScrollBarOutBoundaryExtent()224 double GetScrollBarOutBoundaryExtent() const 225 { 226 return scrollBarOutBoundaryExtent_; 227 } 228 SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent)229 void SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent) 230 { 231 scrollBarOutBoundaryExtent_ = scrollBarOutBoundaryExtent; 232 } 233 234 void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent); 235 GetMainSize(const SizeF & size)236 double GetMainSize(const SizeF& size) const 237 { 238 return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height(); 239 } 240 IsScrollableStopped()241 bool IsScrollableStopped() const 242 { 243 CHECK_NULL_RETURN(scrollableEvent_, true); 244 auto scrollable = scrollableEvent_->GetScrollable(); 245 CHECK_NULL_RETURN(scrollable, true); 246 return scrollable->IsStopped(); 247 } 248 GetIsDragging()249 bool GetIsDragging() const 250 { 251 CHECK_NULL_RETURN(scrollableEvent_, false); 252 auto scrollable = scrollableEvent_->GetScrollable(); 253 CHECK_NULL_RETURN(scrollable, false); 254 return scrollable->GetIsDragging(); 255 } 256 StopScrollable()257 void StopScrollable() 258 { 259 CHECK_NULL_VOID(scrollableEvent_); 260 auto scrollable = scrollableEvent_->GetScrollable(); 261 CHECK_NULL_VOID(scrollable); 262 scrollable->StopScrollable(); 263 } 264 StartScrollSnapMotion(float scrollSnapDelta,float scrollSnapVelocity)265 void StartScrollSnapMotion(float scrollSnapDelta, float scrollSnapVelocity) 266 { 267 CHECK_NULL_VOID(scrollableEvent_); 268 auto scrollable = scrollableEvent_->GetScrollable(); 269 CHECK_NULL_VOID(scrollable); 270 scrollable->ProcessScrollSnapSpringMotion(scrollSnapDelta, scrollSnapVelocity); 271 } 272 IsScrollableSpringEffect()273 bool IsScrollableSpringEffect() const 274 { 275 CHECK_NULL_RETURN(scrollEffect_, false); 276 return scrollEffect_->IsSpringEffect(); 277 } 278 SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring)279 void SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring) 280 { 281 isCoordEventNeedSpring_ = IsCoordEventNeedSpring; 282 } 283 284 void GetParentNavigation(); 285 void GetParentModalSheet(); 286 287 /** 288 * @brief Return the portion of delta that's in overScroll range. 289 * 290 * @param delta incoming offset change. 291 * @return the portion of delta in overScroll range. Both top overScroll and bottom overScroll. 292 */ GetOverScrollOffset(double delta)293 virtual OverScrollOffset GetOverScrollOffset(double delta) const 294 { 295 return { 0, 0 }; 296 } 297 OnScrollSnapCallback(double targetOffset,double velocity)298 virtual bool OnScrollSnapCallback(double targetOffset, double velocity) 299 { 300 return false; 301 } 302 StartScrollBarAnimatorByProxy()303 void StartScrollBarAnimatorByProxy() 304 { 305 if (scrollBarProxy_) { 306 scrollBarProxy_->StartScrollBarAnimator(); 307 } 308 309 for (auto proxy : nestScrollBarProxy_) { 310 auto scrollBarProxy = proxy.Upgrade(); 311 CHECK_NULL_CONTINUE(scrollBarProxy); 312 scrollBarProxy->StartScrollBarAnimator(); 313 } 314 } 315 StopScrollBarAnimatorByProxy()316 void StopScrollBarAnimatorByProxy() 317 { 318 if (scrollBarProxy_) { 319 scrollBarProxy_->StopScrollBarAnimator(); 320 } 321 322 for (auto proxy : nestScrollBarProxy_) { 323 auto scrollBarProxy = proxy.Upgrade(); 324 CHECK_NULL_CONTINUE(scrollBarProxy); 325 scrollBarProxy->StopScrollBarAnimator(); 326 } 327 } 328 329 void SetFriction(double friction); 330 GetFriction()331 double GetFriction() const 332 { 333 return friction_; 334 } 335 336 void SetMaxFlingVelocity(double max); 337 GetMaxFlingVelocity()338 double GetMaxFlingVelocity() const 339 { 340 CHECK_NULL_RETURN(scrollableEvent_, 0.0); 341 auto scrollable = scrollableEvent_->GetScrollable(); 342 CHECK_NULL_RETURN(scrollable, 0.0); 343 return scrollable->GetMaxFlingVelocity(); 344 } 345 346 virtual void StopAnimate(); 347 AnimateRunning()348 bool AnimateRunning() const 349 { 350 return (animator_ && animator_->IsRunning()) || !isAnimationStop_; 351 } AnimateStoped()352 bool AnimateStoped() const 353 { 354 return (!animator_ || animator_->IsStopped()) && isAnimationStop_; 355 } 356 AbortScrollAnimator()357 void AbortScrollAnimator() 358 { 359 if (animator_ && !animator_->IsStopped()) { 360 scrollAbort_ = true; 361 animator_->Stop(); 362 } 363 if (!isAnimationStop_) { 364 scrollAbort_ = true; 365 StopAnimation(springAnimation_); 366 StopAnimation(curveAnimation_); 367 } 368 } GetScrollAbort()369 bool GetScrollAbort() const 370 { 371 return scrollAbort_; 372 } SetScrollAbort(bool abort)373 void SetScrollAbort(bool abort) 374 { 375 scrollAbort_ = abort; 376 } 377 void PlaySpringAnimation(float position, float velocity, float mass, float stiffness, float damping, 378 bool useTotalOffset = true); 379 void PlayCurveAnimation(float position, float duration, const RefPtr<Curve>& curve, bool canOverScroll); GetTotalOffset()380 virtual float GetTotalOffset() const 381 { 382 return 0.0f; 383 } 384 // main size of all children GetTotalHeight()385 virtual float GetTotalHeight() const 386 { 387 return 0.0f; 388 } OnAnimateStop()389 virtual void OnAnimateStop() {} 390 virtual void ScrollTo(float position); 391 virtual void AnimateTo( 392 float position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll = false, 393 bool useTotalOffset = true); CanOverScroll(int32_t source)394 virtual bool CanOverScroll(int32_t source) 395 { 396 auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR && 397 IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_)); 398 if (canOverScroll != lastCanOverScroll_) { 399 lastCanOverScroll_ = canOverScroll; 400 AddScrollableFrameInfo(source); 401 } 402 return canOverScroll; 403 } 404 void MarkSelectedItems(); 405 bool ShouldSelectScrollBeStopped(); 406 void UpdateMouseStart(float offset); 407 408 // scrollSnap CalePredictSnapOffset(float delta,float dragDistance,float velocity)409 virtual std::optional<float> CalePredictSnapOffset(float delta, float dragDistance, float velocity) 410 { 411 std::optional<float> predictSnapPosition; 412 return predictSnapPosition; 413 } 414 NeedScrollSnapToSide(float delta)415 virtual bool NeedScrollSnapToSide(float delta) 416 { 417 return false; 418 } 419 SetScrollSource(int32_t scrollSource)420 void SetScrollSource(int32_t scrollSource) 421 { 422 if (scrollSource == SCROLL_FROM_JUMP || scrollSource == SCROLL_FROM_FOCUS_JUMP) { 423 if (scrollBar_ && scrollBar_->IsScrollable() && scrollBarOverlayModifier_) { 424 scrollBarOverlayModifier_->SetOpacity(UINT8_MAX); 425 scrollBar_->ScheduleDisappearDelayTask(); 426 } 427 StopScrollBarAnimatorByProxy(); 428 StartScrollBarAnimatorByProxy(); 429 } 430 if (scrollSource == SCROLL_FROM_NONE) { 431 if (lastScrollSource_ != scrollSource_) { 432 AddScrollableFrameInfo(scrollSource_); 433 } 434 lastScrollSource_ = scrollSource_; 435 } 436 scrollSource_ = scrollSource; 437 } 438 GetScrollSource()439 int32_t GetScrollSource() const 440 { 441 return scrollSource_; 442 } 443 GetCurrentVelocity()444 float GetCurrentVelocity() const 445 { 446 return currentVelocity_; 447 } 448 449 ScrollState GetScrollState() const; 450 451 static ScrollState GetScrollState(int32_t scrollSource); 452 453 static ScrollSource ConvertScrollSource(int32_t source); 454 CalculateFriction(float gamma)455 static float CalculateFriction(float gamma) 456 { 457 constexpr float RATIO = 1.848f; 458 if (GreatOrEqual(gamma, 1.0)) { 459 gamma = 1.0f; 460 } 461 return exp(-RATIO * gamma); 462 } 463 virtual float GetMainContentSize() const; 464 SupportScrollToIndex()465 virtual bool SupportScrollToIndex() const 466 { 467 return true; 468 } 469 GetDefaultScrollAlign()470 virtual ScrollAlign GetDefaultScrollAlign() const 471 { 472 return ScrollAlign::START; 473 } 474 475 virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, 476 std::optional<float> extraOffset = std::nullopt) 477 {} 478 SetExtraOffset(std::optional<float> extraOffset)479 void SetExtraOffset(std::optional<float> extraOffset) 480 { 481 extraOffset_ = extraOffset; 482 } 483 GetExtraOffset()484 const std::optional<float>& GetExtraOffset() const 485 { 486 return extraOffset_; 487 } 488 ResetExtraOffset()489 void ResetExtraOffset() 490 { 491 extraOffset_.reset(); 492 } 493 494 virtual void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth); 495 GetScrollEdgeType()496 virtual ScrollEdgeType GetScrollEdgeType() const 497 { 498 return ScrollEdgeType::SCROLL_NONE; 499 } 500 SetScrollEdgeType(ScrollEdgeType scrollEdgeType)501 virtual void SetScrollEdgeType(ScrollEdgeType scrollEdgeType) {} 502 503 virtual void Fling(double flingVelocity); 504 SetPositionController(RefPtr<ScrollableController> control)505 void SetPositionController(RefPtr<ScrollableController> control) 506 { 507 positionController_ = control; 508 if (control) { 509 control->SetScrollPattern(AceType::WeakClaim(this)); 510 } 511 } 512 GetOrCreatePositionController()513 RefPtr<ScrollableController> GetOrCreatePositionController() 514 { 515 if (!positionController_) { 516 auto controller = AceType::MakeRefPtr<NG::ScrollableController>(); 517 SetPositionController(controller); 518 } 519 return positionController_; 520 } 521 GetItemRect(int32_t index)522 virtual Rect GetItemRect(int32_t index) const 523 { 524 return Rect(); 525 }; 526 GetItemIndex(double x,double y)527 virtual int32_t GetItemIndex(double x, double y) const 528 { 529 return -1; 530 } 531 SetEdgeEffect(EdgeEffect edgeEffect,bool alwaysEnabled)532 void SetEdgeEffect(EdgeEffect edgeEffect, bool alwaysEnabled) 533 { 534 edgeEffect_ = edgeEffect; 535 edgeEffectAlwaysEnabled_ = alwaysEnabled; 536 } 537 GetEdgeEffect()538 EdgeEffect GetEdgeEffect() 539 { 540 return edgeEffect_; 541 } 542 GetAlwaysEnabled()543 bool GetAlwaysEnabled() const 544 { 545 return edgeEffectAlwaysEnabled_; 546 } 547 SetAlwaysEnabled(bool alwaysEnabled)548 void SetAlwaysEnabled(bool alwaysEnabled) 549 { 550 edgeEffectAlwaysEnabled_ = alwaysEnabled; 551 } 552 IsScrollableAnimationNotRunning()553 bool IsScrollableAnimationNotRunning() 554 { 555 if (scrollableEvent_) { 556 auto scrollable = scrollableEvent_->GetScrollable(); 557 if (scrollable) { 558 return scrollable->IsAnimationNotRunning(); 559 } 560 return false; 561 } 562 return false; 563 } 564 GetFinalPosition()565 float GetFinalPosition() const 566 { 567 return finalPosition_; 568 } 569 void HandleOnDragStatusCallback( 570 const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent) override; 571 IsScrollableSpringMotionRunning()572 bool IsScrollableSpringMotionRunning() 573 { 574 CHECK_NULL_RETURN(scrollableEvent_, false); 575 auto scrollable = scrollableEvent_->GetScrollable(); 576 CHECK_NULL_RETURN(scrollable, false); 577 return scrollable->IsSpringMotionRunning(); 578 } 579 IsScrollSnap()580 virtual bool IsScrollSnap() 581 { 582 // When setting snap or enablePaging in scroll, the PARENT_FIRST in nestedScroll_ is invalid 583 return false; 584 } 585 SetNeedLinked(bool needLinked)586 void SetNeedLinked(bool needLinked) 587 { 588 needLinked_ = needLinked; 589 } 590 SetAnimateCanOverScroll(bool animateCanOverScroll)591 void SetAnimateCanOverScroll(bool animateCanOverScroll) 592 { 593 bool isScrollable = !(IsAtBottom() && IsAtTop() && !GetAlwaysEnabled()); 594 animateCanOverScroll_ = isScrollable && animateCanOverScroll; 595 } 596 GetVisibleSelectedItems()597 virtual std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() 598 { 599 std::vector<RefPtr<FrameNode>> children; 600 return children; 601 } 602 void InitScrollBarGestureEvent(); 603 604 virtual void InitScrollBarClickEvent(); 605 void HandleClickEvent(); 606 void InitScrollBarMouseEvent(); 607 virtual void ScrollPage( 608 bool reverse, bool smooth = false, AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL); 609 void PrintOffsetLog(AceLogTag tag, int32_t id, double finalOffset); 610 611 void CheckRestartSpring(bool sizeDiminished, bool needNestedScrolling = true); 612 GetScrollablePanDirection()613 Axis GetScrollablePanDirection() 614 { 615 CHECK_NULL_RETURN(scrollableEvent_, Axis::NONE); 616 auto scrollable = scrollableEvent_->GetScrollable(); 617 CHECK_NULL_RETURN(scrollable, Axis::NONE); 618 return scrollable->GetPanDirection(); 619 } 620 621 void AddEventsFiredInfo(ScrollableEventType eventType); 622 623 void AddScrollableFrameInfo(int32_t scrollSource); 624 625 void GetEdgeEffectDumpInfo(); 626 627 void GetAxisDumpInfo(); 628 629 void GetPanDirectionDumpInfo(); 630 631 void GetPaintPropertyDumpInfo(); 632 633 void GetEventDumpInfo(); 634 635 void DumpAdvanceInfo() override; 636 SetScrollToSafeAreaHelper(bool isScrollToSafeAreaHelper)637 void SetScrollToSafeAreaHelper(bool isScrollToSafeAreaHelper) 638 { 639 isScrollToSafeAreaHelper_ = isScrollToSafeAreaHelper; 640 } 641 IsScrollToSafeAreaHelper()642 bool IsScrollToSafeAreaHelper() const 643 { 644 return isScrollToSafeAreaHelper_; 645 } 646 GetScrollOffsetAbility()647 virtual ScrollOffsetAbility GetScrollOffsetAbility() 648 { 649 return { nullptr, Axis::NONE }; 650 } 651 GetScrollIndexAbility()652 virtual std::function<bool(int32_t)> GetScrollIndexAbility() 653 { 654 return nullptr; 655 } 656 657 void ScrollAtFixedVelocity(float velocity); 658 659 PositionMode GetPositionMode(); 660 661 void HandleMoveEventInComp(const PointF& point); 662 void HandleLeaveHotzoneEvent(); SetHotZoneScrollCallback(std::function<void (void)> && func)663 void SetHotZoneScrollCallback(std::function<void(void)>&& func) 664 { 665 hotZoneScrollCallback_ = func; 666 } 667 668 void OnCollectClickTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 669 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 670 ResponseLinkResult& responseLinkResult); 671 672 virtual void SetAccessibilityAction(); GetScrollBarProxy()673 RefPtr<NG::ScrollBarProxy> GetScrollBarProxy() const 674 { 675 return scrollBarProxy_; 676 } 677 678 virtual void OnAttachToMainTree() override; 679 680 void AddNestScrollBarProxy(const WeakPtr<ScrollBarProxy>& scrollBarProxy); 681 682 void SetParentNestedScroll(RefPtr<ScrollablePattern>& parentPattern); 683 684 void SearchAndSetParentNestedScroll(const RefPtr<FrameNode>& node); 685 686 void UnsetParentNestedScroll(RefPtr<ScrollablePattern>& parentPattern); 687 688 void SearchAndUnsetParentNestedScroll(const RefPtr<FrameNode>& node); 689 690 void DeleteNestScrollBarProxy(const WeakPtr<ScrollBarProxy>& scrollBarProxy); 691 SetUseTotalOffset(bool useTotalOffset)692 void SetUseTotalOffset(bool useTotalOffset) 693 { 694 useTotalOffset_ = useTotalOffset; 695 } 696 GetNestedScrolling()697 bool GetNestedScrolling() const 698 { 699 CHECK_NULL_RETURN(scrollableEvent_, false); 700 auto scrollable = scrollableEvent_->GetScrollable(); 701 CHECK_NULL_RETURN(scrollable, false); 702 return scrollable->GetNestedScrolling(); 703 } 704 705 void ScrollEndCallback(bool nestedScroll, float velocity); 706 GetChildrenExpandedSize()707 virtual SizeF GetChildrenExpandedSize() 708 { 709 return SizeF(); 710 } 711 712 SizeF GetViewSizeMinusPadding(); 713 714 protected: 715 void SuggestOpIncGroup(bool flag); 716 void OnDetachFromFrameNode(FrameNode* frameNode) override; GetDefaultScrollBarDisplayMode()717 virtual DisplayMode GetDefaultScrollBarDisplayMode() const 718 { 719 return DisplayMode::AUTO; 720 } GetScrollBar()721 RefPtr<ScrollBar> GetScrollBar() const 722 { 723 return scrollBar_; 724 } 725 void UpdateScrollBarRegion(float offset, float estimatedHeight, Size viewPort, Offset viewOffset); 726 727 EdgeEffect GetEdgeEffect() const; SetEdgeEffect()728 void SetEdgeEffect() 729 { 730 SetEdgeEffect(edgeEffect_); 731 } 732 733 virtual void FireOnScroll(float finalOffset, OnScrollEvent& onScroll) const; 734 735 void FireObserverOnTouch(const TouchEventInfo& info); 736 void FireObserverOnPanActionEnd(GestureEvent& info); 737 void FireObserverOnReachStart(); 738 void FireObserverOnReachEnd(); 739 void FireObserverOnScrollStart(); 740 void FireObserverOnScrollStop(); 741 void FireObserverOnDidScroll(float finalOffset); 742 743 virtual void OnScrollStop(const OnScrollStopEvent& onScrollStop); 744 745 float FireOnWillScroll(float offset) const; 746 747 // select with mouse 748 struct ItemSelectedStatus { 749 std::function<void(bool)> onSelected; 750 std::function<void(bool)> selectChangeEvent; 751 RectF rect; 752 bool selected = false; FireSelectChangeEventItemSelectedStatus753 void FireSelectChangeEvent(bool isSelected) 754 { 755 if (selected == isSelected) { 756 return; 757 } 758 selected = isSelected; 759 if (onSelected) { 760 onSelected(isSelected); 761 } 762 if (selectChangeEvent) { 763 selectChangeEvent(isSelected); 764 } 765 } 766 }; 767 void InitMouseEvent(); 768 void UninitMouseEvent(); 769 void DrawSelectedZone(const RectF& selectedZone); 770 void ClearSelectedZone(); 771 bool multiSelectable_ = false; 772 bool isMouseEventInit_ = false; 773 OffsetF mouseStartOffset_; 774 float totalOffsetOfMousePressed_ = 0.0f; 775 std::unordered_map<int32_t, ItemSelectedStatus> itemToBeSelected_; 776 bool animateOverScroll_ = false; 777 bool animateCanOverScroll_ = false; 778 GetScrollBarOverlayModifier()779 RefPtr<ScrollBarOverlayModifier> GetScrollBarOverlayModifier() const 780 { 781 return scrollBarOverlayModifier_; 782 } 783 SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier)784 void SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier) 785 { 786 scrollBarOverlayModifier_ = scrollBarOverlayModifier; 787 } 788 // just for hold ScrollableController 789 RefPtr<ScrollableController> positionController_; 790 791 bool scrollStop_ = false; 792 793 // for onReachStart of the first layout 794 bool isInitialized_ = false; 795 796 void Register2DragDropManager(); 797 SetScrollOriginChild(const WeakPtr<NestableScrollContainer> & scrollOriginChild)798 void SetScrollOriginChild(const WeakPtr<NestableScrollContainer>& scrollOriginChild) 799 { 800 scrollOriginChild_ = scrollOriginChild; 801 } 802 GetScrollOriginChild()803 RefPtr<NestableScrollContainer> GetScrollOriginChild() 804 { 805 return scrollOriginChild_.Upgrade(); 806 } 807 808 void SetCanOverScroll(bool val); 809 bool GetCanOverScroll() const; 810 bool lastCanOverScroll_ = false; 811 812 void CheckScrollBarOff(); 813 814 private: OnScrollEndCallback()815 virtual void OnScrollEndCallback() {}; 816 817 void RegisterScrollBarEventTask(); 818 bool OnScrollPosition(double& offset, int32_t source); 819 void ProcessNavBarReactOnStart(); 820 float ProcessNavBarReactOnUpdate(float offset); 821 void ProcessNavBarReactOnEnd(); 822 void InitSpringOffsetProperty(); 823 void InitCurveOffsetProperty(); 824 void OnAnimateFinish(); 825 void StopAnimation(std::shared_ptr<AnimationUtils::Animation> animation); 826 void PauseAnimation(std::shared_ptr<AnimationUtils::Animation> animation); 827 void InitOption(AnimationOption &option, float duration, const RefPtr<Curve>& curve); 828 float GetScrollDelta(float offset, bool& stopAnimation); 829 830 void OnAttachToFrameNode() override; 831 void AttachAnimatableProperty(RefPtr<Scrollable> scrollable); 832 void InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub); 833 void RegisterWindowStateChangedCallback(); 834 835 // select with mouse MultiSelectWithoutKeyboard(const RectF & selectedZone)836 virtual void MultiSelectWithoutKeyboard(const RectF& selectedZone) {}; ClearMultiSelect()837 virtual void ClearMultiSelect() {}; IsItemSelected(const GestureEvent & info)838 virtual bool IsItemSelected(const GestureEvent& info) 839 { 840 return false; 841 } 842 void ClearInvisibleItemsSelectedStatus(); 843 void HandleInvisibleItemsSelectedStatus(const RectF& selectedZone); 844 void HandleDragStart(const GestureEvent& info); 845 void HandleDragUpdate(const GestureEvent& info); 846 void HandleDragEnd(); 847 void SelectWithScroll(); 848 RectF ComputeSelectedZone(const OffsetF& startOffset, const OffsetF& endOffset); 849 float GetOutOfScrollableOffset() const; 850 virtual float GetOffsetWithLimit(float offset) const; 851 void LimitMouseEndOffset(); 852 void UpdateBorderRadius(); 853 854 /****************************************************************************** 855 * NestableScrollContainer implementations 856 */ 857 ScrollResult HandleScroll( 858 float offset, int32_t source, NestedState state = NestedState::GESTURE, float velocity = 0.f) override; 859 bool HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child = nullptr) override; 860 861 void RemainVelocityToChild(float remainVelocity) override; NestedScrollOutOfBoundary()862 bool NestedScrollOutOfBoundary() override 863 { 864 return OutBoundaryCallback(); 865 } 866 void UpdateNestedScrollVelocity(float offset, NestedState state); 867 float GetNestedScrollVelocity(); 868 869 void OnScrollEndRecursive(const std::optional<float>& velocity) override; 870 void OnScrollEndRecursiveInner(const std::optional<float>& velocity); 871 void OnScrollStartRecursive(WeakPtr<NestableScrollContainer> child, float position, float velocity = 0.f) override; 872 void OnScrollStartRecursiveInner(WeakPtr<NestableScrollContainer> child, float position, float velocity = 0.f); 873 void OnScrollDragEndRecursive() override; 874 void StopScrollAnimation() override; 875 876 ScrollResult HandleScrollParentFirst(float& offset, int32_t source, NestedState state); 877 ScrollResult HandleScrollSelfFirst(float& offset, int32_t source, NestedState state); 878 ScrollResult HandleScrollSelfOnly(float& offset, int32_t source, NestedState state); 879 ScrollResult HandleScrollParallel(float& offset, int32_t source, NestedState state); 880 bool HandleOutBoundary(float& offset, int32_t source, NestedState state, ScrollResult& result); 881 bool HandleSelfOutBoundary(float& offset, int32_t source, const float backOverOffset, float oppositeOverOffset); 882 883 void ExecuteScrollFrameBegin(float& mainDelta, ScrollState state); 884 885 void OnScrollEnd(); 886 void ProcessSpringEffect(float velocity, bool needRestart = false); 887 void SetEdgeEffect(EdgeEffect edgeEffect); 888 889 // Scrollable::UpdateScrollPosition 890 bool HandleScrollImpl(float offset, int32_t source); 891 void NotifyMoved(bool value); 892 893 /* 894 * End of NestableScrollContainer implementations 895 *******************************************************************************/ 896 897 bool HandleOverScroll(float velocity); 898 bool HandleScrollableOverScroll(float velocity); 899 CreateRefreshCoordination()900 void CreateRefreshCoordination() 901 { 902 if (!refreshCoordination_) { 903 auto host = GetHost(); 904 CHECK_NULL_VOID(host); 905 refreshCoordination_ = AceType::MakeRefPtr<RefreshCoordination>(host); 906 } 907 } 908 float GetVelocity() const; 909 bool NeedSplitScroll(OverScrollOffset& overOffsets, int32_t source); 910 RefreshCoordinationMode CoordinateWithRefresh(double& offset, int32_t source, bool isAtTop); 911 bool CoordinateWithNavigation(double& offset, int32_t source, bool isAtTop); 912 void NotifyFRCSceneInfo(const std::string& scene, double velocity, SceneStatus sceneStatus); 913 ModalSheetCoordinationMode CoordinateWithSheet(double& offset, int32_t source, bool isAtTop); 914 bool NeedCoordinateScrollWithNavigation(double offset, int32_t source, const OverScrollOffset& overOffsets); 915 void SetUiDvsyncSwitch(bool on); 916 void SetNestedScrolling(bool nestedScrolling); 917 918 Axis axis_ = Axis::VERTICAL; 919 RefPtr<ScrollableEvent> scrollableEvent_; 920 RefPtr<TouchEventImpl> touchEvent_; 921 RefPtr<ScrollEdgeEffect> scrollEffect_; 922 RefPtr<RefreshCoordination> refreshCoordination_; 923 int32_t scrollSource_ = SCROLL_FROM_NONE; 924 int32_t lastScrollSource_ = SCROLL_FROM_NONE; 925 // scrollBar 926 RefPtr<ScrollBar> scrollBar_; 927 RefPtr<NG::ScrollBarProxy> scrollBarProxy_; 928 std::list<WeakPtr<NG::ScrollBarProxy>> nestScrollBarProxy_; 929 RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_; 930 float barOffset_ = 0.0f; 931 float estimatedHeight_ = 0.0f; 932 bool isReactInParentMovement_ = false; 933 bool isRefreshInReactive_ = false; // true if Refresh component is ready to receive scroll offset. 934 bool isSheetInReactive_ = false; 935 bool isCoordEventNeedSpring_ = true; 936 double scrollBarOutBoundaryExtent_ = 0.0; 937 double friction_ = 0.0; 938 double maxFlingVelocity_ = MAX_VELOCITY; 939 // scroller 940 RefPtr<Animator> animator_; 941 bool scrollAbort_ = false; 942 bool isAnimateOverScroll_ = false; 943 bool isScrollToSafeAreaHelper_ = true; 944 bool inScrollingStatus_ = false; 945 bool switchOnStatus_ = false; 946 947 float startPercent_ = 0.0f; 948 float endPercent_ = 1.0f; 949 void UpdateFadeInfo( 950 bool isFadingTop, bool isFadingBottom, float fadeFrameSize, const RefPtr<ScrollablePaintMethod>& paint); 951 952 // select with mouse 953 enum SelectDirection { SELECT_DOWN, SELECT_UP, SELECT_NONE }; 954 SelectDirection selectDirection_ = SELECT_NONE; 955 bool mousePressed_ = false; 956 bool canMultiSelect_ = false; 957 OffsetF mouseEndOffset_; 958 OffsetF mousePressOffset_; 959 OffsetF lastMouseStart_; 960 GestureEvent lastMouseMove_; 961 RefPtr<SelectMotion> selectMotion_; 962 RefPtr<PanEvent> boxSelectPanEvent_; 963 964 RefPtr<NavBarPattern> navBarPattern_; 965 RefPtr<SheetPresentationPattern> sheetPattern_; 966 std::vector<RefPtr<ScrollingListener>> scrollingListener_; 967 968 EdgeEffect edgeEffect_ = EdgeEffect::NONE; 969 bool edgeEffectAlwaysEnabled_ = false; 970 bool needLinked_ = true; 971 972 RefPtr<NodeAnimatablePropertyFloat> springOffsetProperty_; 973 RefPtr<NodeAnimatablePropertyFloat> curveOffsetProperty_; 974 std::shared_ptr<AnimationUtils::Animation> springAnimation_; 975 std::shared_ptr<AnimationUtils::Animation> curveAnimation_; 976 uint64_t lastVsyncTime_ = 0; 977 bool isAnimationStop_ = true; // graphic animation flag 978 float currentVelocity_ = 0.0f; 979 float lastPosition_ = 0.0f; 980 float finalPosition_ = 0.0f; 981 bool useTotalOffset_ = true; 982 bool animateToTraceFlag_ = false; 983 std::optional<float> extraOffset_; 984 985 RefPtr<Animator> hotzoneAnimator_; 986 float lastHonezoneOffsetPct_ = 0.0f; 987 RefPtr<BezierVariableVelocityMotion> velocityMotion_; 988 RefPtr<VelocityMotion> fixedVelocityMotion_; 989 std::function<void(void)> hotZoneScrollCallback_; 990 void UnRegister2DragDropManager(); 991 float IsInHotZone(const PointF& point); 992 void HotZoneScroll(const float offset); 993 void StopHotzoneScroll(); 994 void HandleHotZone(const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent); 995 bool isVertical() const; 996 Offset locationInfo_; 997 WeakPtr<NestableScrollContainer> scrollOriginChild_; 998 float nestedScrollVelocity_ = 0.0f; 999 uint64_t nestedScrollTimestamp_ = 0; 1000 bool prevHasFadingEdge_ = false; 1001 1002 RefPtr<ClickRecognizer> clickRecognizer_; 1003 // dump info 1004 std::list<ScrollableEventsFiredInfo> eventsFiredInfos_; 1005 std::list<ScrollableFrameInfo> scrollableFrameInfos_; 1006 RefPtr<InputEvent> mouseEvent_; 1007 bool isMousePressed_ = false; 1008 }; 1009 } // namespace OHOS::Ace::NG 1010 1011 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H 1012