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