1 /* 2 * Copyright (c) 2022-2023 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_LIST_LIST_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H 18 19 #include <tuple> 20 #include "core/animation/chain_animation.h" 21 #include "core/components_ng/pattern/list/list_accessibility_property.h" 22 #include "core/components_ng/pattern/list/list_children_main_size.h" 23 #include "core/components_ng/pattern/list/list_content_modifier.h" 24 #include "core/components_ng/pattern/list/list_event_hub.h" 25 #include "core/components_ng/pattern/list/list_item_pattern.h" 26 #include "core/components_ng/pattern/list/list_layout_algorithm.h" 27 #include "core/components_ng/pattern/list/list_layout_property.h" 28 #include "core/components_ng/pattern/list/list_paint_method.h" 29 #include "core/components_ng/pattern/list/list_position_map.h" 30 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h" 31 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h" 32 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 33 #include "core/components_ng/render/render_context.h" 34 #include "core/pipeline_ng/pipeline_context.h" 35 36 namespace OHOS::Ace::NG { 37 class InspectorFilter; 38 39 struct ListItemGroupPara { 40 int32_t lanes = -1; 41 int32_t itemEndIndex = -1; 42 int32_t displayStartIndex = -1; 43 int32_t displayEndIndex = -1; 44 }; 45 46 struct ListScrollTarget { 47 int32_t index = -1; 48 float extraOffset = 0.0f; 49 ScrollAlign align = ScrollAlign::START; 50 float targetOffset; 51 }; 52 53 class ListPattern : public ScrollablePattern { 54 DECLARE_ACE_TYPE(ListPattern, ScrollablePattern); 55 56 public: ListPattern()57 ListPattern() : ScrollablePattern(EdgeEffect::SPRING, false) {} 58 ~ListPattern() override = default; 59 60 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 61 CreateLayoutProperty()62 RefPtr<LayoutProperty> CreateLayoutProperty() override 63 { 64 return MakeRefPtr<ListLayoutProperty>(); 65 } 66 CreateEventHub()67 RefPtr<EventHub> CreateEventHub() override 68 { 69 return MakeRefPtr<ListEventHub>(); 70 } 71 CreateAccessibilityProperty()72 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 73 { 74 return MakeRefPtr<ListAccessibilityProperty>(); 75 } 76 UsResRegion()77 bool UsResRegion() override 78 { 79 return false; 80 } 81 82 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 83 84 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 85 86 void FromJson(const std::unique_ptr<JsonValue>& json) override; 87 88 bool UpdateCurrentOffset(float offset, int32_t source) override; 89 90 DisplayMode GetDefaultScrollBarDisplayMode() const override; 91 GetStartIndex()92 int32_t GetStartIndex() const 93 { 94 return startIndex_; 95 } 96 GetEndIndex()97 int32_t GetEndIndex() const 98 { 99 return endIndex_; 100 } 101 GetMaxListItemIndex()102 int32_t GetMaxListItemIndex() const 103 { 104 return maxListItemIndex_; 105 } 106 IsScrollable()107 bool IsScrollable() const override 108 { 109 return isScrollable_; 110 } 111 SetMaintainVisibleContentPosition(bool enabled)112 void SetMaintainVisibleContentPosition(bool enabled) 113 { 114 maintainVisibleContentPosition_ = enabled; 115 } 116 GetMaintainVisibleContentPosition()117 bool GetMaintainVisibleContentPosition() 118 { 119 return maintainVisibleContentPosition_; 120 } 121 MarkNeedReEstimateOffset()122 void MarkNeedReEstimateOffset() 123 { 124 needReEstimateOffset_ = true; 125 } 126 127 void NotifyDataChange(int32_t index, int32_t count) override; 128 129 bool IsAtTop() const override; 130 bool IsAtBottom() const override; 131 void OnTouchDown(const TouchEventInfo& info) override; 132 OverScrollOffset GetOutBoundaryOffset(float delta, bool useChainDelta = true) const; 133 OverScrollOffset GetOverScrollOffset(double delta) const override; 134 float GetOffsetWithLimit(float offset) const override; 135 void HandleScrollBarOutBoundary(); 136 GetFocusPattern()137 FocusPattern GetFocusPattern() const override 138 { 139 return { FocusType::SCOPE, true }; 140 } 141 GetScopeFocusAlgorithm()142 ScopeFocusAlgorithm GetScopeFocusAlgorithm() override 143 { 144 auto property = GetLayoutProperty<ListLayoutProperty>(); 145 if (!property) { 146 return {}; 147 } 148 return ScopeFocusAlgorithm(property->GetListDirection().value_or(Axis::VERTICAL) == Axis::VERTICAL, true, 149 ScopeType::OTHERS, 150 [wp = WeakClaim(this)]( 151 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) -> bool { 152 auto list = wp.Upgrade(); 153 if (list) { 154 nextFocusNode = list->GetNextFocusNode(step, currFocusNode); 155 } 156 return nextFocusNode.Upgrade() != currFocusNode.Upgrade(); 157 }); 158 } 159 160 ScrollOffsetAbility GetScrollOffsetAbility() override; 161 162 std::function<bool(int32_t)> GetScrollIndexAbility() override; 163 164 bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override; 165 GetItemPosition()166 const ListLayoutAlgorithm::PositionMap& GetItemPosition() const 167 { 168 return itemPosition_; 169 } 170 GetTotalOffset()171 float GetTotalOffset() const override 172 { 173 return currentOffset_; 174 } 175 GetContentStartOffset()176 float GetContentStartOffset() const override 177 { 178 return contentStartOffset_; 179 } 180 GetPositionController()181 RefPtr<ScrollControllerBase> GetPositionController() const 182 { 183 return positionController_; 184 } 185 186 int32_t ProcessAreaVertical(double& x, double& y, Rect& groupRect, int32_t& index, 187 RefPtr<ListItemGroupPattern> groupItemPattern) const; 188 int32_t ProcessAreaHorizontal(double& x, double& y, Rect& groupRect, int32_t& index, 189 RefPtr<ListItemGroupPattern> groupItemPattern) const; 190 void TriggerModifyDone(); 191 192 float GetTotalHeight() const override; 193 194 // scroller 195 void ScrollTo(float position) override; 196 void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, 197 std::optional<float> extraOffset = std::nullopt) override; 198 void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false, 199 ScrollAlign align = ScrollAlign::START); 200 bool CheckTargetValid(int32_t index, int32_t indexInGroup); 201 void ScrollPage(bool reverse, bool smooth = false, 202 AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL) override; 203 void ScrollBy(float offset); 204 bool AnimateToTarget(int32_t index, std::optional<int32_t> indexInGroup, ScrollAlign align); 205 Offset GetCurrentOffset() const; 206 Rect GetItemRect(int32_t index) const override; 207 int32_t GetItemIndex(double x, double y) const override; 208 Rect GetItemRectInGroup(int32_t index, int32_t indexInGroup) const; 209 ListItemIndex GetItemIndexInGroup(double x, double y) const; 210 bool GetGroupItemIndex(double x, double y, RefPtr<FrameNode> itemFrameNode, int32_t& index, 211 ListItemIndex& itemIndex) const; 212 void OnAnimateStop() override; GetMainContentSize()213 float GetMainContentSize() const override 214 { 215 return contentMainSize_; 216 } GetLanes()217 int32_t GetLanes() const 218 { 219 return lanes_; 220 } 221 222 void UpdatePosMapStart(float delta); 223 void UpdatePosMapEnd(); 224 void CalculateCurrentOffset(float delta, const ListLayoutAlgorithm::PositionMap& recycledItemPosition); 225 void UpdateScrollBarOffset() override; 226 // chain animation 227 void SetChainAnimation(); 228 void SetChainAnimationOptions(const ChainAnimationOptions& options); 229 float FlushChainAnimation(float dragOffset); 230 void ProcessDragStart(float startPosition); 231 void ProcessDragUpdate(float dragOffset, int32_t source); 232 float GetChainDelta(int32_t index) const; 233 234 // multiSelectable SetMultiSelectable(bool multiSelectable)235 void SetMultiSelectable(bool multiSelectable) 236 { 237 multiSelectable_ = multiSelectable; 238 } 239 240 void SetSwiperItem(WeakPtr<ListItemPattern> swiperItem); GetSwiperItem()241 WeakPtr<ListItemPattern> GetSwiperItem() 242 { 243 if (!swiperItem_.Upgrade()) { 244 return nullptr; 245 } 246 return swiperItem_; 247 } SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)248 void SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem) 249 { 250 if (swiperItem == swiperItem_) { 251 canReplaceSwiperItem_ = true; 252 } 253 } IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)254 bool IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem) 255 { 256 if (!swiperItem_.Upgrade()) { 257 return true; 258 } 259 return swiperItem == swiperItem_; 260 } CanReplaceSwiperItem()261 bool CanReplaceSwiperItem() 262 { 263 auto listItemPattern = swiperItem_.Upgrade(); 264 if (!listItemPattern) { 265 canReplaceSwiperItem_ = true; 266 return canReplaceSwiperItem_; 267 } 268 auto host = listItemPattern->GetHost(); 269 if (!host || !host->IsOnMainTree()) { 270 canReplaceSwiperItem_ = true; 271 return canReplaceSwiperItem_; 272 } 273 return canReplaceSwiperItem_; 274 } 275 SetPredictSnapOffset(float predictSnapOffset)276 void SetPredictSnapOffset(float predictSnapOffset) 277 { 278 predictSnapOffset_ = predictSnapOffset; 279 } 280 bool OnScrollSnapCallback(double targetOffset, double velocity) override; 281 282 int32_t GetItemIndexByPosition(float xOffset, float yOffset); 283 SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)284 void SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param) 285 { 286 predictLayoutParam_ = param; 287 } GetPredictLayoutParam()288 std::optional<ListPredictLayoutParam> GetPredictLayoutParam() const 289 { 290 return predictLayoutParam_; 291 } 292 SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)293 void SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param) 294 { 295 predictLayoutParamV2_ = param; 296 } 297 GetPredictLayoutParamV2()298 std::optional<ListPredictLayoutParamV2> GetPredictLayoutParamV2() const 299 { 300 return predictLayoutParamV2_; 301 } 302 303 void CloseAllSwipeActions(OnFinishFunc&&); 304 305 std::string ProvideRestoreInfo() override; 306 void OnRestoreInfo(const std::string& restoreInfo) override; 307 void DumpAdvanceInfo() override; 308 SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)309 void SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection) 310 { 311 isNeedToUpdateListDirection_ = isNeedToUpdateListDirection; 312 } 313 IsNeedToUpdateListDirectionInCardStyle()314 bool IsNeedToUpdateListDirectionInCardStyle() const 315 { 316 return isNeedToUpdateListDirection_; 317 } 318 319 std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override; 320 SetItemPressed(bool isPressed,int32_t id)321 void SetItemPressed(bool isPressed, int32_t id) 322 { 323 if (isPressed) { 324 pressedItem_.emplace(id); 325 } else { 326 pressedItem_.erase(id); 327 } 328 } 329 330 RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize(); 331 void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize); 332 void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag); 333 void ResetChildrenSize(); ListChildrenSizeExist()334 bool ListChildrenSizeExist() 335 { 336 return static_cast<bool>(childrenSize_); 337 } CanOverScroll(int32_t source)338 bool CanOverScroll(int32_t source) override 339 { 340 auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR && 341 IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_) && 342 (IsAtBottom() || IsAtTop())); 343 if (canOverScroll != lastCanOverScroll_) { 344 lastCanOverScroll_ = canOverScroll; 345 AddScrollableFrameInfo(source); 346 } 347 return canOverScroll; 348 } 349 void UpdateChildPosInfo(int32_t index, float delta, float sizeChange); 350 351 SizeF GetChildrenExpandedSize() override; 352 private: 353 IsNeedInitClickEventRecorder()354 bool IsNeedInitClickEventRecorder() const override 355 { 356 return true; 357 } 358 359 void OnScrollEndCallback() override; 360 void FireOnReachStart(const OnReachEvent& onReachStart) override; 361 void FireOnReachEnd(const OnReachEvent& onReachEnd) override; 362 void FireOnScrollIndex(bool indexChanged, const OnScrollIndexEvent& onScrollIndex); 363 void OnModifyDone() override; 364 void ChangeAxis(RefPtr<UINode> node); 365 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 366 float CalculateTargetPos(float startPos, float endPos); 367 368 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 369 bool OnKeyEvent(const KeyEvent& event); 370 bool HandleDirectionKey(const KeyEvent& event); 371 WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode); 372 WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarGroupIndex); 373 WeakPtr<FocusHub> ScrollAndFindFocusNode(int32_t nextIndex, int32_t curIndex, int32_t& nextIndexInGroup, 374 int32_t curIndexInGroup, int32_t moveStep, FocusStep step); 375 bool ScrollListForFocus(int32_t nextIndex, int32_t curIndex, int32_t nextIndexInGroup); 376 bool ScrollListItemGroupForFocus(int32_t nextIndex, int32_t& nextIndexInGroup, int32_t curIndexInGroup, 377 int32_t moveStep, FocusStep step, bool isScrollIndex); 378 379 void MarkDirtyNodeSelf(); 380 SizeF GetContentSize() const; 381 void ProcessEvent(bool indexChanged, float finalOffset, bool isJump); 382 void CheckScrollable(); 383 bool IsOutOfBoundary(bool useCurrentDelta = true) override; 384 bool OnScrollCallback(float offset, int32_t source) override; 385 void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override; 386 void HandleScrollEffect(float offset); 387 void StartDefaultOrCustomSpringMotion(float start, float end, const RefPtr<InterpolatingSpring>& curve); 388 bool IsScrollSnapAlignCenter() const; 389 void SetChainAnimationCallback(); 390 void SetChainAnimationToPosMap(); 391 void SetChainAnimationLayoutAlgorithm( 392 RefPtr<ListLayoutAlgorithm> listLayoutAlgorithm, RefPtr<ListLayoutProperty> listLayoutProperty); 393 bool NeedScrollSnapAlignEffect() const; 394 ScrollAlign GetScrollAlignByScrollSnapAlign() const; 395 bool GetListItemAnimatePos(float startPos, float endPos, ScrollAlign align, float& targetPos); 396 bool GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, float startPos, float endPos, 397 ScrollAlign align, float& targetPos); 398 bool GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int32_t indexInGroup, float startPos, 399 ScrollAlign align, float& targetPos); 400 401 // multiSelectable 402 void ClearMultiSelect() override; 403 bool IsItemSelected(const GestureEvent& info) override; 404 void MultiSelectWithoutKeyboard(const RectF& selectedZone) override; 405 void HandleCardModeSelectedEvent( 406 const RectF& selectedZone, const RefPtr<FrameNode>& itemGroupNode, float itemGroupTop); 407 408 void DrivenRender(const RefPtr<LayoutWrapper>& layoutWrapper); 409 ListItemGroupPara GetListItemGroupParameter(const RefPtr<FrameNode>& node); 410 bool IsListItemGroup(int32_t listIndex, RefPtr<FrameNode>& node); 411 void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const; 412 void RefreshLanesItemRange(); 413 void UpdateListDirectionInCardStyle(); 414 bool UpdateStartListItemIndex(); 415 bool UpdateEndListItemIndex(); 416 float GetStartOverScrollOffset(float offset, float startMainPos) const; 417 float GetEndOverScrollOffset(float offset, float endMainPos, float startMainPos) const; 418 float UpdateTotalOffset(const RefPtr<ListLayoutAlgorithm>& listLayoutAlgorithm, bool isJump); 419 RefPtr<ListContentModifier> listContentModifier_; 420 421 int32_t maxListItemIndex_ = 0; 422 int32_t startIndex_ = -1; 423 int32_t endIndex_ = -1; 424 int32_t centerIndex_ = -1; 425 float startMainPos_ = 0.0f; 426 float endMainPos_ = 0.0f; 427 float prevStartOffset_ = 0.f; 428 float prevEndOffset_ = 0.f; 429 float currentOffset_ = 0.0f; 430 float spaceWidth_ = 0.0f; 431 float contentMainSize_ = 0.0f; 432 float contentStartOffset_ = 0.0f; 433 float contentEndOffset_ = 0.0f; 434 bool maintainVisibleContentPosition_ = false; 435 436 float currentDelta_ = 0.0f; 437 bool crossMatchChild_ = false; 438 bool smooth_ = false; 439 float scrollSnapVelocity_ = 0.0f; 440 bool snapTrigOnScrollStart_ = false; 441 442 std::optional<int32_t> jumpIndex_; 443 std::optional<int32_t> jumpIndexInGroup_; 444 std::optional<int32_t> targetIndex_; 445 std::optional<int32_t> targetIndexInGroup_; 446 std::optional<ListScrollTarget> scrollTarget_; 447 std::optional<float> predictSnapOffset_; 448 std::optional<float> predictSnapEndPos_; 449 ScrollAlign scrollAlign_ = ScrollAlign::START; 450 bool isScrollable_ = true; 451 bool paintStateFlag_ = false; 452 bool isFramePaintStateValid_ = false; 453 bool isNeedCheckOffset_ = false; 454 455 ListLayoutAlgorithm::PositionMap itemPosition_; 456 ListLayoutAlgorithm::PositionMap cachedItemPosition_; 457 RefPtr<ListPositionMap> posMap_; 458 RefPtr<ListChildrenMainSize> childrenSize_; 459 float listTotalHeight_ = 0.0f; 460 461 std::map<int32_t, int32_t> lanesItemRange_; 462 std::set<int32_t> pressedItem_; 463 int32_t lanes_ = 1; 464 float laneGutter_ = 0.0f; 465 // chain animation 466 RefPtr<ChainAnimation> chainAnimation_; 467 bool dragFromSpring_ = false; 468 RefPtr<SpringProperty> springProperty_; 469 std::optional<ChainAnimationOptions> chainAnimationOptions_; 470 471 bool isOritationListenerRegisted_ = false; 472 473 // ListItem swiperAction 474 WeakPtr<ListItemPattern> swiperItem_; 475 bool canReplaceSwiperItem_ = true; 476 477 RefPtr<SpringMotion> scrollToIndexMotion_; 478 RefPtr<SpringMotion> scrollSnapMotion_; 479 RefPtr<Scrollable> scrollable_; 480 481 bool isScrollEnd_ = false; 482 bool needReEstimateOffset_ = false; 483 std::optional<ListPredictLayoutParam> predictLayoutParam_; 484 std::optional<ListPredictLayoutParamV2> predictLayoutParamV2_; 485 486 bool isNeedToUpdateListDirection_ = false; 487 bool startIndexChanged_ = false; 488 bool endIndexChanged_ = false; 489 490 ListItemIndex startInfo_ = {-1, -1, -1}; 491 ListItemIndex endInfo_ = {-1, -1, -1}; 492 }; 493 } // namespace OHOS::Ace::NG 494 495 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H 496