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