1 /* 2 * Copyright (c) 2022 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_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H 18 19 #include <cstdint> 20 #include <optional> 21 22 #include "base/geometry/axis.h" 23 #include "base/geometry/ng/offset_t.h" 24 #include "base/memory/referenced.h" 25 #include "core/components_ng/layout/layout_algorithm.h" 26 #include "core/components_ng/layout/layout_wrapper.h" 27 #include "core/components_ng/pattern/swiper/swiper_layout_property.h" 28 29 namespace OHOS::Ace::NG { 30 31 struct SwiperItemInfo { 32 float startPos = 0.0f; 33 float endPos = 0.0f; 34 RefPtr<FrameNode> node = nullptr; 35 OffsetF finalOffset = OffsetF(); 36 CancelableCallback<void()> task = CancelableCallback<void()>(); 37 bool isFinishAnimation = false; 38 }; 39 40 class ACE_EXPORT SwiperLayoutAlgorithm : public LayoutAlgorithm { 41 DECLARE_ACE_TYPE(SwiperLayoutAlgorithm, LayoutAlgorithm); 42 43 public: 44 using PositionMap = std::map<int32_t, SwiperItemInfo>; 45 46 SwiperLayoutAlgorithm() = default; ~SwiperLayoutAlgorithm()47 ~SwiperLayoutAlgorithm() override 48 { 49 std::lock_guard<std::mutex> lock(swiperMutex_); 50 } 51 OnReset()52 void OnReset() override {} 53 void Measure(LayoutWrapper* layoutWrapper) override; 54 void Layout(LayoutWrapper* layoutWrapper) override; 55 SetItemsPosition(const PositionMap & itemPosition)56 void SetItemsPosition(const PositionMap& itemPosition) 57 { 58 itemPosition_ = itemPosition; 59 } 60 GetItemPosition()61 PositionMap&& GetItemPosition() 62 { 63 return std::move(itemPosition_); 64 } 65 SetJumpIndex(int32_t index)66 void SetJumpIndex(int32_t index) 67 { 68 jumpIndex_ = index; 69 } 70 SetCurrentDelta(float offset)71 void SetCurrentDelta(float offset) 72 { 73 currentDelta_ = offset; 74 currentOffset_ = offset; 75 } 76 SetOverScrollFeature()77 void SetOverScrollFeature() 78 { 79 overScrollFeature_ = true; 80 } 81 SetCanOverScroll(bool canOverScroll)82 void SetCanOverScroll(bool canOverScroll) 83 { 84 canOverScroll_ = canOverScroll; 85 } 86 SetTotalItemCount(int32_t totalItemCount)87 void SetTotalItemCount(int32_t totalItemCount) 88 { 89 totalItemCount_ = totalItemCount; 90 } 91 GetContentMainSize()92 float GetContentMainSize() const 93 { 94 return contentMainSize_; 95 } 96 SetContentMainSize(float contentMainSize)97 void SetContentMainSize(float contentMainSize) 98 { 99 contentMainSize_ = contentMainSize; 100 oldContentMainSize_ = contentMainSize; 101 } 102 GetContentCrossSize()103 float GetContentCrossSize() const 104 { 105 return contentCrossSize_; 106 } 107 SetCurrentOffset(float offset)108 void SetCurrentOffset(float offset) 109 { 110 currentOffset_ = offset; 111 } 112 GetCurrentOffset()113 float GetCurrentOffset() const 114 { 115 return currentOffset_; 116 } 117 SetTargetIndex(std::optional<int32_t> targetIndex)118 void SetTargetIndex(std::optional<int32_t> targetIndex) 119 { 120 targetIndex_ = targetIndex; 121 } 122 SetIsLoop(bool isLoop)123 void SetIsLoop(bool isLoop) 124 { 125 isLoop_ = isLoop; 126 } 127 GetStartIndex()128 int32_t GetStartIndex() const 129 { 130 return itemPosition_.empty() ? 0 : itemPosition_.begin()->first; 131 } 132 GetEndIndex()133 int32_t GetEndIndex() const 134 { 135 return itemPosition_.empty() ? 0 : itemPosition_.rbegin()->first; 136 } 137 GetStartPosition()138 float GetStartPosition() const 139 { 140 if (itemPosition_.empty()) { 141 return 0.0f; 142 } 143 if (GetStartIndex() == 0 && !isLoop_) { 144 return itemPosition_.begin()->second.startPos; 145 } 146 return itemPosition_.begin()->second.startPos - spaceWidth_; 147 } 148 GetEndPosition()149 float GetEndPosition() const 150 { 151 if (itemPosition_.empty()) { 152 return 0.0f; 153 } 154 if (GetEndIndex() == totalItemCount_ - 1 && !isLoop_) { 155 return itemPosition_.rbegin()->second.endPos; 156 } 157 return itemPosition_.rbegin()->second.endPos + spaceWidth_; 158 } 159 SetMainSizeIsMeasured(bool mainSizeIsMeasured)160 void SetMainSizeIsMeasured(bool mainSizeIsMeasured) 161 { 162 mainSizeIsMeasured_ = mainSizeIsMeasured; 163 } 164 GetMainSizeIsMeasured()165 bool GetMainSizeIsMeasured() const 166 { 167 return mainSizeIsMeasured_; 168 } 169 SetCurrentIndex(int32_t currentIndex)170 void SetCurrentIndex(int32_t currentIndex) 171 { 172 currentIndex_ = currentIndex; 173 } 174 GetCurrentIndex()175 int32_t GetCurrentIndex() const 176 { 177 return currentIndex_; 178 } 179 IsCrossMatchChild()180 bool IsCrossMatchChild() const 181 { 182 return crossMatchChild_; 183 } 184 SetUseCustomAnimation(bool useCustomAnimation)185 void SetUseCustomAnimation(bool useCustomAnimation) 186 { 187 useCustomAnimation_ = useCustomAnimation; 188 } 189 SetCustomAnimationToIndex(std::optional<int32_t> customAnimationToIndex)190 void SetCustomAnimationToIndex(std::optional<int32_t> customAnimationToIndex) 191 { 192 customAnimationToIndex_ = customAnimationToIndex; 193 } 194 SetRemoveFromRSTreeIndex(std::optional<int32_t> removeFromRSTreeIndex)195 void SetRemoveFromRSTreeIndex(std::optional<int32_t> removeFromRSTreeIndex) 196 { 197 removeFromRSTreeIndex_ = removeFromRSTreeIndex; 198 } 199 SetIndexsInAnimation(const std::set<int32_t> & indexsInAnimation)200 void SetIndexsInAnimation(const std::set<int32_t>& indexsInAnimation) 201 { 202 indexsInAnimation_ = indexsInAnimation; 203 } 204 SetNeedUnmountIndexs(const std::set<int32_t> & needUnmountIndexs)205 void SetNeedUnmountIndexs(const std::set<int32_t>& needUnmountIndexs) 206 { 207 needUnmountIndexs_ = needUnmountIndexs; 208 } 209 GetNeedUnmountIndexs()210 std::set<int32_t> GetNeedUnmountIndexs() const 211 { 212 return needUnmountIndexs_; 213 } 214 SetSwipeByGroup(bool swipeByGroup)215 void SetSwipeByGroup(bool swipeByGroup) 216 { 217 swipeByGroup_ = swipeByGroup; 218 } 219 SetRealTotalCount(int32_t realTotalCount)220 void SetRealTotalCount(int32_t realTotalCount) 221 { 222 realTotalCount_ = realTotalCount; 223 } 224 SetPlaceItemWidth(std::optional<float> placeItemWidth)225 void SetPlaceItemWidth(std::optional<float> placeItemWidth) 226 { 227 placeItemWidth_ = placeItemWidth; 228 } 229 SetHasCachedCapture(bool hasCachedCapture)230 void SetHasCachedCapture(bool hasCachedCapture) 231 { 232 hasCachedCapture_ = hasCachedCapture; 233 } 234 SetIsCaptureReverse(bool isCaptureReverse)235 void SetIsCaptureReverse(bool isCaptureReverse) 236 { 237 isCaptureReverse_ = isCaptureReverse; 238 } 239 GetIsCaptureReverse()240 bool GetIsCaptureReverse() const 241 { 242 return isCaptureReverse_; 243 } 244 GetIsNeedUpdateCapture()245 bool GetIsNeedUpdateCapture() const 246 { 247 return isNeedUpdateCapture_; 248 } 249 SetItemsPositionInAnimation(const PositionMap & itemPositionInAnimation)250 void SetItemsPositionInAnimation(const PositionMap& itemPositionInAnimation) 251 { 252 itemPositionInAnimation_ = itemPositionInAnimation; 253 } 254 GetItemsPositionInAnimation()255 PositionMap&& GetItemsPositionInAnimation() 256 { 257 return std::move(itemPositionInAnimation_); 258 } 259 SetIsMeasureOneMoreItem(bool isMeasureOneMoreItem)260 void SetIsMeasureOneMoreItem(bool isMeasureOneMoreItem) 261 { 262 isMeasureOneMoreItem_ = isMeasureOneMoreItem; 263 } 264 SetIsFrameAnimation(bool isFrameAnimation)265 void SetIsFrameAnimation(bool isFrameAnimation) 266 { 267 isFrameAnimation_ = isFrameAnimation; 268 } 269 GetTargetStartPos()270 float GetTargetStartPos() const 271 { 272 return targetStartPos_; 273 } 274 SetCachedCount(int32_t cachedCount)275 void SetCachedCount(int32_t cachedCount) 276 { 277 cachedCount_ = cachedCount > realTotalCount_ ? realTotalCount_ : cachedCount; 278 } 279 GetCachedItems()280 const std::set<int32_t>& GetCachedItems() const 281 { 282 return cachedItems_; 283 } 284 GetLayoutConstraint()285 const LayoutConstraintF& GetLayoutConstraint() const 286 { 287 return childLayoutConstraint_; 288 } 289 GetIgnoreBlankOffset()290 float GetIgnoreBlankOffset() const 291 { 292 return ignoreBlankOffset_; 293 } 294 SetIgnoreBlankOffset(float ignoreBlankOffset)295 void SetIgnoreBlankOffset(float ignoreBlankOffset) 296 { 297 ignoreBlankOffset_ = ignoreBlankOffset; 298 } 299 SetDuringInteraction(bool duringInteraction)300 void SetDuringInteraction(bool duringInteraction) 301 { 302 duringInteraction_ = duringInteraction; 303 } 304 GetJumpIndex()305 std::optional<int32_t> GetJumpIndex() const 306 { 307 return jumpIndex_; 308 } 309 SetCachedShow(bool cachedShow)310 void SetCachedShow(bool cachedShow) 311 { 312 cachedShow_ = cachedShow; 313 } 314 315 private: 316 void LayoutForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex, 317 float startPos, bool cachedLayout = false); 318 void LayoutBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t endIndex, 319 float endPos, bool cachedLayout = false); 320 bool LayoutForwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 321 int32_t& currentIndex, float startPos, float& endPos); 322 bool LayoutBackwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 323 int32_t& currentIndex, float endPos, float& startPos); 324 float GetChildMaxSize(LayoutWrapper* layoutWrapper, bool isMainAxis) const; 325 int32_t GetLoopIndex(int32_t originalIndex) const; 326 327 void LayoutSwiperIndicator( 328 LayoutWrapper* layoutWrapper, const RefPtr<SwiperLayoutProperty>& swiperLayoutProperty, 329 const PaddingPropertyF& padding); 330 void MeasureSwiper(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint); 331 void MeasureTabsCustomAnimation(LayoutWrapper* layoutWrapper); 332 void MeasureSwiperCustomAnimation(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint); 333 void LayoutCustomAnimation(LayoutWrapper* layoutWrapper) const; 334 void LayoutItem(LayoutWrapper* layoutWrapper, OffsetF offset, std::pair<int32_t, SwiperItemInfo> pos); 335 void SetInactive( 336 LayoutWrapper* layoutWrapper, float startMainPos, float endMainPos, std::optional<int32_t> targetIndex); 337 338 void PlaceDigitChild(const RefPtr<LayoutWrapper>& indicatorWrapper, const RefPtr<LayoutProperty>& layoutProperty); 339 RefPtr<LayoutWrapper> GetNodeLayoutWrapperByTag(LayoutWrapper* layoutWrapper, const std::string& tagName) const; 340 void MeasureArrow(const RefPtr<LayoutWrapper>& arrowWrapper, const RefPtr<LayoutProperty>& layoutProperty) const; 341 void ArrowLayout( 342 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& arrowWrapper, const PaddingPropertyF padding) const; 343 void ResetOffscreenItemPosition(LayoutWrapper* layoutWrapper, int32_t index, bool isForward) const; 344 int32_t GetDisplayCount(LayoutWrapper* layoutWrapper) const; 345 void SetInactiveOnForward(LayoutWrapper* layoutWrapper); 346 void SetInactiveOnBackward(LayoutWrapper* layoutWrapper); 347 void AdjustStartInfoOnSwipeByGroup( 348 int32_t startIndex, const PositionMap& itemPosition, int32_t& startIndexInVisibleWindow, float& startPos); 349 bool HasCustomIndicatorOffset(const RefPtr<LayoutWrapper>& indicatorWrapper); 350 const OffsetF CalculateCustomOffset( 351 const RefPtr<LayoutWrapper>& indicatorWrapper, const OffsetF& currentOffset); 352 void CaptureMeasure(LayoutWrapper* layoutWrapper, LayoutConstraintF& childLayoutConstraint); 353 void CaptureLayout(LayoutWrapper* layoutWrapper); 354 bool IsNormalItem(const RefPtr<LayoutWrapper>& wrapper) const; 355 void UpdateLayoutInfoBeforeMeasureSwiper( 356 const RefPtr<SwiperLayoutProperty>& property, const LayoutConstraintF& layoutConstraint); 357 void IndicatorAndArrowMeasure(LayoutWrapper* layoutWrapper, const OptionalSizeF& parentIdealSize); 358 float GetChildMainAxisSize( 359 const RefPtr<LayoutWrapper>& childWrapper, const RefPtr<SwiperLayoutProperty>& swiperProperty); 360 361 void CheckCachedItem(int32_t startIndex, int32_t endIndex, LayoutWrapper* layoutWrapper); 362 void MeasureSwiperOnJump(LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint, int32_t jumpIndex); 363 bool NeedMeasureForward(int32_t currentIndex, float currentEndPos, float forwardEndPos, bool cachedLayout) const; 364 bool NeedMeasureBackward( 365 int32_t currentIndex, float currentStartPos, float backwardStartPos, bool isStretch, bool cachedLayout) const; 366 void CalcCachedItemIndex(LayoutWrapper* layoutWrapper); 367 int32_t GetCurrentFirstIndexInWindow(LayoutWrapper* layoutWrapper) const; 368 int32_t GetCurrentLastIndexInWindow(LayoutWrapper* layoutWrapper) const; 369 void LayoutCachedItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint); 370 int32_t GetUserSetCachedCount(LayoutWrapper* layoutWrapper) const; 371 void AdjustItemPositionOnCachedShow(); 372 void AdjustOffsetOnForward(float currentEndPos); 373 void AdjustOffsetOnBackward(float currentStartPos); 374 float GetHeightForDigit(LayoutWrapper* layoutWrapper, float height) const; 375 376 bool isLoop_ = true; 377 float prevMargin_ = 0.0f; 378 float nextMargin_ = 0.0f; 379 380 PositionMap itemPosition_; 381 PositionMap prevItemPosition_; 382 PositionMap itemPositionInAnimation_; 383 float currentOffset_ = 0.0f; 384 float currentDelta_ = 0.0f; 385 float startMainPos_ = 0.0f; 386 float endMainPos_ = 0.0f; 387 388 float paddingBeforeContent_ = 0.0f; 389 float paddingAfterContent_ = 0.0f; 390 float contentMainSize_ = 0.0f; 391 float oldContentMainSize_ = 0.0f; 392 float contentCrossSize_ = 0.0f; 393 int32_t totalItemCount_ = 0; 394 bool mainSizeIsDefined_ = false; 395 396 float spaceWidth_ = 0.0f; 397 bool overScrollFeature_ = false; 398 bool canOverScroll_ = false; 399 400 bool mainSizeIsMeasured_ = false; 401 bool crossMatchChild_ = false; 402 bool measured_ = false; // to distinguish first and second measure in flex layout 403 bool duringInteraction_ = false; // user interacting, include touching and translating animation. 404 405 std::optional<int32_t> jumpIndex_; 406 std::optional<int32_t> targetIndex_; 407 std::optional<int32_t> currentJumpIndex_; 408 std::optional<int32_t> currentTargetIndex_; 409 std::optional<int32_t> customAnimationToIndex_; 410 std::optional<int32_t> removeFromRSTreeIndex_; 411 std::optional<SizeF> leftCaptureSize_ = std::nullopt; 412 std::optional<SizeF> rightCaptureSize_ = std::nullopt; 413 int32_t currentIndex_ = 0; 414 bool targetIsSameWithStartFlag_ = false; 415 bool useCustomAnimation_ = false; 416 std::set<int32_t> indexsInAnimation_; 417 std::set<int32_t> needUnmountIndexs_; 418 bool swipeByGroup_ = false; 419 int32_t realTotalCount_ = 0; 420 std::optional<float> placeItemWidth_; 421 bool useCustomIndicatorOffset = false; 422 bool hasCachedCapture_ = false; 423 bool isCaptureReverse_ = false; 424 bool isNeedUpdateCapture_ = false; 425 bool isMeasureOneMoreItem_ = false; 426 bool isFrameAnimation_ = false; 427 float ignoreBlankOffset_ = 0.0f; 428 float currentIgnoreBlankOffset_ = 0.0f; 429 bool prevMarginIgnoreBlank_ = false; 430 std::set<int32_t> measuredItems_; 431 std::set<int32_t> activeItems_; 432 std::set<int32_t> cachedItems_; 433 // only be used in AutoLinear mode 434 float targetStartPos_ = 0.0f; 435 int32_t cachedCount_ = 0; 436 bool cachedShow_ = false; 437 int32_t cachedStartIndex_ = 0; 438 int32_t cachedEndIndex_ = 0; 439 LayoutConstraintF childLayoutConstraint_; 440 Axis axis_ = Axis::HORIZONTAL; 441 442 std::mutex swiperMutex_; 443 }; 444 445 } // namespace OHOS::Ace::NG 446 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H 447