1 /* 2 * Copyright (c) 2025 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_FREE_GESTURE_CONTROLLER_H 16 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_FREE_GESTURE_CONTROLLER_H 17 18 #include "core/components_ng/base/modifier.h" 19 #include "core/components_ng/gestures/recognizers/pan_recognizer.h" 20 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 21 22 namespace OHOS::Ace::NG { 23 class ScrollPattern; 24 class AxisAnimator; 25 enum class ScrollEdge; 26 27 /** 28 * @brief Controller for free scrolling behavior. It manages related gestures and animations. 29 * 30 */ 31 class FreeScrollController final : public AceType { 32 DECLARE_ACE_TYPE(FreeScrollController, AceType); 33 ACE_DISALLOW_COPY_AND_MOVE(FreeScrollController); 34 35 public: 36 explicit FreeScrollController(ScrollPattern& pattern); 37 ~FreeScrollController() final; 38 GetFreePanGesture()39 RefPtr<PanRecognizer> GetFreePanGesture() const 40 { 41 freePanGesture_->SetEnabled(enableScroll_); // workaround gesture's internal reset 42 return freePanGesture_; 43 } 44 45 /** 46 * @brief Allow other modules to modify offset. Calling this function automatically stops scroll animations. 47 */ 48 void SetOffset(OffsetF newPos, bool allowOverScroll = false); UpdateOffset(const OffsetF & delta)49 inline void UpdateOffset(const OffsetF& delta) 50 { 51 SetOffset(offset_->Get() + delta); 52 } 53 54 void OnLayoutFinished(const OffsetF& adjustedOffset, const SizeF& scrollableArea); 55 56 OffsetF GetOffset() const; GetLayoutOffset()57 const OffsetF& GetLayoutOffset() const 58 { 59 return actualOffset_; 60 } 61 62 /** 63 * @brief Start a scroll animation to the final position. 64 */ 65 void ScrollTo(OffsetF finalPos, const std::optional<float>& velocity, 66 std::optional<int32_t> duration = std::nullopt, RefPtr<Curve> curve = nullptr, bool allowOverScroll = false); 67 68 private: 69 void InitializePanRecognizer(); 70 void InitializeTouchEvent(); 71 72 void HandlePanStart(const GestureEvent& event); 73 void HandlePanUpdate(const GestureEvent& event); 74 void HandlePanEndOrCancel(const GestureEvent& event); 75 76 void HandleTouchDown(); 77 void HandleTouchUpOrCancel(); 78 79 /** 80 * @brief update callback of AnimatableProperty @c offset_. 81 */ 82 void HandleOffsetUpdate(const OffsetF& currentValue); 83 84 /** 85 * @brief Start the scroll animation if possible with the given velocity and offset_. 86 */ 87 void Fling(const OffsetF& velocity); 88 void StopScrollAnimation(); 89 void HandleAnimationEnd(); 90 91 /** 92 * @brief clamp position to be within the scrollable area. 93 */ 94 OffsetF ClampPosition(const OffsetF& finalPos) const; 95 96 /** 97 * @brief Check if the new offset would reach any edges. If so, fire corresponding user callbacks. 98 * @return true if any edge is reached, false otherwise. 99 */ 100 bool CheckCrashEdge(const OffsetF& newOffset, const SizeF& scrollableArea) const; 101 102 /** 103 * @brief triggers onWillScroll user callback 104 * @return user-modified delta 105 */ 106 OffsetF FireOnWillScroll(const OffsetF& delta, ScrollState state, ScrollSource source) const; 107 void FireOnDidScroll(const OffsetF& delta, ScrollState state) const; 108 void FireOnScrollStart() const; 109 void FireOnScrollEnd() const; 110 void FireOnScrollEdge(const std::vector<ScrollEdge>& edges) const; 111 112 void AnimateOnMouseScroll(const OffsetF& delta); 113 void HandleAxisAnimationFrame(float newOffset); 114 115 ScrollPattern& pattern_; 116 RefPtr<NodeAnimatablePropertyOffsetF> offset_; 117 OffsetF actualOffset_; // actual displayed offset, adjusted by LayoutAlgorithm 118 RefPtr<PanRecognizer> freePanGesture_; 119 RefPtr<TouchEventImpl> freeTouch_; 120 RefPtr<AxisAnimator> axisAnimator_; // to smooth out mouse wheel scrolls 121 122 public: 123 enum class State { 124 IDLE, 125 DRAG, 126 FLING, 127 EXTERNAL_FLING, // used for external animations like scroller animation 128 BOUNCE, // used for bounce animation transitioned from FLING when reaching edge 129 }; 130 131 private: 132 State state_ = State::IDLE; 133 bool enableScroll_ = true; 134 bool mouseWheelScrollIsVertical_ = true; 135 }; 136 137 } // namespace OHOS::Ace::NG 138 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_FREE_GESTURE_CONTROLLER_H 139