From 01d9ed63e33ba3491479605bdbcc701648e38774 Mon Sep 17 00:00:00 2001 From: caocan Date: Mon, 29 Aug 2022 21:29:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]Swi?= =?UTF-8?q?per=E7=BB=84=E4=BB=B6=E6=94=AF=E6=8C=81swipeTo=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: If2bbf55ef479c83d5828311a0cdad76b9a55f12a --- .../declarative_frontend/jsview/js_swiper.cpp | 3 +- .../declarative_frontend/jsview/js_swiper.h | 11 ++++ .../swiper/swiper_layout_algorithm.cpp | 23 +++++++- .../pattern/swiper/swiper_layout_algorithm.h | 12 +++++ .../pattern/swiper/swiper_pattern.cpp | 52 +++++++++++++++---- .../pattern/swiper/swiper_pattern.h | 5 ++ 6 files changed, 94 insertions(+), 12 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_swiper.cpp b/frameworks/bridge/declarative_frontend/jsview/js_swiper.cpp index a9c4a17e5af..c2c0bdd7e80 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_swiper.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_swiper.cpp @@ -637,9 +637,10 @@ void JSSwiper::SetSize(const JSCallbackInfo& info) void JSSwiperController::JSBind(BindingTarget globalObj) { JSClass::Declare("SwiperController"); + JSClass::CustomMethod("swipeTo", &JSSwiperController::SwipeTo); JSClass::CustomMethod("showNext", &JSSwiperController::ShowNext); - JSClass::CustomMethod("finishAnimation", &JSSwiperController::FinishAnimation); JSClass::CustomMethod("showPrevious", &JSSwiperController::ShowPrevious); + JSClass::CustomMethod("finishAnimation", &JSSwiperController::FinishAnimation); JSClass::Bind(globalObj, JSSwiperController::Constructor, JSSwiperController::Destructor); } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_swiper.h b/frameworks/bridge/declarative_frontend/jsview/js_swiper.h index c1f37f573fc..b8333d4cc8d 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_swiper.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_swiper.h @@ -64,6 +64,17 @@ public: static void Constructor(const JSCallbackInfo& args); static void Destructor(JSSwiperController* scroller); + void SwipeTo(const JSCallbackInfo& args) + { + if (args.Length() < 1 || !args[0]->IsNumber()) { + LOGE("Param is not valid"); + return; + } + if (controller_) { + controller_->SwipeTo(args[0]->ToNumber()); + } + } + void ShowNext(const JSCallbackInfo& args) { if (controller_) { diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp index 044938a2e4b..46d2fd4b939 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp @@ -77,10 +77,32 @@ void SwiperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1); auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); auto childrenSize = layoutWrapper->GetTotalChildCount(); + auto itemWidth = (axis == Axis::HORIZONTAL ? (size.Width() / displayCount) : (size.Height() / displayCount)); auto parentOffset = layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); + if (targetIndex_.has_value() && std::abs(targetIndex_.value() - currentIndex_) > 1) { + auto currentOffset = axis == Axis::HORIZONTAL ? OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_); + // Layout current item. + auto currentWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex_); + if (currentWrapper && currentWrapper->GetGeometryNode()) { + currentWrapper->GetGeometryNode()->SetFrameOffset(currentOffset); + currentWrapper->Layout(parentOffset); + } + + // Layout target item. + auto targetMainOffset = targetIndex_ > currentIndex_ ? itemWidth : -itemWidth; + auto targetOffset = + axis == Axis::HORIZONTAL ? OffsetF(targetMainOffset, 0.0f) : OffsetF(0.0f, targetMainOffset); + auto targetWrapper = layoutWrapper->GetOrCreateChildByIndex(targetIndex_.value()); + if (targetWrapper && targetWrapper->GetGeometryNode()) { + targetWrapper->GetGeometryNode()->SetFrameOffset(currentOffset + targetOffset); + targetWrapper->Layout(parentOffset); + } + return; + } + // layout children. for (auto index = startIndex_.value(); index <= endIndex_.value(); ++index) { // When enable loop, adjust offset. @@ -92,7 +114,6 @@ void SwiperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) } auto offset = OffsetF(0.0, 0.0); - auto itemWidth = (axis == Axis::HORIZONTAL ? (size.Width() / displayCount) : (size.Height() / displayCount)); if (axis == Axis::HORIZONTAL) { offset += OffsetF((loopIndex - currentIndex_) * itemWidth + currentOffset_, 0.0f); } else if (axis == Axis::VERTICAL) { diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h index 884f8510690..0501ea5f9c7 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h @@ -18,6 +18,7 @@ #include #include +#include #include "base/geometry/axis.h" #include "base/memory/referenced.h" @@ -57,12 +58,23 @@ public: return endIndex_.value_or(0); } + void SetTargetIndex(std::optional targetIndex) + { + targetIndex_ = targetIndex; + } + + void ResetTargetIndex() + { + targetIndex_.reset(); + } + void Measure(LayoutWrapper* layoutWrapper) override; void Layout(LayoutWrapper* layoutWrapper) override; private: int32_t currentIndex_ = 0; + std::optional targetIndex_ = 0; int32_t preStartIndex_ = 0; int32_t preEndIndex_ = 0; std::optional startIndex_; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp index 6954932d091..e5aa839c84c 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp @@ -72,7 +72,7 @@ void SwiperPattern::OnModifyDone() auto gestureHub = hub->GetOrCreateGestureEventHub(); CHECK_NULL_VOID(gestureHub); - auto childrenSize = static_cast(host->GetChildren().size()); + auto childrenSize = TotalCount(); if (CurrentIndex() >= 0 && CurrentIndex() < childrenSize) { currentIndex_ = CurrentIndex(); } else { @@ -112,11 +112,28 @@ void SwiperPattern::FireChangeEvent() const swiperEventHub->FireChangeEvent(currentIndex_); } +void SwiperPattern::SwipeTo(int32_t index) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto targetIndex = std::clamp(index, 0, TotalCount() - 1); + if (currentIndex_ == targetIndex) { + LOGD("Target index is same with current index."); + return; + } + + StopAutoPlay(); + StopTranslateAnimation(); + targetIndex_ = targetIndex; + auto translateOffset = targetIndex_.value() > currentIndex_ ? -MainSize() : MainSize(); + PlayTranslateAnimation(0, translateOffset, targetIndex_.value(), true); +} + void SwiperPattern::ShowNext() { auto host = GetHost(); CHECK_NULL_VOID(host); - auto childrenSize = static_cast(host->GetChildren().size()); + auto childrenSize = TotalCount(); if (currentIndex_ >= childrenSize - 1 && !IsLoop()) { LOGW("already last one, can't show next"); return; @@ -130,7 +147,7 @@ void SwiperPattern::ShowPrevious() { auto host = GetHost(); CHECK_NULL_VOID(host); - auto childrenSize = static_cast(host->GetChildren().size()); + auto childrenSize = TotalCount(); if (currentIndex_ <= 0 && !IsLoop()) { LOGW("already first one, can't show previous"); return; @@ -160,6 +177,14 @@ void SwiperPattern::InitSwiperController() if (swiperController_->HasInitialized()) { return; } + + swiperController_->SetSwipeToImpl([weak = WeakClaim(this)](int32_t index, bool reverse) { + auto swiper = weak.Upgrade(); + if (swiper) { + swiper->SwipeTo(index); + } + }); + swiperController_->SetShowNextImpl([weak = WeakClaim(this)]() { auto swiper = weak.Upgrade(); if (swiper) { @@ -291,16 +316,16 @@ void SwiperPattern::Tick(uint64_t duration) auto host = GetHost(); CHECK_NULL_VOID(host); + auto childrenSize = TotalCount(); elapsedTime_ += duration; if (elapsedTime_ >= static_cast(GetInterval())) { - if (currentIndex_ >= static_cast(host->GetChildren().size()) - 1 && !IsLoop()) { + if (currentIndex_ >= childrenSize - 1 && !IsLoop()) { LOGD("already last one, stop auto play because not loop"); if (scheduler_) { scheduler_->Stop(); } } else { - PlayTranslateAnimation( - 0, -MainSize(), (currentIndex_ + 1) % static_cast(host->GetChildren().size())); + PlayTranslateAnimation(0, -MainSize(), (currentIndex_ + 1) % childrenSize); } elapsedTime_ = 0; } @@ -322,7 +347,7 @@ void SwiperPattern::StartAutoPlay() if (!scheduler_ || !IsAutoPlay()) { return; } - bool reachEnd = currentIndex_ >= static_cast(host->GetChildren().size()) - 1 && !IsLoop(); + bool reachEnd = currentIndex_ >= TotalCount() - 1 && !IsLoop(); if (reachEnd && scheduler_->IsActive()) { scheduler_->Stop(); } else { @@ -444,7 +469,7 @@ void SwiperPattern::HandleDragEnd(double dragVelocity) } // Adjust next item index when loop and index is out of range. - auto childrenSize = static_cast(host->GetChildren().size()); + auto childrenSize = TotalCount(); if (IsLoop()) { if (nextIndex < 0) { nextIndex = childrenSize + nextIndex; @@ -492,6 +517,7 @@ void SwiperPattern::PlayTranslateAnimation(float startPos, float endPos, int32_t auto swiper = weak.Upgrade(); CHECK_NULL_VOID(swiper); swiper->currentOffset_ = 0.0; + swiper->targetIndex_.reset(); if (swiper->currentIndex_ != nextIndex) { swiper->currentIndex_ = nextIndex; swiper->FireChangeEvent(); @@ -578,9 +604,8 @@ bool SwiperPattern::IsOutOfBoundary(double mainOffset) const } mainOffset = std::fmod(currentOffset_, MainSize()); - auto childrenSize = static_cast(host->GetChildren().size()); auto isOutOfStart = currentIndex_ == 0 && GreatOrEqual(mainOffset, 0.0); - auto isOutOfEnd = currentIndex_ == childrenSize - 1 && LessOrEqual(mainOffset, 0.0); + auto isOutOfEnd = currentIndex_ == TotalCount() - 1 && LessOrEqual(mainOffset, 0.0); return isOutOfStart || isOutOfEnd; } @@ -658,4 +683,11 @@ bool SwiperPattern::IsDisableSwipe() const return swiperPaintProperty->GetDisableSwipe().value_or(false); } +int32_t SwiperPattern::TotalCount() const +{ + auto host = GetHost(); + CHECK_NULL_RETURN(host, 0); + return static_cast(host->GetChildren().size()); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h index b897afd773e..28328121e66 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h @@ -16,6 +16,7 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_PATTERN_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_PATTERN_H +#include #include "base/geometry/axis.h" #include "base/memory/referenced.h" #include "core/components/common/layout/constants.h" @@ -56,6 +57,7 @@ public: { auto layoutAlgorithm = MakeRefPtr(currentIndex_, startIndex_, endIndex_); layoutAlgorithm->SetCurrentOffset(currentOffset_); + layoutAlgorithm->SetTargetIndex(targetIndex_); return layoutAlgorithm; } @@ -109,6 +111,7 @@ private: void PlayFadeAnimation(); // Implement of swiper controller + void SwipeTo(int32_t index); void ShowNext(); void ShowPrevious(); void FinishAnimation(); @@ -131,6 +134,7 @@ private: bool IsAutoPlay() const; bool IsLoop() const; bool IsDisableSwipe() const; + int32_t TotalCount() const; RefPtr panEvent_; RefPtr touchEvent_; @@ -151,6 +155,7 @@ private: int32_t startIndex_ = 0; int32_t endIndex_ = 0; int32_t currentIndex_ = 0; + std::optional targetIndex_; float currentOffset_ = 0.0f; -- Gitee From de66898894846a5bf4b4404835ff45235009c23d Mon Sep 17 00:00:00 2001 From: caocan Date: Tue, 30 Aug 2022 10:40:05 +0800 Subject: [PATCH 2/2] fix codex Signed-off-by: caocan Change-Id: I12fa0ed885d0c63381ed16fdb3ed7015a5c4ed02 --- frameworks/core/components_ng/base/frame_node.h | 5 +++++ frameworks/core/components_ng/base/ui_node.cpp | 14 ++++++++++++++ frameworks/core/components_ng/base/ui_node.h | 4 ++++ .../pattern/swiper/swiper_layout_algorithm.cpp | 3 +++ .../pattern/swiper/swiper_layout_algorithm.h | 2 +- .../pattern/swiper/swiper_pattern.cpp | 3 ++- .../components_ng/pattern/swiper/swiper_pattern.h | 1 + 7 files changed, 30 insertions(+), 2 deletions(-) diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index b58c18381a2..da9195800af 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -68,6 +68,11 @@ public: ~FrameNode() override; + int32_t FrameCount() const override + { + return 1; + } + void InitializePatternAndContext(); void MarkModifyDone(); diff --git a/frameworks/core/components_ng/base/ui_node.cpp b/frameworks/core/components_ng/base/ui_node.cpp index 4b8d8714bf8..1ee471777e0 100644 --- a/frameworks/core/components_ng/base/ui_node.cpp +++ b/frameworks/core/components_ng/base/ui_node.cpp @@ -222,4 +222,18 @@ bool UINode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint return preventBubbling; } +int32_t UINode::FrameCount() const +{ + return TotalChildCount(); +} + +int32_t UINode::TotalChildCount() const +{ + int32_t count = 0; + for (const auto& child : GetChildren()) { + count += child->FrameCount(); + } + return count; +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/base/ui_node.h b/frameworks/core/components_ng/base/ui_node.h index cea4e630a9b..2a9380c235d 100644 --- a/frameworks/core/components_ng/base/ui_node.h +++ b/frameworks/core/components_ng/base/ui_node.h @@ -42,6 +42,8 @@ public: // In ets UI compiler, the atomic node does not Add Pop function, only have Create function. virtual bool IsAtomicNode() const = 0; + virtual int32_t FrameCount() const; + // Tree operation start. void AddChild(const RefPtr& child, int32_t slot = DEFAULT_NODE_SLOT); void RemoveChild(const RefPtr& child); @@ -51,6 +53,8 @@ public: void AttachToMainTree(); void DetachFromMainTree(); + int32_t TotalChildCount() const; + const std::list>& GetChildren() const { return children_; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp index 46d2fd4b939..2f008affb97 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp @@ -82,6 +82,9 @@ void SwiperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto parentOffset = layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); + // Effect when difference between current index and target index is greater than 1. + // eg. Current index is 0, call swipeTo method to jump to index 2, + // change item's position only 0 and 2, ignore others. if (targetIndex_.has_value() && std::abs(targetIndex_.value() - currentIndex_) > 1) { auto currentOffset = axis == Axis::HORIZONTAL ? OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_); // Layout current item. diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h index 0501ea5f9c7..29d2496a85b 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.h @@ -74,7 +74,7 @@ public: private: int32_t currentIndex_ = 0; - std::optional targetIndex_ = 0; + std::optional targetIndex_; int32_t preStartIndex_ = 0; int32_t preEndIndex_ = 0; std::optional startIndex_; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp index e5aa839c84c..0bc7b2fdc4a 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp @@ -125,6 +125,7 @@ void SwiperPattern::SwipeTo(int32_t index) StopAutoPlay(); StopTranslateAnimation(); targetIndex_ = targetIndex; + // TODO Adapt displayCount. auto translateOffset = targetIndex_.value() > currentIndex_ ? -MainSize() : MainSize(); PlayTranslateAnimation(0, translateOffset, targetIndex_.value(), true); } @@ -687,7 +688,7 @@ int32_t SwiperPattern::TotalCount() const { auto host = GetHost(); CHECK_NULL_RETURN(host, 0); - return static_cast(host->GetChildren().size()); + return host->TotalChildCount(); } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h index 28328121e66..a79d563c5f6 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h @@ -17,6 +17,7 @@ #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_PATTERN_H #include + #include "base/geometry/axis.h" #include "base/memory/referenced.h" #include "core/components/common/layout/constants.h" -- Gitee