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