From 66935aaa31e934309396a3e977ee48c44d709552 Mon Sep 17 00:00:00 2001 From: caocan Date: Thu, 1 Sep 2022 15:46:02 +0800 Subject: [PATCH 1/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]?= =?UTF-8?q?=E6=96=B0=E6=A1=86=E6=9E=B6=E5=AF=B9=E6=8E=A5Tabs=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: Ib1de1924ac3eedd5b00e34298b1fb1bc7182eca8 --- .../jsview/js_tab_content.cpp | 85 +++++++- .../jsview/js_tab_content.h | 3 + .../declarative_frontend/jsview/js_tabs.cpp | 85 ++++++-- .../core/components_ng/base/group_node.h | 1 + .../base/view_stack_processor.cpp | 10 + .../components_ng/base/view_stack_processor.h | 6 + .../core/components_ng/pattern/BUILD.gn | 5 + .../linear_layout/linear_layout_algorithm.cpp | 2 + .../swiper/swiper_layout_algorithm.cpp | 2 +- .../pattern/tabs/tab_bar_layout_algorithm.cpp | 94 +++++++++ .../pattern/tabs/tab_bar_layout_algorithm.h | 48 +++++ .../pattern/tabs/tab_bar_layout_property.h | 67 ++++++ .../pattern/tabs/tab_bar_pattern.cpp | 124 ++++++++++++ .../pattern/tabs/tab_bar_pattern.h | 68 +++++++ .../pattern/tabs/tab_content_pattern.h | 53 +++++ .../pattern/tabs/tab_content_view.cpp | 88 ++++++++ .../pattern/tabs/tab_content_view.h | 37 ++++ .../components_ng/pattern/tabs/tabs_node.cpp | 28 +++ .../components_ng/pattern/tabs/tabs_node.h | 34 ++++ .../components_ng/pattern/tabs/tabs_view.cpp | 191 ++++++++++++++++++ .../components_ng/pattern/tabs/tabs_view.h | 59 ++++++ .../inspector/inspector_constants.cpp | 4 + .../inspector/inspector_constants.h | 4 + 23 files changed, 1079 insertions(+), 19 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_content_pattern.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tab_content_view.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_node.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_node.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_view.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_view.h diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp index f541fcb6d24..959bb76b3aa 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp @@ -16,6 +16,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_tab_content.h" #include "base/log/ace_trace.h" +#include "core/components_ng/pattern/tabs/tab_content_view.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" namespace OHOS::Ace::Framework { @@ -27,15 +28,18 @@ constexpr char DEFAULT_TAB_BAR_NAME[] = "TabBar"; void JSTabContent::Create(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + CreateForNG(info); + return; + } + + bool usePartialUpdate = Container::IsCurrentUsePartialUpdate(); std::list> components; auto tabContentItemComponent = AceType::MakeRefPtr(components); tabContentItemComponent->SetCrossAxisSize(CrossAxisSize::MAX); ViewStackProcessor::GetInstance()->ClaimElementId(tabContentItemComponent); - RefPtr tabsComponent = nullptr; - - bool usePartialUpdate = Container::IsCurrentUsePartialUpdate(); - + RefPtr tabsComponent = nullptr; if (!usePartialUpdate) { tabsComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetTopTabs()); if (!tabsComponent) { @@ -71,8 +75,41 @@ void JSTabContent::Create(const JSCallbackInfo& info) LOGE("No build function for a tab provided"); } +void JSTabContent::CreateForNG(const JSCallbackInfo& info) +{ + bool usePartialUpdate = Container::IsCurrentUsePartialUpdate(); + if (!usePartialUpdate) { + NG::TabContentView::Create(); + return; + } + + if (info.Length() < 1 || !info[0]->IsFunction()) { + LOGW("Param should be a function."); + return; + } + + RefPtr jsDeepRender = AceType::MakeRefPtr(info.This(), JSRef::Cast(info[0])); + auto tabContentDeepRenderFunc = [execCtx = info.GetExecutionContext(), + jsDeepRenderFunc = std::move(jsDeepRender)](int32_t nodeId) { + if (!jsDeepRenderFunc) { + LOGE("Func is null."); + return; + } + + ACE_SCOPED_TRACE("JSTabContent::ExecuteDeepRender"); + JAVASCRIPT_EXECUTION_SCOPE(execCtx); + jsDeepRenderFunc->ExecuteJS(); + }; + NG::TabContentView::Create(std::move(tabContentDeepRenderFunc)); +} + void JSTabContent::SetTabBar(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + SetTabBarForNG(info); + return; + } + auto tabContentItemComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!tabContentItemComponent) { @@ -148,6 +185,39 @@ void JSTabContent::SetTabBar(const JSCallbackInfo& info) } } +void JSTabContent::SetTabBarForNG(const JSCallbackInfo& info) +{ + if (info.Length() <= 0) { + return; + } + + std::string content; + if (ParseJsString(info[0], content)) { + auto textVal = content.empty() ? DEFAULT_TAB_BAR_NAME : content; + NG::TabContentView::SetTabBar(textVal, ""); + return; + } + + if (!info[0]->IsObject()) { + return; + } + auto paramObject = JSRef::Cast(info[0]); + JSRef builderFuncParam = paramObject->GetProperty("builder"); + JSRef textParam = paramObject->GetProperty("text"); + JSRef iconParam = paramObject->GetProperty("icon"); + + if (builderFuncParam->IsFunction()) { + // TODO adapt builder + return; + } + + std::string text; + std::string icon; + ParseJsString(textParam, text); + ParseJsString(iconParam, icon); + NG::TabContentView::SetTabBar(text.empty() ? DEFAULT_TAB_BAR_NAME : text, icon); +} + RefPtr JSTabContent::ProcessTabBarBuilderFunction(const JSCallbackInfo& info, RefPtr& tabContent, JSRef builderFunc) { @@ -215,10 +285,17 @@ RefPtr JSTabContent::ProcessTabBarTextIconPair( return nullptr; } +void JSTabContent::Pop() +{ + JSContainerBase::Pop(); + NG::TabContentView::Pop(); +} + void JSTabContent::JSBind(BindingTarget globalObj) { JSClass::Declare("TabContent"); JSClass::StaticMethod("create", &JSTabContent::Create); + JSClass::StaticMethod("pop", &JSTabContent::Pop); JSClass::StaticMethod("tabBar", &JSTabContent::SetTabBar); JSClass::StaticMethod("onAppear", &JSInteractableView::JsOnAppear); JSClass::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.h b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.h index dacbd013869..636d65fb156 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.h @@ -28,6 +28,7 @@ class JSTabContent : public JSContainerBase { public: static void JSBind(BindingTarget globalObj); static void Create(const JSCallbackInfo& info); + static void Pop(); protected: static void SetTabBar(const JSCallbackInfo& info); @@ -49,6 +50,8 @@ protected: } private: + static void CreateForNG(const JSCallbackInfo& info); + static void SetTabBarForNG(const JSCallbackInfo& info); static RefPtr ProcessTabBarBuilderFunction(const JSCallbackInfo& info, RefPtr& tabContent, JSRef builderFunc); static RefPtr ProcessTabBarTextIconPair( diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp index 84c84d0018d..4410c609222 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp @@ -17,6 +17,8 @@ #include "core/components/tab_bar/tab_bar_component.h" #include "core/components/tab_bar/tab_content_component.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/tabs/tabs_view.h" #include "core/components_v2/tabs/tabs_component.h" #include "frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" @@ -63,6 +65,11 @@ void JSTabs::SetOnChange(const JSCallbackInfo& args) void JSTabs::Create(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::Create(); + return; + } + BarPosition barVal = BarPosition::START; RefPtr tabController; if (info[0]->IsObject()) { @@ -106,16 +113,17 @@ void JSTabs::Create(const JSCallbackInfo& info) void JSTabs::Pop() { + if (Container::IsCurrentUseNewPipeline()) { + NG::ViewStackProcessor::GetInstance()->PopContainer(); + return; + } + ViewStackProcessor::GetInstance()->PopTabs(); JSContainerBase::Pop(); } void JSTabs::SetBarPosition(const JSCallbackInfo& info) { - auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); - if (!component) { - return; - } BarPosition barVal = BarPosition::START; if (info.Length() > 0 && info[0]->IsNumber()) { auto barPositionVal = info[0]->ToNumber(); @@ -123,6 +131,16 @@ void JSTabs::SetBarPosition(const JSCallbackInfo& info) barVal = BAR_POSITIONS[barPositionVal]; } } + + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetTabBarPosition(barVal); + return; + } + + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (!component) { + return; + } auto tabBar = component->GetTabBarChild(); if (tabBar) { tabBar->SetBarPosition(barVal); @@ -131,11 +149,16 @@ void JSTabs::SetBarPosition(const JSCallbackInfo& info) void JSTabs::SetVertical(const std::string& value) { + bool isVertical = StringToBool(value); + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetAxis(isVertical ? Axis::VERTICAL : Axis::HORIZONTAL); + return; + } + auto tabsComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!tabsComponent) { return; } - bool isVertical = StringToBool(value); if (isVertical) { tabsComponent->SetDirection(FlexDirection::ROW); } else { @@ -153,6 +176,11 @@ void JSTabs::SetVertical(const std::string& value) void JSTabs::SetScrollable(const std::string& value) { + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetScrollable(StringToBool(value)); + return; + } + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!component) { return; @@ -165,31 +193,44 @@ void JSTabs::SetScrollable(const std::string& value) void JSTabs::SetBarMode(const std::string& value) { + auto tabBarMode = ConvertStrToTabBarMode(value); + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetTabBarMode(tabBarMode); + return; + } + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!component) { return; } auto tabBar = component->GetTabBarChild(); if (tabBar) { - tabBar->SetMode(ConvertStrToTabBarMode(value)); + tabBar->SetMode(tabBarMode); } } void JSTabs::SetBarWidth(const JSCallbackInfo& info) { - auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); - if (!component) { - return; - } if (info.Length() < 1) { LOGE("The arg is wrong, it is supposed to have atleast 1 arguments"); return; } + Dimension width; if (!ParseJsDimensionVp(info[0], width)) { LOGE("The arg is wrong, fail to parse dimension"); return; } + + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetTabBarWidth(width); + return; + } + + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (!component) { + return; + } auto tabBar = component->GetTabBarChild(); if (!tabBar) { LOGE("can not find tab bar component"); @@ -205,10 +246,6 @@ void JSTabs::SetBarWidth(const JSCallbackInfo& info) void JSTabs::SetBarHeight(const JSCallbackInfo& info) { - auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); - if (!component) { - return; - } if (info.Length() < 1) { LOGE("The arg is wrong, it is supposed to have atleast 1 arguments"); return; @@ -218,6 +255,16 @@ void JSTabs::SetBarHeight(const JSCallbackInfo& info) LOGE("The arg is wrong, fail to parse dimension"); return; } + + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetTabBarHeight(height); + return; + } + + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (!component) { + return; + } auto tabBar = component->GetTabBarChild(); if (!tabBar) { LOGE("can not find tab bar component"); @@ -233,6 +280,11 @@ void JSTabs::SetBarHeight(const JSCallbackInfo& info) void JSTabs::SetIndex(int32_t index) { + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetIndex(index); + return; + } + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!component) { LOGE("can not find tabs component"); @@ -248,6 +300,11 @@ void JSTabs::SetIndex(int32_t index) void JSTabs::SetAnimationDuration(float value) { + if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::SetAnimationDuration(static_cast(value)); + return; + } + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); if (!component) { return; diff --git a/frameworks/core/components_ng/base/group_node.h b/frameworks/core/components_ng/base/group_node.h index afbb92694a1..d4708d1f170 100644 --- a/frameworks/core/components_ng/base/group_node.h +++ b/frameworks/core/components_ng/base/group_node.h @@ -22,6 +22,7 @@ namespace OHOS::Ace::NG { class ACE_EXPORT GroupNode : public FrameNode { DECLARE_ACE_TYPE(GroupNode, FrameNode); + public: GroupNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot = false) : FrameNode(tag, nodeId, pattern, isRoot) {} diff --git a/frameworks/core/components_ng/base/view_stack_processor.cpp b/frameworks/core/components_ng/base/view_stack_processor.cpp index 4cc8e09236c..2a370623d53 100644 --- a/frameworks/core/components_ng/base/view_stack_processor.cpp +++ b/frameworks/core/components_ng/base/view_stack_processor.cpp @@ -56,6 +56,16 @@ void ViewStackProcessor::Push(const RefPtr& element, bool /*isCustomView elementsStack_.push(element); } +void ViewStackProcessor::PushTabBar(const TabBarParam& tabBarParam) +{ + tabBarParam_ = tabBarParam; +} + +const TabBarParam& ViewStackProcessor::PopTabBar() const +{ + return tabBarParam_; +} + bool ViewStackProcessor::ShouldPopImmediately() { if (elementsStack_.size() <= 1) { diff --git a/frameworks/core/components_ng/base/view_stack_processor.h b/frameworks/core/components_ng/base/view_stack_processor.h index 8d3e2eaedfc..0b6866603a2 100644 --- a/frameworks/core/components_ng/base/view_stack_processor.h +++ b/frameworks/core/components_ng/base/view_stack_processor.h @@ -26,6 +26,7 @@ #include "core/components_ng/base/ui_node.h" #include "core/components_ng/layout/layout_property.h" #include "core/components_ng/pattern/custom/custom_node.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" #include "core/gestures/gesture_processor.h" #include "core/pipeline/base/render_context.h" @@ -105,6 +106,9 @@ public: // the map to the render component stack. void Push(const RefPtr& element, bool isCustomView = false); + void PushTabBar(const TabBarParam& tabBarParam); + const TabBarParam& PopTabBar() const; + // Wrap the components map for the stack top and then pop the stack. // Add the wrapped component has child of the new stack top's main component. void Pop(); @@ -244,6 +248,8 @@ private: // elmtId to account get access to ElementIdType accountGetAccessToNodeId_ = ElementRegister::UndefinedElementId; + TabBarParam tabBarParam_; + ACE_DISALLOW_COPY_AND_MOVE(ViewStackProcessor); }; diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 3853e646b24..6398399e50a 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -62,6 +62,11 @@ build_component_ng("pattern_ng") { "swiper/swiper_paint_method.cpp", "swiper/swiper_pattern.cpp", "swiper/swiper_view.cpp", + "tabs/tab_bar_layout_algorithm.cpp", + "tabs/tab_bar_pattern.cpp", + "tabs/tab_content_view.cpp", + "tabs/tabs_node.cpp", + "tabs/tabs_view.cpp", "text/span_node.cpp", "text/span_view.cpp", "text/text_layout_algorithm.cpp", diff --git a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_algorithm.cpp index 410919b468c..dd8e8e216a3 100644 --- a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_algorithm.cpp @@ -21,6 +21,7 @@ #include "core/components_ng/pattern/linear_layout/linear_layout_utils.h" namespace OHOS::Ace::NG { + void LinearLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) { auto linearLayoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); @@ -45,4 +46,5 @@ void LinearLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) child->Layout(parentOffset); } } + } // namespace OHOS::Ace::NG 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 d6e4448d08b..5f1a1f8c8f4 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp @@ -90,10 +90,10 @@ void SwiperLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) // Measure children. auto layoutConstraint = swiperLayoutProperty->CreateChildConstraint(); + layoutConstraint.parentIdealSize = OptionalSizeF(idealSize); for (const auto& index : itemRange_) { auto wrapper = layoutWrapper->GetOrCreateChildByIndex(index); if (!wrapper) { - LOGE("Item %{public}d wrapper is null", index); break; } wrapper->Measure(layoutConstraint); diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp new file mode 100644 index 00000000000..eb9955550bd --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h" + +#include "base/geometry/axis.h" +#include "base/geometry/ng/offset_t.h" +#include "base/geometry/ng/size_t.h" +#include "base/log/ace_trace.h" +#include "base/utils/utils.h" +#include "core/components_ng/layout/layout_algorithm.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" +#include "core/components_ng/property/layout_constraint.h" +#include "core/components_ng/property/measure_property.h" +#include "core/components_ng/property/measure_utils.h" + +namespace OHOS::Ace::NG { + +void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) +{ + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_VOID(layoutProperty); + auto geometryNode = layoutWrapper->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto constraint = layoutProperty->GetLayoutConstraint(); + auto idealSize = CreateIdealSize(constraint.value(), axis_, layoutProperty->GetMeasureType(), true); + geometryNode->SetFrameSize(idealSize); + + // Create children layout constraint. + auto childCount = layoutWrapper->GetTotalChildCount(); + auto childLayoutConstraint = layoutProperty->CreateChildConstraint(); + auto childMainSize = geometryNode->GetFrameSize().MainSize(axis_) / childCount; + if (axis_ == Axis::HORIZONTAL) { + childLayoutConstraint.minSize.SetWidth(childMainSize); + childLayoutConstraint.maxSize.SetWidth(childMainSize); + } else { + childLayoutConstraint.minSize.SetHeight(childMainSize); + childLayoutConstraint.maxSize.SetHeight(childMainSize); + } + + // Measure children. + for (int32_t index = 0; index < childCount; ++index) { + auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); + if (!childWrapper) { + LOGI("Child %{public}d is null.", index); + return; + } + childWrapper->Measure(childLayoutConstraint); + } +} + +void TabBarLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ + tabItemOffset_.clear(); + CHECK_NULL_VOID(layoutWrapper); + auto geometryNode = layoutWrapper->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto childCount = layoutWrapper->GetTotalChildCount(); + + auto parentOffset = + layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); + auto childMainSize = geometryNode->GetFrameSize().MainSize(axis_) / childCount; + OffsetF childOffset = OffsetF(0.0f, 0.0f); + for (int32_t index = 0; index < childCount; ++index) { + auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); + CHECK_NULL_VOID(childWrapper); + auto childGeometryNode = childWrapper->GetGeometryNode(); + CHECK_NULL_VOID(childGeometryNode); + if (axis_ == Axis::HORIZONTAL) { + childOffset = OffsetF(childMainSize * index, 0.0f); + } else { + childOffset = OffsetF(0.0f, childMainSize * index); + } + childGeometryNode->SetFrameOffset(childOffset); + childWrapper->Layout(parentOffset); + tabItemOffset_.emplace_back(childOffset); + } + tabItemOffset_.emplace_back(childOffset + + (axis_ == Axis::HORIZONTAL ? OffsetF(childMainSize, 0.0f) : OffsetF(0.0f, childMainSize))); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h new file mode 100644 index 00000000000..a609e9a6069 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_ALGORITHM_H + +#include "base/geometry/axis.h" +#include "base/memory/referenced.h" +#include "core/components_ng/layout/layout_algorithm.h" +#include "core/components_ng/layout/layout_wrapper.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabBarLayoutAlgorithm : public LayoutAlgorithm { + DECLARE_ACE_TYPE(TabBarLayoutAlgorithm, LayoutAlgorithm); + +public: + TabBarLayoutAlgorithm() = default; + ~TabBarLayoutAlgorithm() override = default; + + void OnReset() override {} + void Measure(LayoutWrapper* layoutWrapper) override; + void Layout(LayoutWrapper* layoutWrapper) override; + + const std::vector& GetTabItemOffset() const + { + return tabItemOffset_; + } + +private: + Axis axis_ = Axis::HORIZONTAL; + std::vector tabItemOffset_; +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h new file mode 100644 index 00000000000..ed900542212 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_PROPERTY_H + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/layout/layout_property.h" +#include "core/components_ng/property/property.h" + +namespace OHOS::Ace::NG { + +struct TabBarParam { + std::string text; + std::string icon; +}; + +class ACE_EXPORT TabBarLayoutProperty : public LayoutProperty { + DECLARE_ACE_TYPE(TabBarLayoutProperty, LayoutProperty); + +public: + TabBarLayoutProperty() = default; + ~TabBarLayoutProperty() override = default; + + RefPtr Clone() const override + { + auto value = MakeRefPtr(); + value->LayoutProperty::UpdateLayoutProperty(AceType::DynamicCast(this)); + value->propTabBarMode_ = CloneTabBarMode(); + value->propTabBarWidth_ = CloneTabBarWidth(); + value->propTabBarHeight_ = CloneTabBarHeight(); + value->propAxis_ = CloneAxis(); + return value; + } + + void Reset() override + { + LayoutProperty::Reset(); + ResetTabBarMode(); + ResetTabBarWidth(); + ResetTabBarHeight(); + ResetAxis(); + } + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarMode, TabBarMode, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarWidth, Dimension, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarHeight, Dimension, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Axis, Axis, PROPERTY_UPDATE_LAYOUT); +}; + +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TAB_BAR_LAYOUT_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp new file mode 100644 index 00000000000..fe08ee9f91e --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tab_bar_pattern.h" + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/utils/utils.h" +#include "core/components/common/layout/constants.h" +#include "core/components/scroll/scrollable.h" +#include "core/components_ng/property/property.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { + +void TabBarPattern::OnAttachToFrameNode() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + host->GetRenderContext()->SetClipToFrame(true); +} + +void TabBarPattern::OnModifyDone() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto hub = host->GetEventHub(); + CHECK_NULL_VOID(hub); + auto gestureHub = hub->GetOrCreateGestureEventHub(); + CHECK_NULL_VOID(gestureHub); + auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) { + auto tabBar = weak.Upgrade(); + if (tabBar) { + tabBar->HandleClick(info); + } + }; + auto clickEvent = AceType::MakeRefPtr(std::move(clickCallback)); + gestureHub->AddClickEvent(clickEvent); +} + +bool TabBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) +{ + if (skipMeasure && skipLayout) { + return false; + } + auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); + CHECK_NULL_RETURN(layoutAlgorithmWrapper, false); + auto tabBarLayoutAlgorithm = DynamicCast(layoutAlgorithmWrapper->GetLayoutAlgorithm()); + CHECK_NULL_RETURN(tabBarLayoutAlgorithm, false); + tabItemOffsets_ = tabBarLayoutAlgorithm->GetTabItemOffset(); + return false; +} + +void TabBarPattern::HandleClick(const GestureEvent& info) const +{ + LOGI("Click event x is %{public}lf", info.GetLocalLocation().GetX()); + if (tabItemOffsets_.empty()) { + LOGW("tabItemOffsets is empty"); + return; + } + + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto geometryNode = host->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto frameSize = geometryNode->GetFrameSize(); + auto layoutProperty = host->GetLayoutProperty(); + CHECK_NULL_VOID(layoutProperty); + auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); + auto totalCount = host->TotalChildCount(); + + auto local = OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()) - scrollableOffset_; + if (axis == Axis::VERTICAL) { + auto clickRange = std::make_pair(tabItemOffsets_[0].GetY(), tabItemOffsets_[tabItemOffsets_.size() - 1].GetY()); + if (LessNotEqual(local.GetY(), clickRange.first) || GreatNotEqual(local.GetY(), clickRange.second)) { + LOGW("clicked (%{public}lf) position out of range [%{public}lf, %{public}lf]", local.GetY(), + clickRange.first, clickRange.second); + return; + } + } else { + auto clickRange = std::make_pair(tabItemOffsets_[0].GetX(), tabItemOffsets_[tabItemOffsets_.size() - 1].GetX()); + if (!isRTL_) { + if (LessNotEqual(local.GetX(), clickRange.first) || GreatNotEqual(local.GetX(), clickRange.second)) { + LOGW("clicked (%{public}lf) position out of range [%{public}lf, %{public}lf]", local.GetX(), + clickRange.first, clickRange.second); + return; + } + } else { + if (GreatNotEqual(local.GetX(), frameSize.MainSize(axis)) || LessNotEqual(local.GetX(), clickRange.second)) { + LOGW("clicked (%{public}lf) position out of range [%{public}lf, %{public}lf]", local.GetX(), + clickRange.first, clickRange.second); + return; + } + } + } + auto pos = std::lower_bound(tabItemOffsets_.begin(), tabItemOffsets_.end(), local, + [axis, isRTL = isRTL_](const OffsetF& a, const OffsetF& b) { + return isRTL ? GreatNotEqual(a.GetX(), b.GetX()) + : (axis == Axis::VERTICAL ? LessNotEqual(a.GetY(), b.GetY()) : LessNotEqual(a.GetX(), b.GetX())); + }); + + if (pos == tabItemOffsets_.end()) { + return; + } + auto index = isRTL_ ? std::distance(tabItemOffsets_.begin(), pos) + : std::distance(tabItemOffsets_.begin(), pos) - 1; + if (index >= 0 && index < totalCount && swiperController_) { + swiperController_->SwipeTo(index); + } +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h new file mode 100644 index 00000000000..fff4f6e8ddd --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H + +#include + +#include "base/geometry/axis.h" +#include "base/memory/referenced.h" +#include "core/components/common/layout/constants.h" +#include "core/components/swiper/swiper_controller.h" +#include "core/components_ng/event/event_hub.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" + +namespace OHOS::Ace::NG { + +class TabBarPattern : public Pattern { + DECLARE_ACE_TYPE(TabBarPattern, Pattern); + +public: + explicit TabBarPattern(const RefPtr& swiperController) : swiperController_(swiperController) {}; + ~TabBarPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } + + RefPtr CreateLayoutProperty() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + return MakeRefPtr(); + } + +private: + void OnModifyDone() override; + void OnAttachToFrameNode() override; + bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; + + void HandleClick(const GestureEvent& info) const; + + RefPtr swiperController_; + std::vector tabItemOffsets_; + OffsetF scrollableOffset_; + bool isRTL_ = false; // TODO Adapt RTL. +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_pattern.h b/frameworks/core/components_ng/pattern/tabs/tab_content_pattern.h new file mode 100644 index 00000000000..e265f36faaf --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_pattern.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H + +#include "base/memory/referenced.h" +#include "base/utils/noncopyable.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/syntax/shallow_builder.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabContentPattern : public Pattern { + DECLARE_ACE_TYPE(TabContentPattern, Pattern); + +public: + explicit TabContentPattern(const RefPtr& shallowBuilder) : shallowBuilder_(shallowBuilder) {} + ~TabContentPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } + + void BeforeCreateLayoutWrapper() override + { + if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) { + shallowBuilder_->ExecuteDeepRender(); + shallowBuilder_.Reset(); + } + } + +private: + RefPtr shallowBuilder_; + + ACE_DISALLOW_COPY_AND_MOVE(TabContentPattern); +}; + +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp new file mode 100644 index 00000000000..b85ef6cfa69 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tab_content_view.h" + +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/tabs/tab_content_pattern.h" +#include "core/components_ng/pattern/swiper/swiper_pattern.h" +#include "core/components_ng/pattern/text/text_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { + +void TabContentView::Create(std::function&& deepRenderFunc) +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto deepRender = [nodeId, deepRenderFunc = std::move(deepRenderFunc)]() -> RefPtr { + CHECK_NULL_RETURN(deepRenderFunc, nullptr); + deepRenderFunc(nodeId); + auto deepChild = ViewStackProcessor::GetInstance()->Finish(); + auto parent = FrameNode::GetOrCreateFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, nullptr); + if (deepChild && parent) { + deepChild->MountToParent(parent); + } + return deepChild; + }; + auto frameNode = FrameNode::GetOrCreateFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, + [shallowBuilder = AceType::MakeRefPtr(std::move(deepRender))]() { + return AceType::MakeRefPtr(shallowBuilder); + }); + stack->Push(frameNode); +} + +void TabContentView::Create() +{ + auto* stack = ViewStackProcessor::GetInstance(); + int32_t nodeId = (stack == nullptr ? 0 : stack->ClaimNodeId()); + auto frameNode = FrameNode::GetOrCreateFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, + []() { return AceType::MakeRefPtr(nullptr); }); + stack->Push(frameNode); +} + +void TabContentView::Pop() +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto tabBarParam = stack->PopTabBar(); + if (tabBarParam.text.empty()) { + LOGW("Text is empty."); + return; + } + + auto tabsNode = stack->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto tabBarNode = tabsNode->GetChildren().front(); + CHECK_NULL_VOID(tabBarNode); + + auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + []() { return AceType::MakeRefPtr(); }); + auto textLayoutProperty = textNode->GetLayoutProperty(); + textLayoutProperty->UpdateContent(tabBarParam.text); + textLayoutProperty->UpdateTextAlign(TextAlign::CENTER); + textNode->MountToParent(tabBarNode); + textNode->MarkModifyDone(); +} + +void TabContentView::SetTabBar(const std::string& text, const std::string& icon) +{ + TabBarParam tabBarParam { .text = text, .icon = icon }; + ViewStackProcessor::GetInstance()->PushTabBar(tabBarParam); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.h b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h new file mode 100644 index 00000000000..8b7713a8ee7 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_VIEW_H + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/memory/referenced.h" +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabContentView { +public: + static void Create(std::function&& deepRenderFunc); + static void Create(); + static void Pop(); + static void SetTabBar(const std::string& text, const std::string& icon); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_VIEW_H diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp new file mode 100644 index 00000000000..810a09eab9e --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tabs_node.h" + +namespace OHOS::Ace::NG { + +void TabsNode::AddChildToGroup(const RefPtr& child) +{ + auto swiperNode = GetChildren().back(); + if (swiperNode) { + child->MountToParent(swiperNode); + } +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.h b/frameworks/core/components_ng/pattern/tabs/tabs_node.h new file mode 100644 index 00000000000..2167b7a95a6 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H + +#include "core/components_ng/base/group_node.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabsNode : public GroupNode { + DECLARE_ACE_TYPE(TabsNode, GroupNode); + +public: + TabsNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot = false) + : GroupNode(tag, nodeId, pattern, isRoot) {} + ~TabsNode() override = default; + void AddChildToGroup(const RefPtr& child) override; +}; + +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp new file mode 100644 index 00000000000..6ea4c3ba302 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tabs_view.h" +#include + +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components/common/layout/constants.h" +#include "core/components/swiper/swiper_controller.h" +#include "core/components_ng/base/group_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" +#include "core/components_ng/pattern/swiper/swiper_layout_property.h" +#include "core/components_ng/pattern/swiper/swiper_paint_property.h" +#include "core/components_ng/pattern/swiper/swiper_pattern.h" +#include "core/components_ng/pattern/tabs/tab_bar_pattern.h" +#include "core/components_ng/pattern/tabs/tabs_node.h" +#include "core/components_ng/pattern/text/text_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { + +void TabsView::Create() +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto groupNode = GetOrCreateGroupNode(V2::TABS_ETS_TAG, nodeId, + []() { return AceType::MakeRefPtr(true); }); + + // Create Swiper node to contain TabContent. + auto swiperNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + []() { return AceType::MakeRefPtr(); }); + auto swiperLayoutProperty = swiperNode->GetLayoutProperty(); + swiperLayoutProperty->UpdateLayoutWeight(3.0); // TODO use tabBarWidth and tabBarHeight. + auto swiperPaintProperty = swiperNode->GetPaintProperty(); + swiperPaintProperty->UpdateLoop(false); + auto swiperPattern = swiperNode->GetPattern(); + CHECK_NULL_VOID(swiperPattern); + auto swiperController = swiperPattern->GetSwiperController(); + + // Create TabBar to contain TabBar of TabContent. + auto tabBarNode = FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + [swiperController]() { return AceType::MakeRefPtr(swiperController); }); + auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); + tabBarLayoutProperty->UpdateLayoutWeight(1.0); + + tabBarNode->MountToParent(groupNode); + tabBarNode->MarkModifyDone(); + + swiperNode->MountToParent(groupNode); + swiperNode->MarkModifyDone(); + + ViewStackProcessor::GetInstance()->Push(groupNode); +} + +RefPtr TabsView::GetGroupNode(const std::string& tag, int32_t nodeId) +{ + auto groupNode = ElementRegister::GetInstance()->GetSpecificItemById(nodeId); + if (!groupNode) { + return nullptr; + } + if (groupNode->GetTag() != tag) { + LOGE("the tag is changed"); + ElementRegister::GetInstance()->RemoveItemSilently(nodeId); + auto parent = groupNode->GetParent(); + if (parent) { + parent->RemoveChild(groupNode); + } + return nullptr; + } + return groupNode; +} + +void TabsView::SetTabBarPosition(BarPosition tabBarPosition) {} + +void TabsView::SetTabBarMode(TabBarMode tabBarMode) +{ + auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateTabBarMode(tabBarMode); +} + +void TabsView::SetTabBarWidth(const Dimension& tabBarWidth) +{ + auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateTabBarWidth(tabBarWidth); +} + +void TabsView::SetTabBarHeight(const Dimension& tabBarHeight) +{ + auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateTabBarHeight(tabBarHeight); +} + +void TabsView::SetAxis(Axis axis) +{ + auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateAxis(axis); +} + +void TabsView::SetIndex(int32_t index) +{ + auto swiperLayoutProperty = GetSwiperLayoutProperty(); + CHECK_NULL_VOID(swiperLayoutProperty); + swiperLayoutProperty->UpdateIndex(index); +} + +void TabsView::SetScrollable(bool scrollable) +{ + auto swiperPaintProperty = GetSwiperPaintProperty(); + CHECK_NULL_VOID(swiperPaintProperty); + swiperPaintProperty->UpdateDisableSwipe(scrollable); +} + +void TabsView::SetAnimationDuration(int32_t duration) +{ + auto swiperPaintProperty = GetSwiperPaintProperty(); + CHECK_NULL_VOID(swiperPaintProperty); + swiperPaintProperty->UpdateDuration(duration); +} + +RefPtr TabsView::GetTabBarLayoutProperty() +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_RETURN(tabsNode, nullptr); + auto tabBarNode = AceType::DynamicCast(tabsNode->GetChildren().front()); + CHECK_NULL_RETURN(tabBarNode, nullptr); + auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); + CHECK_NULL_RETURN(tabBarLayoutProperty, nullptr); + return tabBarLayoutProperty; +} + +RefPtr TabsView::GetSwiperLayoutProperty() +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_RETURN(tabsNode, nullptr); + auto swiperNode = AceType::DynamicCast(tabsNode->GetChildren().back()); + CHECK_NULL_RETURN(swiperNode, nullptr); + auto swiperLayoutProperty = swiperNode->GetLayoutProperty(); + CHECK_NULL_RETURN(swiperLayoutProperty, nullptr); + return swiperLayoutProperty; +} + +RefPtr TabsView::GetSwiperPaintProperty() +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_RETURN(tabsNode, nullptr); + auto swiperNode = AceType::DynamicCast(tabsNode->GetChildren().back()); + CHECK_NULL_RETURN(swiperNode, nullptr); + auto swiperPaintProperty = swiperNode->GetPaintProperty(); + CHECK_NULL_RETURN(swiperPaintProperty, nullptr); + return swiperPaintProperty; +} + +RefPtr TabsView::CreateGroupNode( + const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot) +{ + auto groupNode = AceType::MakeRefPtr(tag, nodeId, pattern, isRoot); + groupNode->InitializePatternAndContext(); + ElementRegister::GetInstance()->AddUINode(groupNode); + return groupNode; +} + +RefPtr TabsView::GetOrCreateGroupNode( + const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator) +{ + auto groupNode = GetGroupNode(tag, nodeId); + if (groupNode) { + return groupNode; + } + auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr(); + return CreateGroupNode(tag, nodeId, pattern); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.h b/frameworks/core/components_ng/pattern/tabs/tabs_view.h new file mode 100644 index 00000000000..79e59748457 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_VIEW_H + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/memory/referenced.h" +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/base/group_node.h" +#include "core/components_ng/pattern/swiper/swiper_layout_property.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" + +namespace OHOS::Ace::NG { + +class SwiperPaintProperty; +class ACE_EXPORT TabsView { +public: + static void Create(); + static void SetIndex(int32_t index); + static void SetTabBarPosition(BarPosition tabBarPosition); + static void SetTabBarMode(TabBarMode tabBarMode); + static void SetTabBarWidth(const Dimension& tabBarWidth); + static void SetTabBarHeight(const Dimension& tabBarHeight); + static void SetAxis(Axis axis); + static void SetScrollable(bool scrollable); + static void SetAnimationDuration(int32_t duration); + + static RefPtr GetOrCreateGroupNode( + const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator); + + static RefPtr CreateGroupNode( + const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot = false); + + static RefPtr GetGroupNode(const std::string& tag, int32_t nodeId); + +private: + static RefPtr GetTabBarLayoutProperty(); + static RefPtr GetSwiperLayoutProperty(); + static RefPtr GetSwiperPaintProperty(); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_VIEW_H diff --git a/frameworks/core/components_v2/inspector/inspector_constants.cpp b/frameworks/core/components_v2/inspector/inspector_constants.cpp index e482e8bd4c2..4f8f40b1312 100644 --- a/frameworks/core/components_v2/inspector/inspector_constants.cpp +++ b/frameworks/core/components_v2/inspector/inspector_constants.cpp @@ -95,6 +95,10 @@ const char TABS_ETS_TAG[] = "Tabs"; const char TAB_CONTENT_ITEM_COMPONENT_TAG[] = "TabContentItemComponent"; const char TAB_CONTENT_ITEM_ETS_TAG[] = "TabContent"; +// tab bar +const char TAB_BAR_COMPONENT_TAG[] = "TabBarComponent"; +const char TAB_BAR_ETS_TAG[] = "TabBar"; + // navigation view const char NAVIGATION_VIEW_COMPONENT_TAG[] = "NavigationContainerComponent"; const char NAVIGATION_VIEW_ETS_TAG[] = "Navigation"; diff --git a/frameworks/core/components_v2/inspector/inspector_constants.h b/frameworks/core/components_v2/inspector/inspector_constants.h index 65bff1b08f2..f63c59e4e0f 100644 --- a/frameworks/core/components_v2/inspector/inspector_constants.h +++ b/frameworks/core/components_v2/inspector/inspector_constants.h @@ -99,6 +99,10 @@ ACE_EXPORT extern const char TABS_ETS_TAG[]; ACE_EXPORT extern const char TAB_CONTENT_ITEM_COMPONENT_TAG[]; ACE_EXPORT extern const char TAB_CONTENT_ITEM_ETS_TAG[]; +// tab bar +ACE_EXPORT extern const char TAB_BAR_COMPONENT_TAG[]; +ACE_EXPORT extern const char TAB_BAR_ETS_TAG[]; + // navigation view ACE_EXPORT extern const char NAVIGATION_VIEW_COMPONENT_TAG[]; ACE_EXPORT extern const char NAVIGATION_VIEW_ETS_TAG[]; -- Gitee From 9ebde1f24daf6c83e8f9e388916c1245a9295221 Mon Sep 17 00:00:00 2001 From: caocan Date: Tue, 6 Sep 2022 11:46:59 +0800 Subject: [PATCH 2/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]Tab?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: Ifedc69541e6d08b9abcaff566d5ffdd19a8e7ce3 --- .../declarative_frontend/jsview/js_tabs.cpp | 35 ++++- .../declarative_frontend/jsview/js_tabs.h | 1 + .../jsview/js_tabs_controller.cpp | 5 + .../jsview/js_tabs_controller.h | 7 + .../components_ng/event/gesture_event_hub.h | 2 +- .../core/components_ng/event/pan_event.h | 5 + .../core/components_ng/pattern/BUILD.gn | 2 + .../pattern/tabs/tab_bar_layout_algorithm.cpp | 96 ++++++++++--- .../pattern/tabs/tab_bar_layout_algorithm.h | 18 ++- .../pattern/tabs/tab_bar_pattern.cpp | 41 +++++- .../pattern/tabs/tab_bar_pattern.h | 12 +- .../pattern/tabs/tab_content_view.cpp | 8 ++ .../pattern/tabs/tabs_layout_algorithm.cpp | 132 ++++++++++++++++++ .../pattern/tabs/tabs_layout_algorithm.h | 44 ++++++ .../pattern/tabs/tabs_layout_property.h | 56 ++++++++ .../pattern/tabs/tabs_pattern.cpp | 46 ++++++ .../components_ng/pattern/tabs/tabs_pattern.h | 60 ++++++++ .../components_ng/pattern/tabs/tabs_view.cpp | 60 ++++++-- .../components_ng/pattern/tabs/tabs_view.h | 3 + 19 files changed, 593 insertions(+), 40 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_layout_property.h create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/tabs/tabs_pattern.h diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp index 4410c609222..dead31591b7 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp @@ -66,7 +66,7 @@ void JSTabs::SetOnChange(const JSCallbackInfo& args) void JSTabs::Create(const JSCallbackInfo& info) { if (Container::IsCurrentUseNewPipeline()) { - NG::TabsView::Create(); + CreateForNG(info); return; } @@ -111,9 +111,42 @@ void JSTabs::Create(const JSCallbackInfo& info) ViewStackProcessor::GetInstance()->Push(tabsComponent); } +void JSTabs::CreateForNG(const JSCallbackInfo& info) +{ + NG::TabsView::Create(); + if (!info[0]->IsObject()) { + LOGE("param is not valid."); + return; + } + + auto obj = JSRef::Cast(info[0]); + auto val = obj->GetProperty("barPosition"); + if (val->IsNumber()) { + auto barPositionVal = val->ToNumber(); + if (barPositionVal >= 0 && barPositionVal < static_cast(BAR_POSITIONS.size())) { + auto barVal = BAR_POSITIONS[barPositionVal]; + NG::TabsView::SetTabBarPosition(barVal); + } + } + + auto controller = obj->GetProperty("controller"); + if (controller->IsObject()) { + auto jsTabsController = JSRef::Cast(controller)->Unwrap(); + if (jsTabsController) { + jsTabsController->SetSwiperController(NG::TabsView::GetSwiperController()); + } + } + + auto index = obj->GetProperty("index"); + if (index->IsNumber()) { + NG::TabsView::SetIndex(index->ToNumber()); + } +} + void JSTabs::Pop() { if (Container::IsCurrentUseNewPipeline()) { + NG::TabsView::Pop(); NG::ViewStackProcessor::GetInstance()->PopContainer(); return; } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.h b/frameworks/bridge/declarative_frontend/jsview/js_tabs.h index e8888af79b5..d8e41cbeb0b 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.h @@ -27,6 +27,7 @@ public: static void Pop(); protected: + static void CreateForNG(const JSCallbackInfo& info); static void SetIndex(int32_t number); static void SetVertical(const std::string& value); static void SetBarPosition(const JSCallbackInfo& info); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.cpp index 6e84c871ade..488443b6cc0 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.cpp @@ -57,6 +57,11 @@ RefPtr JSTabsController::CreateController() void JSTabsController::ChangeIndex(int32_t index) { + if (swiperController_) { + swiperController_->SwipeTo(index); + return; + } + if (controller_) { controller_->SetIndexByController(index, false); } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h index 1062919251c..fa4a2219232 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h @@ -19,6 +19,7 @@ #include "base/memory/referenced.h" #include "bridge/declarative_frontend/engine/bindings_defines.h" #include "bridge/declarative_frontend/engine/js_types.h" +#include "core/components/swiper/swiper_controller.h" #include "core/components/tab_bar/tab_controller.h" namespace OHOS::Ace::Framework { @@ -40,8 +41,14 @@ public: return controller_; } + void SetSwiperController(const RefPtr& swiperController) + { + swiperController_ = swiperController; + } + private: RefPtr controller_; + RefPtr swiperController_; ACE_DISALLOW_COPY_AND_MOVE(JSTabsController); }; diff --git a/frameworks/core/components_ng/event/gesture_event_hub.h b/frameworks/core/components_ng/event/gesture_event_hub.h index 4070e5936ef..fecf13afc75 100644 --- a/frameworks/core/components_ng/event/gesture_event_hub.h +++ b/frameworks/core/components_ng/event/gesture_event_hub.h @@ -156,7 +156,7 @@ public: void AddPanEvent(const RefPtr& panEvent, PanDirection direction, int32_t fingers, float distance) { - if (!panEventActuator_) { + if (!panEventActuator_ || direction.type != panEventActuator_->GetDirection().type) { panEventActuator_ = MakeRefPtr(WeakClaim(this), direction, fingers, distance); } panEventActuator_->AddPanEvent(panEvent); diff --git a/frameworks/core/components_ng/event/pan_event.h b/frameworks/core/components_ng/event/pan_event.h index 3120a299d60..92dd42b2bae 100644 --- a/frameworks/core/components_ng/event/pan_event.h +++ b/frameworks/core/components_ng/event/pan_event.h @@ -97,6 +97,11 @@ public: void OnCollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict, const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result) override; + PanDirection GetDirection() const + { + return direction_; + } + private: WeakPtr gestureEventHub_; std::list> panEvents_; diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 6398399e50a..1eb7736c225 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -65,7 +65,9 @@ build_component_ng("pattern_ng") { "tabs/tab_bar_layout_algorithm.cpp", "tabs/tab_bar_pattern.cpp", "tabs/tab_content_view.cpp", + "tabs/tabs_layout_algorithm.cpp", "tabs/tabs_node.cpp", + "tabs/tabs_pattern.cpp", "tabs/tabs_view.cpp", "text/span_node.cpp", "text/span_view.cpp", diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp index eb9955550bd..94f6a611dc6 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp @@ -16,41 +16,72 @@ #include "core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h" #include "base/geometry/axis.h" +#include "base/geometry/dimension.h" #include "base/geometry/ng/offset_t.h" #include "base/geometry/ng/size_t.h" #include "base/log/ace_trace.h" #include "base/utils/utils.h" #include "core/components_ng/layout/layout_algorithm.h" -#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/measure_property.h" #include "core/components_ng/property/measure_utils.h" namespace OHOS::Ace::NG { +namespace { + +constexpr Dimension TAB_BAR_DEFAULT_SIZE = 56.0_vp; + +} // namespace + +void TabBarLayoutAlgorithm::UpdateChildConstraint(LayoutConstraintF& childConstraint, + const RefPtr& layoutProperty, const SizeF& ideaSize, int32_t childCount, Axis axis) +{ + childConstraint.parentIdealSize = OptionalSizeF(ideaSize); + auto barMode = layoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED); + if (barMode == TabBarMode::FIXED) { + auto childIdeaSize = ideaSize; + if (axis == Axis::HORIZONTAL) { + childIdeaSize.SetWidth(ideaSize.Width() / childCount); + } else if (axis == Axis::VERTICAL) { + childIdeaSize.SetHeight(ideaSize.Height() / childCount); + } + childConstraint.selfIdealSize = OptionalSizeF(childIdeaSize); + } else { + if (axis == Axis::HORIZONTAL) { + childConstraint.maxSize.SetWidth(Infinity()); + } else if (axis == Axis::VERTICAL) { + childConstraint.maxSize.SetHeight(Infinity()); + } + } +} void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) { - auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); - CHECK_NULL_VOID(layoutProperty); auto geometryNode = layoutWrapper->GetGeometryNode(); CHECK_NULL_VOID(geometryNode); + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_VOID(layoutProperty); + auto axis = GetAxis(layoutWrapper); auto constraint = layoutProperty->GetLayoutConstraint(); - auto idealSize = CreateIdealSize(constraint.value(), axis_, layoutProperty->GetMeasureType(), true); - geometryNode->SetFrameSize(idealSize); + auto idealSize = CreateIdealSize(constraint.value(), axis, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)); + auto scale = layoutProperty->GetLayoutConstraint()->scaleProperty; + auto defaultSize = ConvertToPx(TAB_BAR_DEFAULT_SIZE, scale, 0.0).value_or(0); + if (!constraint->selfIdealSize.Width().has_value() && axis == Axis::VERTICAL) { + idealSize.SetWidth(defaultSize); + } + if (!constraint->selfIdealSize.Height().has_value() && axis == Axis::HORIZONTAL) { + idealSize.SetHeight(defaultSize); + } + geometryNode->SetFrameSize(idealSize.ConvertToSizeT()); - // Create children layout constraint. + // Create layout constraint of children . auto childCount = layoutWrapper->GetTotalChildCount(); auto childLayoutConstraint = layoutProperty->CreateChildConstraint(); - auto childMainSize = geometryNode->GetFrameSize().MainSize(axis_) / childCount; - if (axis_ == Axis::HORIZONTAL) { - childLayoutConstraint.minSize.SetWidth(childMainSize); - childLayoutConstraint.maxSize.SetWidth(childMainSize); - } else { - childLayoutConstraint.minSize.SetHeight(childMainSize); - childLayoutConstraint.maxSize.SetHeight(childMainSize); - } + UpdateChildConstraint(childLayoutConstraint, layoutProperty, idealSize.ConvertToSizeT(), childCount, axis); + LOGE("CCCC Measure idealSize: %{public}s, childConstraint: %{public}s", idealSize.ConvertToSizeT().ToString().c_str(), childLayoutConstraint.ToString().c_str()); // Measure children. + childrenMainSize_ = 0.0f; for (int32_t index = 0; index < childCount; ++index) { auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); if (!childWrapper) { @@ -58,6 +89,12 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) return; } childWrapper->Measure(childLayoutConstraint); + + auto childGeometryNode = childWrapper->GetGeometryNode(); + if (childGeometryNode) { + childrenMainSize_ += childGeometryNode->GetFrameSize().MainSize(axis); + } + LOGE("CCCC Measure childSize: %{public}s - %{public}d", childWrapper->GetGeometryNode()->GetFrameSize().ToString().c_str(), index); } } @@ -68,27 +105,40 @@ void TabBarLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto geometryNode = layoutWrapper->GetGeometryNode(); CHECK_NULL_VOID(geometryNode); auto childCount = layoutWrapper->GetTotalChildCount(); + auto axis = GetAxis(layoutWrapper); auto parentOffset = layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); - auto childMainSize = geometryNode->GetFrameSize().MainSize(axis_) / childCount; - OffsetF childOffset = OffsetF(0.0f, 0.0f); + auto scrollableDistance = std::max(childrenMainSize_ - geometryNode->GetFrameSize().MainSize(axis), 0.0f); + currentOffset_ = std::clamp(currentOffset_, -scrollableDistance, 0.0f); + OffsetF childOffset = (axis == Axis::HORIZONTAL ? + OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_)); for (int32_t index = 0; index < childCount; ++index) { auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); CHECK_NULL_VOID(childWrapper); auto childGeometryNode = childWrapper->GetGeometryNode(); CHECK_NULL_VOID(childGeometryNode); - if (axis_ == Axis::HORIZONTAL) { - childOffset = OffsetF(childMainSize * index, 0.0f); - } else { - childOffset = OffsetF(0.0f, childMainSize * index); - } childGeometryNode->SetFrameOffset(childOffset); childWrapper->Layout(parentOffset); tabItemOffset_.emplace_back(childOffset); + + LOGE("CCCC Layout childOffset: %{public}s, parentOffset: %{public}s, currentOffset: %{public}lf", + childOffset.ToString().c_str(), parentOffset.ToString().c_str(), currentOffset_); + + if (axis == Axis::HORIZONTAL) { + childOffset += OffsetF(childGeometryNode->GetFrameSize().Width(), 0.0f); + } else { + childOffset += OffsetF(0.0f, childGeometryNode->GetFrameSize().Height()); + } } - tabItemOffset_.emplace_back(childOffset + - (axis_ == Axis::HORIZONTAL ? OffsetF(childMainSize, 0.0f) : OffsetF(0.0f, childMainSize))); + tabItemOffset_.emplace_back(childOffset); +} + +Axis TabBarLayoutAlgorithm::GetAxis(LayoutWrapper* layoutWrapper) const +{ + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_RETURN(layoutProperty, Axis::HORIZONTAL); + return layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h index a609e9a6069..1a8eae8b68a 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h @@ -20,6 +20,7 @@ #include "base/memory/referenced.h" #include "core/components_ng/layout/layout_algorithm.h" #include "core/components_ng/layout/layout_wrapper.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" namespace OHOS::Ace::NG { @@ -39,9 +40,24 @@ public: return tabItemOffset_; } + void SetCurrentOffset(float currentOffset) + { + currentOffset_ = currentOffset; + } + + float GetCurrentOffset() const + { + return currentOffset_; + } + private: - Axis axis_ = Axis::HORIZONTAL; + Axis GetAxis(LayoutWrapper* layoutWrapper) const; + void UpdateChildConstraint(LayoutConstraintF& childConstraint, + const RefPtr& layoutProperty, const SizeF& ideaSize, int32_t childCount, Axis axis); + std::vector tabItemOffset_; + float currentOffset_ = 0.0f; + float childrenMainSize_ = 0.0f; // Children total size in main axis. }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp index fe08ee9f91e..27240b4522d 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp @@ -40,6 +40,8 @@ void TabBarPattern::OnModifyDone() CHECK_NULL_VOID(hub); auto gestureHub = hub->GetOrCreateGestureEventHub(); CHECK_NULL_VOID(gestureHub); + + // Init click event. auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) { auto tabBar = weak.Upgrade(); if (tabBar) { @@ -48,6 +50,33 @@ void TabBarPattern::OnModifyDone() }; auto clickEvent = AceType::MakeRefPtr(std::move(clickCallback)); gestureHub->AddClickEvent(clickEvent); + + // Init scrollable. + auto layoutProperty = host->GetLayoutProperty(); + CHECK_NULL_VOID(layoutProperty); + auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); + if (axis_ == axis && scrollableEvent_) { + LOGD("Direction not changed, need't resister scroll event again."); + return; + } + + axis_ = axis; + auto task = [weak = WeakClaim(this)](double offset, int32_t source) { + if (source != SCROLL_FROM_START) { + auto pattern = weak.Upgrade(); + if (pattern) { + pattern->UpdateCurrentOffset(static_cast(offset)); + } + } + return true; + }; + + if (scrollableEvent_) { + gestureHub->RemoveScrollableEvent(scrollableEvent_); + } + scrollableEvent_ = MakeRefPtr(axis); + scrollableEvent_->SetScrollPositionCallback(std::move(task)); + gestureHub->AddScrollableEvent(scrollableEvent_); } bool TabBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) @@ -60,6 +89,7 @@ bool TabBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, auto tabBarLayoutAlgorithm = DynamicCast(layoutAlgorithmWrapper->GetLayoutAlgorithm()); CHECK_NULL_RETURN(tabBarLayoutAlgorithm, false); tabItemOffsets_ = tabBarLayoutAlgorithm->GetTabItemOffset(); + currentOffset_ = tabBarLayoutAlgorithm->GetCurrentOffset(); return false; } @@ -81,7 +111,8 @@ void TabBarPattern::HandleClick(const GestureEvent& info) const auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); auto totalCount = host->TotalChildCount(); - auto local = OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()) - scrollableOffset_; + OffsetF currentOffset = (axis == Axis::HORIZONTAL ? OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_)); + auto local = OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()) - currentOffset; if (axis == Axis::VERTICAL) { auto clickRange = std::make_pair(tabItemOffsets_[0].GetY(), tabItemOffsets_[tabItemOffsets_.size() - 1].GetY()); if (LessNotEqual(local.GetY(), clickRange.first) || GreatNotEqual(local.GetY(), clickRange.second)) { @@ -121,4 +152,12 @@ void TabBarPattern::HandleClick(const GestureEvent& info) const } } +void TabBarPattern::UpdateCurrentOffset(float offset) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + currentOffset_ = currentOffset_ + offset; + host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h index fff4f6e8ddd..e86ffad9d79 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h @@ -48,9 +48,13 @@ public: RefPtr CreateLayoutAlgorithm() override { - return MakeRefPtr(); + auto layoutAlgorithm = MakeRefPtr(); + layoutAlgorithm->SetCurrentOffset(currentOffset_); + return layoutAlgorithm; } + void UpdateCurrentOffset(float offset); + private: void OnModifyDone() override; void OnAttachToFrameNode() override; @@ -60,7 +64,11 @@ private: RefPtr swiperController_; std::vector tabItemOffsets_; - OffsetF scrollableOffset_; + + float currentOffset_; + Axis axis_ = Axis::HORIZONTAL; + RefPtr scrollableEvent_; + bool isRTL_ = false; // TODO Adapt RTL. }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp index b85ef6cfa69..e3e29e5901b 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp @@ -25,6 +25,11 @@ #include "core/components_v2/inspector/inspector_constants.h" namespace OHOS::Ace::NG { +namespace { + +constexpr char DEFAULT_TAB_BAR_NAME[] = "TabBar"; + +} // namespace void TabContentView::Create(std::function&& deepRenderFunc) { @@ -45,6 +50,7 @@ void TabContentView::Create(std::function&& deepRenderFunc) return AceType::MakeRefPtr(shallowBuilder); }); stack->Push(frameNode); + SetTabBar(DEFAULT_TAB_BAR_NAME, ""); // Set default tab bar. } void TabContentView::Create() @@ -75,6 +81,8 @@ void TabContentView::Pop() auto textLayoutProperty = textNode->GetLayoutProperty(); textLayoutProperty->UpdateContent(tabBarParam.text); textLayoutProperty->UpdateTextAlign(TextAlign::CENTER); + textLayoutProperty->UpdateMaxLines(1); + textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS); textNode->MountToParent(tabBarNode); textNode->MarkModifyDone(); } diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp new file mode 100644 index 00000000000..bcd75357337 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tabs_layout_algorithm.h" + +#include "base/geometry/axis.h" +#include "base/geometry/ng/offset_t.h" +#include "base/geometry/ng/size_t.h" +#include "base/log/ace_trace.h" +#include "base/utils/utils.h" +#include "core/components_ng/layout/layout_algorithm.h" +#include "core/components_ng/property/layout_constraint.h" +#include "core/components_ng/property/measure_property.h" +#include "core/components_ng/property/measure_utils.h" + +namespace OHOS::Ace::NG { + +void TabsLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) +{ + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_VOID(layoutProperty); + auto geometryNode = layoutWrapper->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); + auto constraint = layoutProperty->GetLayoutConstraint(); + auto idealSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true); + geometryNode->SetFrameSize(idealSize); + auto childLayoutConstraint = layoutProperty->CreateChildConstraint(); + childLayoutConstraint.parentIdealSize = OptionalSizeF(idealSize); + + // Measure tab bar. + auto tabBarWrapper = layoutWrapper->GetOrCreateChildByIndex(0); + SizeF tabBarSize; + if (tabBarWrapper) { + tabBarWrapper->Measure(childLayoutConstraint); + tabBarSize = tabBarWrapper->GetGeometryNode()->GetFrameSize(); + } + LOGE("CCCC Measure tabBarSize: %{public}s, childConstraint: %{public}s", tabBarSize.ToString().c_str(), childLayoutConstraint.ToString().c_str()); + + // Measure swiper. + auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(1); + if (swiperWrapper) { + SizeF parentIdealSize = idealSize; + if (axis == Axis::HORIZONTAL) { + childLayoutConstraint.maxSize.SetHeight(childLayoutConstraint.maxSize.Height() - tabBarSize.Height()); + parentIdealSize.SetHeight(idealSize.Height() - tabBarSize.Height()); + } else if (axis == Axis::VERTICAL) { + childLayoutConstraint.maxSize.SetWidth(childLayoutConstraint.maxSize.Width() - tabBarSize.Width()); + parentIdealSize.SetWidth(idealSize.Width() - tabBarSize.Width()); + } + childLayoutConstraint.parentIdealSize = OptionalSizeF(parentIdealSize); + swiperWrapper->Measure(childLayoutConstraint); + LOGE("CCCC Measure swiper size: %{public}s, childLayoutConstraint: %{public}s", + swiperWrapper->GetGeometryNode()->GetFrameSize().ToString().c_str(), childLayoutConstraint.ToString().c_str()); + } +} + +void TabsLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ + CHECK_NULL_VOID(layoutWrapper); + auto geometryNode = layoutWrapper->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto frameSize = geometryNode->GetFrameSize(); + + auto tabBarWrapper = layoutWrapper->GetOrCreateChildByIndex(0); + auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(1); + if (!tabBarWrapper || !swiperWrapper) { + return; + } + + auto axis = GetAxis(layoutWrapper); + auto barPosition = GetBarPosition(layoutWrapper); + auto tabBarGeometryNode = tabBarWrapper->GetGeometryNode(); + CHECK_NULL_VOID(tabBarGeometryNode); + auto tabBarFrameSize = tabBarGeometryNode->GetFrameSize(); + + OffsetF tabBarOffset; + OffsetF swiperOffset; + if (axis == Axis::HORIZONTAL) { + if (barPosition == BarPosition::START) { + tabBarOffset = OffsetF(); + swiperOffset = OffsetF(0.0f, tabBarFrameSize.MainSize(Axis::VERTICAL)); + } else { + tabBarOffset = OffsetF(0.0f, frameSize.MainSize(Axis::VERTICAL) - tabBarFrameSize.MainSize(Axis::VERTICAL)); + swiperOffset = OffsetF(); + } + } else { + if (barPosition == BarPosition::START) { + tabBarOffset = OffsetF(); + swiperOffset = OffsetF(tabBarFrameSize.MainSize(Axis::HORIZONTAL), 0.0f); + } else { + tabBarOffset = OffsetF(frameSize.MainSize(Axis::HORIZONTAL) - tabBarFrameSize.MainSize(Axis::HORIZONTAL), 0.0); + swiperOffset = OffsetF(); + } + } + + auto parentOffset = geometryNode->GetParentGlobalOffset() + geometryNode->GetFrameOffset(); + tabBarGeometryNode->SetFrameOffset(tabBarOffset); + tabBarWrapper->Layout(parentOffset); + LOGE("CCCC Layout tabBarOffset: %{public}s, parentOffset: %{public}s", tabBarOffset.ToString().c_str(), parentOffset.ToString().c_str()); + + swiperWrapper->GetGeometryNode()->SetFrameOffset(swiperOffset); + swiperWrapper->Layout(parentOffset); +} + +BarPosition TabsLayoutAlgorithm::GetBarPosition(LayoutWrapper* layoutWrapper) const +{ + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_RETURN(layoutProperty, BarPosition::START); + return layoutProperty->GetTabBarPosition().value_or(BarPosition::START); +} + +Axis TabsLayoutAlgorithm::GetAxis(LayoutWrapper* layoutWrapper) const +{ + auto layoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_RETURN(layoutProperty, Axis::HORIZONTAL); + return layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.h b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.h new file mode 100644 index 00000000000..8c01e553896 --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_ALGORITHM_H + +#include "base/geometry/axis.h" +#include "base/memory/referenced.h" +#include "core/components_ng/layout/layout_algorithm.h" +#include "core/components_ng/layout/layout_wrapper.h" +#include "core/components_ng/pattern/tabs/tabs_layout_property.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabsLayoutAlgorithm : public LayoutAlgorithm { + DECLARE_ACE_TYPE(TabsLayoutAlgorithm, LayoutAlgorithm); + +public: + TabsLayoutAlgorithm() = default; + ~TabsLayoutAlgorithm() override = default; + + void OnReset() override {} + void Measure(LayoutWrapper* layoutWrapper) override; + void Layout(LayoutWrapper* layoutWrapper) override; + +private: + BarPosition GetBarPosition(LayoutWrapper* layoutWrapper) const; + Axis GetAxis(LayoutWrapper* layoutWrapper) const; +}; + +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_layout_property.h b/frameworks/core/components_ng/pattern/tabs/tabs_layout_property.h new file mode 100644 index 00000000000..3890d7850ee --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_layout_property.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_PROPERTY_H + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/layout/layout_property.h" +#include "core/components_ng/property/property.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT TabsLayoutProperty : public LayoutProperty { + DECLARE_ACE_TYPE(TabsLayoutProperty, LayoutProperty); + +public: + TabsLayoutProperty() = default; + ~TabsLayoutProperty() override = default; + + RefPtr Clone() const override + { + auto value = MakeRefPtr(); + value->LayoutProperty::UpdateLayoutProperty(AceType::DynamicCast(this)); + value->propTabBarPosition_ = CloneTabBarPosition(); + value->propAxis_ = CloneAxis(); + return value; + } + + void Reset() override + { + LayoutProperty::Reset(); + ResetTabBarPosition(); + ResetAxis(); + } + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarPosition, BarPosition, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Axis, Axis, PROPERTY_UPDATE_LAYOUT); +}; + +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TABS_TABS_LAYOUT_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp new file mode 100644 index 00000000000..a994d417c7f --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/tabs/tabs_pattern.h" + +#include "base/geometry/axis.h" +#include "base/geometry/dimension.h" +#include "base/utils/utils.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/property/property.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { + +void TabsPattern::OnAttachToFrameNode() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + host->GetRenderContext()->SetClipToFrame(true); +} + +void TabsPattern::OnModifyDone() {} + +bool TabsPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) +{ + if (skipMeasure && skipLayout) { + return false; + } + auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); + CHECK_NULL_RETURN(layoutAlgorithmWrapper, false); + return false; +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h new file mode 100644 index 00000000000..0e9aa923ccf --- /dev/null +++ b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_PATTERN_H + +#include + +#include "base/geometry/axis.h" +#include "base/memory/referenced.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/event/event_hub.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/tabs/tabs_layout_algorithm.h" +#include "core/components_ng/pattern/tabs/tabs_layout_property.h" + +namespace OHOS::Ace::NG { + +class TabsPattern : public Pattern { + DECLARE_ACE_TYPE(TabsPattern, Pattern); + +public: + TabsPattern() = default; + ~TabsPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } + + RefPtr CreateLayoutProperty() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + return MakeRefPtr(); + } + +private: + void OnModifyDone() override; + void OnAttachToFrameNode() override; + bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp index 6ea4c3ba302..bfcbfc4ea56 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp @@ -28,6 +28,7 @@ #include "core/components_ng/pattern/swiper/swiper_pattern.h" #include "core/components_ng/pattern/tabs/tab_bar_pattern.h" #include "core/components_ng/pattern/tabs/tabs_node.h" +#include "core/components_ng/pattern/tabs/tabs_pattern.h" #include "core/components_ng/pattern/text/text_pattern.h" #include "core/components_v2/inspector/inspector_constants.h" @@ -38,13 +39,11 @@ void TabsView::Create() auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); auto groupNode = GetOrCreateGroupNode(V2::TABS_ETS_TAG, nodeId, - []() { return AceType::MakeRefPtr(true); }); + []() { return AceType::MakeRefPtr(); }); // Create Swiper node to contain TabContent. auto swiperNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); - auto swiperLayoutProperty = swiperNode->GetLayoutProperty(); - swiperLayoutProperty->UpdateLayoutWeight(3.0); // TODO use tabBarWidth and tabBarHeight. auto swiperPaintProperty = swiperNode->GetPaintProperty(); swiperPaintProperty->UpdateLoop(false); auto swiperPattern = swiperNode->GetPattern(); @@ -55,13 +54,9 @@ void TabsView::Create() auto tabBarNode = FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), [swiperController]() { return AceType::MakeRefPtr(swiperController); }); auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); - tabBarLayoutProperty->UpdateLayoutWeight(1.0); tabBarNode->MountToParent(groupNode); - tabBarNode->MarkModifyDone(); - swiperNode->MountToParent(groupNode); - swiperNode->MarkModifyDone(); ViewStackProcessor::GetInstance()->Push(groupNode); } @@ -84,7 +79,10 @@ RefPtr TabsView::GetGroupNode(const std::string& tag, int32_t nodeId) return groupNode; } -void TabsView::SetTabBarPosition(BarPosition tabBarPosition) {} +void TabsView::SetTabBarPosition(BarPosition tabBarPosition) +{ + ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarPosition, tabBarPosition); +} void TabsView::SetTabBarMode(TabBarMode tabBarMode) { @@ -95,23 +93,39 @@ void TabsView::SetTabBarMode(TabBarMode tabBarMode) void TabsView::SetTabBarWidth(const Dimension& tabBarWidth) { - auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto tabBarNode = AceType::DynamicCast(tabsNode->GetChildren().front()); + CHECK_NULL_VOID(tabBarNode); + auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateCalcSelfIdealSize(CalcSize(NG::CalcLength(tabBarWidth), std::nullopt)); tabBarLayoutProperty->UpdateTabBarWidth(tabBarWidth); } void TabsView::SetTabBarHeight(const Dimension& tabBarHeight) { - auto tabBarLayoutProperty = GetTabBarLayoutProperty(); + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto tabBarNode = AceType::DynamicCast(tabsNode->GetChildren().front()); + CHECK_NULL_VOID(tabBarNode); + auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); CHECK_NULL_VOID(tabBarLayoutProperty); + tabBarLayoutProperty->UpdateCalcSelfIdealSize(CalcSize(std::nullopt, NG::CalcLength(tabBarHeight))); tabBarLayoutProperty->UpdateTabBarHeight(tabBarHeight); } void TabsView::SetAxis(Axis axis) { + ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Axis, axis); + auto tabBarLayoutProperty = GetTabBarLayoutProperty(); CHECK_NULL_VOID(tabBarLayoutProperty); tabBarLayoutProperty->UpdateAxis(axis); + + auto swiperLayoutProperty = GetSwiperLayoutProperty(); + CHECK_NULL_VOID(swiperLayoutProperty); + swiperLayoutProperty->UpdateDirection(axis); } void TabsView::SetIndex(int32_t index) @@ -125,7 +139,7 @@ void TabsView::SetScrollable(bool scrollable) { auto swiperPaintProperty = GetSwiperPaintProperty(); CHECK_NULL_VOID(swiperPaintProperty); - swiperPaintProperty->UpdateDisableSwipe(scrollable); + swiperPaintProperty->UpdateDisableSwipe(!scrollable); } void TabsView::SetAnimationDuration(int32_t duration) @@ -168,6 +182,30 @@ RefPtr TabsView::GetSwiperPaintProperty() return swiperPaintProperty; } +RefPtr TabsView::GetSwiperController() +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_RETURN(tabsNode, nullptr); + auto swiperNode = AceType::DynamicCast(tabsNode->GetChildren().back()); + CHECK_NULL_RETURN(swiperNode, nullptr); + auto swiperPattern = swiperNode->GetPattern(); + CHECK_NULL_RETURN(swiperNode, nullptr); + return swiperPattern->GetSwiperController(); +} + +void TabsView::Pop() +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto tabBarNode = AceType::DynamicCast(tabsNode->GetChildren().front()); + CHECK_NULL_VOID(tabBarNode); + tabBarNode->MarkModifyDone(); + + auto swiperNode = AceType::DynamicCast(tabsNode->GetChildren().back()); + CHECK_NULL_VOID(swiperNode); + swiperNode->MarkModifyDone(); +} + RefPtr TabsView::CreateGroupNode( const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot) { diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.h b/frameworks/core/components_ng/pattern/tabs/tabs_view.h index 79e59748457..15a9319698c 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.h @@ -31,6 +31,7 @@ class SwiperPaintProperty; class ACE_EXPORT TabsView { public: static void Create(); + static void Pop(); static void SetIndex(int32_t index); static void SetTabBarPosition(BarPosition tabBarPosition); static void SetTabBarMode(TabBarMode tabBarMode); @@ -40,6 +41,8 @@ public: static void SetScrollable(bool scrollable); static void SetAnimationDuration(int32_t duration); + static RefPtr GetSwiperController(); + static RefPtr GetOrCreateGroupNode( const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator); -- Gitee From e25cc285f0dcbc6b7e87068c65bc1db30cbb2256 Mon Sep 17 00:00:00 2001 From: caocan Date: Tue, 6 Sep 2022 15:41:14 +0800 Subject: [PATCH 3/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]Tab?= =?UTF-8?q?s=E7=BB=84=E4=BB=B6=E6=94=AF=E6=8C=81change=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: Ie5bced971fe96e359e2fdcd98601b2c16fde2e00 --- .../jsview/js_tab_content.cpp | 42 ++++++---- .../declarative_frontend/jsview/js_tabs.cpp | 53 +++++++----- .../pattern/tabs/tab_bar_layout_algorithm.cpp | 35 ++++---- .../pattern/tabs/tab_bar_layout_algorithm.h | 4 +- .../pattern/tabs/tab_bar_layout_property.h | 2 + .../pattern/tabs/tab_bar_pattern.cpp | 66 +++++++++++---- .../pattern/tabs/tab_bar_pattern.h | 16 ++-- .../pattern/tabs/tab_content_view.cpp | 82 +++++++++++++++---- .../pattern/tabs/tab_content_view.h | 5 +- .../pattern/tabs/tabs_layout_algorithm.cpp | 16 ++-- .../components_ng/pattern/tabs/tabs_node.h | 3 +- .../components_ng/pattern/tabs/tabs_pattern.h | 2 +- .../components_ng/pattern/tabs/tabs_view.cpp | 71 ++++++++-------- .../components_ng/pattern/tabs/tabs_view.h | 9 +- 14 files changed, 263 insertions(+), 143 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp index 959bb76b3aa..32aac82a0ea 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp @@ -63,8 +63,8 @@ void JSTabContent::Create(const JSCallbackInfo& info) if (usePartialUpdate && info.Length() > 0 && info[0]->IsFunction()) { JSRef builderFunctionJS = info[0]; LOGD("We have a build function for a tab"); - auto jsWrapperFunc = - [context = info.GetExecutionContext(), builder = builderFunctionJS]() -> RefPtr { + auto jsWrapperFunc = [context = info.GetExecutionContext(), + builder = builderFunctionJS]() -> RefPtr { JAVASCRIPT_EXECUTION_SCOPE(context) JSRef::Cast(builder)->Call(JSRef()); return ViewStackProcessor::GetInstance()->Finish(); @@ -90,7 +90,7 @@ void JSTabContent::CreateForNG(const JSCallbackInfo& info) RefPtr jsDeepRender = AceType::MakeRefPtr(info.This(), JSRef::Cast(info[0])); auto tabContentDeepRenderFunc = [execCtx = info.GetExecutionContext(), - jsDeepRenderFunc = std::move(jsDeepRender)](int32_t nodeId) { + jsDeepRenderFunc = std::move(jsDeepRender)]() { if (!jsDeepRenderFunc) { LOGE("Func is null."); return; @@ -180,8 +180,8 @@ void JSTabContent::SetTabBar(const JSCallbackInfo& info) if (tabContentItemComponent->GetBarElementId() == ElementRegister::UndefinedElementId) { const auto id = ElementRegister::GetInstance()->MakeUniqueId(); tabContentItemComponent->SetBarElementId(id); - LOGD("Setting ID for tab bar item to %{public}d tabContentItemComponent id %{public}d", - id, tabContentItemComponent->GetBarElementId()); + LOGD("Setting ID for tab bar item to %{public}d tabContentItemComponent id %{public}d", id, + tabContentItemComponent->GetBarElementId()); } } @@ -194,7 +194,7 @@ void JSTabContent::SetTabBarForNG(const JSCallbackInfo& info) std::string content; if (ParseJsString(info[0], content)) { auto textVal = content.empty() ? DEFAULT_TAB_BAR_NAME : content; - NG::TabContentView::SetTabBar(textVal, ""); + NG::TabContentView::SetTabBar(textVal, "", nullptr); return; } @@ -207,28 +207,37 @@ void JSTabContent::SetTabBarForNG(const JSCallbackInfo& info) JSRef iconParam = paramObject->GetProperty("icon"); if (builderFuncParam->IsFunction()) { - // TODO adapt builder + auto tabBarBuilder = AceType::MakeRefPtr(info.This(), JSRef::Cast(builderFuncParam)); + auto tabBarBuilderFunc = [execCtx = info.GetExecutionContext(), + tabBarBuilderFunc = std::move(tabBarBuilder)]() { + if (tabBarBuilderFunc) { + ACE_SCOPED_TRACE("JSTabContent::Execute TabBar builder"); + JAVASCRIPT_EXECUTION_SCOPE(execCtx); + tabBarBuilderFunc->ExecuteJS(); + } + }; + NG::TabContentView::SetTabBar("", "", std::move(tabBarBuilderFunc)); return; } std::string text; std::string icon; ParseJsString(textParam, text); - ParseJsString(iconParam, icon); - NG::TabContentView::SetTabBar(text.empty() ? DEFAULT_TAB_BAR_NAME : text, icon); + ParseJsMedia(iconParam, icon); + NG::TabContentView::SetTabBar(text.empty() ? DEFAULT_TAB_BAR_NAME : text, icon, nullptr); } -RefPtr JSTabContent::ProcessTabBarBuilderFunction(const JSCallbackInfo& info, - RefPtr& tabContent, JSRef builderFunc) +RefPtr JSTabContent::ProcessTabBarBuilderFunction( + const JSCallbackInfo& info, RefPtr& tabContent, JSRef builderFunc) { tabContent->SetBarText("custom"); if (Container::IsCurrentUsePartialUpdate()) { auto jsWrapperFunc = [context = info.GetExecutionContext(), builder = builderFunc]() -> RefPtr { - ACE_SCORING_EVENT("TabContent.tabBarBuilder"); - JAVASCRIPT_EXECUTION_SCOPE(context) - JSRef::Cast(builder)->Call(JSRef()); - return ViewStackProcessor::GetInstance()->Finish(); - }; + ACE_SCORING_EVENT("TabContent.tabBarBuilder"); + JAVASCRIPT_EXECUTION_SCOPE(context) + JSRef::Cast(builder)->Call(JSRef()); + return ViewStackProcessor::GetInstance()->Finish(); + }; tabContent->SetBarBuilder(jsWrapperFunc); return nullptr; @@ -240,7 +249,6 @@ RefPtr JSTabContent::ProcessTabBarBuilderFunction(const JSCallbackInf jsBuilderFunc.Execute(); RefPtr builderGeneratedRootComponent = ViewStackProcessor::GetInstance()->Finish(); return builderGeneratedRootComponent; - } RefPtr JSTabContent::CreateTabBarLabelComponent( diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp index dead31591b7..d5b02971139 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp @@ -38,29 +38,42 @@ JSRef TabContentChangeEventToJSValue(const TabContentChangeEvent& eventIn void JSTabs::SetOnChange(const JSCallbackInfo& args) { - if (args[0]->IsFunction()) { - auto changeHandler = AceType::MakeRefPtr>( - JSRef::Cast(args[0]), TabContentChangeEventToJSValue); - auto onChange = EventMarker([executionContext = args.GetExecutionContext(), func = std::move(changeHandler)]( - const BaseEventInfo* info) { - JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext); - auto TabsInfo = TypeInfoHelper::DynamicCast(info); - if (!TabsInfo) { - LOGE("HandleChangeEvent TabsInfo == nullptr"); - return; - } + if (!args[0]->IsFunction()) { + return; + } + + if (Container::IsCurrentUseNewPipeline()) { + auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); + auto onChange = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](int32_t index) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Tabs.onChange"); - func->Execute(*TabsInfo); - }); - auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); - if (component) { - auto tabContent = component->GetTabContentChild(); - if (tabContent) { - tabContent->SetChangeEventId(onChange); - } + auto newJSVal = JSRef::Make(ToJSValue(index)); + func->ExecuteJS(1, &newJSVal); + }; + NG::TabsView::SetOnChange(std::move(onChange)); + return; + } + + auto changeHandler = AceType::MakeRefPtr>( + JSRef::Cast(args[0]), TabContentChangeEventToJSValue); + auto onChange = EventMarker([executionContext = args.GetExecutionContext(), func = std::move(changeHandler)]( + const BaseEventInfo* info) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext); + auto TabsInfo = TypeInfoHelper::DynamicCast(info); + if (!TabsInfo) { + LOGE("HandleChangeEvent TabsInfo == nullptr"); + return; + } + ACE_SCORING_EVENT("Tabs.onChange"); + func->Execute(*TabsInfo); + }); + auto component = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (component) { + auto tabContent = component->GetTabContentChild(); + if (tabContent) { + tabContent->SetChangeEventId(onChange); } } - args.ReturnSelf(); } void JSTabs::Create(const JSCallbackInfo& info) diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp index 94f6a611dc6..235af85dae3 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp @@ -63,9 +63,10 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) CHECK_NULL_VOID(layoutProperty); auto axis = GetAxis(layoutWrapper); auto constraint = layoutProperty->GetLayoutConstraint(); - auto idealSize = CreateIdealSize(constraint.value(), axis, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)); + auto idealSize = + CreateIdealSize(constraint.value(), axis, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)); auto scale = layoutProperty->GetLayoutConstraint()->scaleProperty; - auto defaultSize = ConvertToPx(TAB_BAR_DEFAULT_SIZE, scale, 0.0).value_or(0); + auto defaultSize = ConvertToPx(TAB_BAR_DEFAULT_SIZE, scale, 0).value_or(0); if (!constraint->selfIdealSize.Width().has_value() && axis == Axis::VERTICAL) { idealSize.SetWidth(defaultSize); } @@ -78,7 +79,6 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) auto childCount = layoutWrapper->GetTotalChildCount(); auto childLayoutConstraint = layoutProperty->CreateChildConstraint(); UpdateChildConstraint(childLayoutConstraint, layoutProperty, idealSize.ConvertToSizeT(), childCount, axis); - LOGE("CCCC Measure idealSize: %{public}s, childConstraint: %{public}s", idealSize.ConvertToSizeT().ToString().c_str(), childLayoutConstraint.ToString().c_str()); // Measure children. childrenMainSize_ = 0.0f; @@ -94,7 +94,6 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) if (childGeometryNode) { childrenMainSize_ += childGeometryNode->GetFrameSize().MainSize(axis); } - LOGE("CCCC Measure childSize: %{public}s - %{public}d", childWrapper->GetGeometryNode()->GetFrameSize().ToString().c_str(), index); } } @@ -106,29 +105,31 @@ void TabBarLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) CHECK_NULL_VOID(geometryNode); auto childCount = layoutWrapper->GetTotalChildCount(); auto axis = GetAxis(layoutWrapper); + auto frameSize = geometryNode->GetFrameSize(); - auto parentOffset = - layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); - auto scrollableDistance = std::max(childrenMainSize_ - geometryNode->GetFrameSize().MainSize(axis), 0.0f); + auto parentOffset = geometryNode->GetParentGlobalOffset() + geometryNode->GetFrameOffset(); + auto scrollableDistance = std::max(childrenMainSize_ - frameSize.MainSize(axis), 0.0f); currentOffset_ = std::clamp(currentOffset_, -scrollableDistance, 0.0f); - OffsetF childOffset = (axis == Axis::HORIZONTAL ? - OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_)); + OffsetF childOffset = (axis == Axis::HORIZONTAL ? OffsetF(currentOffset_, 0.0f) : OffsetF(0.0f, currentOffset_)); for (int32_t index = 0; index < childCount; ++index) { auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); - CHECK_NULL_VOID(childWrapper); + if (!childWrapper) { + continue; + } auto childGeometryNode = childWrapper->GetGeometryNode(); - CHECK_NULL_VOID(childGeometryNode); - childGeometryNode->SetFrameOffset(childOffset); + if (!childGeometryNode) { + continue; + } + auto childFrameSize = childGeometryNode->GetFrameSize(); + auto centerOffset = OffsetF(0, (frameSize.Height() - childFrameSize.Height()) / 2.0); // Center child in vertical. + childGeometryNode->SetFrameOffset(childOffset + centerOffset); childWrapper->Layout(parentOffset); tabItemOffset_.emplace_back(childOffset); - LOGE("CCCC Layout childOffset: %{public}s, parentOffset: %{public}s, currentOffset: %{public}lf", - childOffset.ToString().c_str(), parentOffset.ToString().c_str(), currentOffset_); - if (axis == Axis::HORIZONTAL) { - childOffset += OffsetF(childGeometryNode->GetFrameSize().Width(), 0.0f); + childOffset += OffsetF(childFrameSize.Width(), 0.0f); } else { - childOffset += OffsetF(0.0f, childGeometryNode->GetFrameSize().Height()); + childOffset += OffsetF(0.0f, childFrameSize.Height()); } } tabItemOffset_.emplace_back(childOffset); diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h index 1a8eae8b68a..363885efd0d 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h @@ -52,8 +52,8 @@ public: private: Axis GetAxis(LayoutWrapper* layoutWrapper) const; - void UpdateChildConstraint(LayoutConstraintF& childConstraint, - const RefPtr& layoutProperty, const SizeF& ideaSize, int32_t childCount, Axis axis); + void UpdateChildConstraint(LayoutConstraintF& childConstraint, const RefPtr& layoutProperty, + const SizeF& ideaSize, int32_t childCount, Axis axis); std::vector tabItemOffset_; float currentOffset_ = 0.0f; diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h index ed900542212..242d59d0297 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h @@ -25,9 +25,11 @@ namespace OHOS::Ace::NG { +using TabBarBuilderFunc = std::function; struct TabBarParam { std::string text; std::string icon; + TabBarBuilderFunc builder; }; class ACE_EXPORT TabBarLayoutProperty : public LayoutProperty { diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp index 27240b4522d..6bb909908ff 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.cpp @@ -32,26 +32,26 @@ void TabBarPattern::OnAttachToFrameNode() host->GetRenderContext()->SetClipToFrame(true); } -void TabBarPattern::OnModifyDone() +void TabBarPattern::InitClick(const RefPtr& gestureHub) { - auto host = GetHost(); - CHECK_NULL_VOID(host); - auto hub = host->GetEventHub(); - CHECK_NULL_VOID(hub); - auto gestureHub = hub->GetOrCreateGestureEventHub(); - CHECK_NULL_VOID(gestureHub); + if (clickEvent_) { + return; + } - // Init click event. auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) { auto tabBar = weak.Upgrade(); if (tabBar) { tabBar->HandleClick(info); } }; - auto clickEvent = AceType::MakeRefPtr(std::move(clickCallback)); - gestureHub->AddClickEvent(clickEvent); + clickEvent_ = AceType::MakeRefPtr(std::move(clickCallback)); + gestureHub->AddClickEvent(clickEvent_); +} - // Init scrollable. +void TabBarPattern::InitScrollable(const RefPtr& gestureHub) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); auto layoutProperty = host->GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); @@ -79,6 +79,34 @@ void TabBarPattern::OnModifyDone() gestureHub->AddScrollableEvent(scrollableEvent_); } +void TabBarPattern::InitTouch(const RefPtr& gestureHub) +{ + if (touchEvent_) { + return; + } + auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + pattern->HandleTouchEvent(info.GetTouches().front()); + }; + touchEvent_ = MakeRefPtr(std::move(touchCallback)); + gestureHub->AddTouchEvent(touchEvent_); +} + +void TabBarPattern::OnModifyDone() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto hub = host->GetEventHub(); + CHECK_NULL_VOID(hub); + auto gestureHub = hub->GetOrCreateGestureEventHub(); + CHECK_NULL_VOID(gestureHub); + + InitClick(gestureHub); + InitScrollable(gestureHub); + InitTouch(gestureHub); +} + bool TabBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) { if (skipMeasure && skipLayout) { @@ -129,7 +157,8 @@ void TabBarPattern::HandleClick(const GestureEvent& info) const return; } } else { - if (GreatNotEqual(local.GetX(), frameSize.MainSize(axis)) || LessNotEqual(local.GetX(), clickRange.second)) { + if (GreatNotEqual(local.GetX(), frameSize.MainSize(axis)) || + LessNotEqual(local.GetX(), clickRange.second)) { LOGW("clicked (%{public}lf) position out of range [%{public}lf, %{public}lf]", local.GetX(), clickRange.first, clickRange.second); return; @@ -138,20 +167,25 @@ void TabBarPattern::HandleClick(const GestureEvent& info) const } auto pos = std::lower_bound(tabItemOffsets_.begin(), tabItemOffsets_.end(), local, [axis, isRTL = isRTL_](const OffsetF& a, const OffsetF& b) { - return isRTL ? GreatNotEqual(a.GetX(), b.GetX()) - : (axis == Axis::VERTICAL ? LessNotEqual(a.GetY(), b.GetY()) : LessNotEqual(a.GetX(), b.GetX())); + return isRTL + ? GreatNotEqual(a.GetX(), b.GetX()) + : (axis == Axis::VERTICAL ? LessNotEqual(a.GetY(), b.GetY()) : LessNotEqual(a.GetX(), b.GetX())); }); if (pos == tabItemOffsets_.end()) { return; } - auto index = isRTL_ ? std::distance(tabItemOffsets_.begin(), pos) - : std::distance(tabItemOffsets_.begin(), pos) - 1; + auto index = isRTL_ ? std::distance(tabItemOffsets_.begin(), pos) : std::distance(tabItemOffsets_.begin(), pos) - 1; if (index >= 0 && index < totalCount && swiperController_) { swiperController_->SwipeTo(index); } } +void TabBarPattern::HandleTouchEvent(const TouchLocationInfo& info) +{ + // TODO change background color when touch down. +} + void TabBarPattern::UpdateCurrentOffset(float offset) { auto host = GetHost(); diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h index e86ffad9d79..5fff67ec055 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H -#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAR_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAR_PATTERN_H #include @@ -60,17 +60,23 @@ private: void OnAttachToFrameNode() override; bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; + void InitClick(const RefPtr& gestureHub); + void InitScrollable(const RefPtr& gestureHub); + void InitTouch(const RefPtr& gestureHub); void HandleClick(const GestureEvent& info) const; + void HandleTouchEvent(const TouchLocationInfo& info); + RefPtr clickEvent_; + RefPtr touchEvent_; + RefPtr scrollableEvent_; RefPtr swiperController_; - std::vector tabItemOffsets_; float currentOffset_; Axis axis_ = Axis::HORIZONTAL; - RefPtr scrollableEvent_; + std::vector tabItemOffsets_; bool isRTL_ = false; // TODO Adapt RTL. }; } // namespace OHOS::Ace::NG -#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAT_PATTERN_H \ No newline at end of file +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_BAR_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp index e3e29e5901b..d3e8dbb734e 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp @@ -19,27 +19,35 @@ #include "base/utils/utils.h" #include "core/components_ng/base/frame_node.h" #include "core/components_ng/base/view_stack_processor.h" -#include "core/components_ng/pattern/tabs/tab_content_pattern.h" +#include "core/components_ng/pattern/image/image_layout_property.h" +#include "core/components_ng/pattern/image/image_pattern.h" +#include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" #include "core/components_ng/pattern/swiper/swiper_pattern.h" +#include "core/components_ng/pattern/tabs/tab_content_pattern.h" #include "core/components_ng/pattern/text/text_pattern.h" #include "core/components_v2/inspector/inspector_constants.h" namespace OHOS::Ace::NG { namespace { +// TODO use theme constexpr char DEFAULT_TAB_BAR_NAME[] = "TabBar"; +constexpr Dimension DEFAULT_SINGLE_TEXT_FONT_SIZE = 16.0_fp; +constexpr Dimension DEFAULT_SMALL_TEXT_FONT_SIZE = 10.0_fp; +constexpr Dimension DEFAULT_IMAGE_SIZE = 24.0_vp; +constexpr Dimension TAB_BAR_SPACE = 2.0_vp; } // namespace -void TabContentView::Create(std::function&& deepRenderFunc) +void TabContentView::Create(std::function&& deepRenderFunc) { auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); auto deepRender = [nodeId, deepRenderFunc = std::move(deepRenderFunc)]() -> RefPtr { CHECK_NULL_RETURN(deepRenderFunc, nullptr); - deepRenderFunc(nodeId); + deepRenderFunc(); auto deepChild = ViewStackProcessor::GetInstance()->Finish(); - auto parent = FrameNode::GetOrCreateFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, nullptr); + auto parent = FrameNode::GetFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId); if (deepChild && parent) { deepChild->MountToParent(parent); } @@ -50,46 +58,92 @@ void TabContentView::Create(std::function&& deepRenderFunc) return AceType::MakeRefPtr(shallowBuilder); }); stack->Push(frameNode); - SetTabBar(DEFAULT_TAB_BAR_NAME, ""); // Set default tab bar. + SetTabBar(DEFAULT_TAB_BAR_NAME, "", nullptr); // Set default tab bar. } void TabContentView::Create() { auto* stack = ViewStackProcessor::GetInstance(); int32_t nodeId = (stack == nullptr ? 0 : stack->ClaimNodeId()); - auto frameNode = FrameNode::GetOrCreateFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, - []() { return AceType::MakeRefPtr(nullptr); }); + auto frameNode = FrameNode::GetOrCreateFrameNode( + V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(nullptr); }); stack->Push(frameNode); } void TabContentView::Pop() { auto* stack = ViewStackProcessor::GetInstance(); + auto tabsNode = stack->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto tabBarNode = tabsNode->GetChildren().front(); + CHECK_NULL_VOID(tabBarNode); auto tabBarParam = stack->PopTabBar(); + + // Create tab bar with builder. + if (tabBarParam.builder) { + ScopedViewStackProcessor builderViewStackProcessor; + tabBarParam.builder(); + auto builderNode = ViewStackProcessor::GetInstance()->Finish(); + if (builderNode) { + builderNode->MountToParent(tabBarNode); + } + return; + } + if (tabBarParam.text.empty()) { LOGW("Text is empty."); return; } - auto tabsNode = stack->GetMainFrameNode(); - CHECK_NULL_VOID(tabsNode); - auto tabBarNode = tabsNode->GetChildren().front(); - CHECK_NULL_VOID(tabBarNode); - + // Create text node. auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); auto textLayoutProperty = textNode->GetLayoutProperty(); textLayoutProperty->UpdateContent(tabBarParam.text); + textLayoutProperty->UpdateFontSize(DEFAULT_SINGLE_TEXT_FONT_SIZE); textLayoutProperty->UpdateTextAlign(TextAlign::CENTER); textLayoutProperty->UpdateMaxLines(1); textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS); + + if (!tabBarParam.icon.empty()) { + textLayoutProperty->UpdateFontSize(DEFAULT_SMALL_TEXT_FONT_SIZE); + // Create column node to contain image and text node. + auto columnNode = + FrameNode::GetOrCreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + []() { return AceType::MakeRefPtr(true); }); + auto linearLayoutProperty = columnNode->GetLayoutProperty(); + CHECK_NULL_VOID(linearLayoutProperty); + linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); + linearLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER); + linearLayoutProperty->UpdateSpace(TAB_BAR_SPACE); + + // Create image node. + ImageSourceInfo imageSourceInfo(tabBarParam.icon); + auto imageNode = + FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + [imageSourceInfo]() { return AceType::MakeRefPtr(imageSourceInfo); }); + auto imageProperty = imageNode->GetLayoutProperty(); + CHECK_NULL_VOID(imageProperty); + imageProperty->UpdateImageSourceInfo(imageSourceInfo); + imageProperty->UpdateCalcSelfIdealSize( + CalcSize(NG::CalcLength(DEFAULT_IMAGE_SIZE), NG::CalcLength(DEFAULT_IMAGE_SIZE))); + + columnNode->MountToParent(tabBarNode); + imageNode->MountToParent(columnNode); + imageNode->MarkModifyDone(); + textNode->MountToParent(columnNode); + textNode->MarkModifyDone(); + columnNode->MarkModifyDone(); + return; + } + textNode->MountToParent(tabBarNode); textNode->MarkModifyDone(); } -void TabContentView::SetTabBar(const std::string& text, const std::string& icon) +void TabContentView::SetTabBar(const std::string& text, const std::string& icon, TabBarBuilderFunc&& builder) { - TabBarParam tabBarParam { .text = text, .icon = icon }; + TabBarParam tabBarParam { .text = text, .icon = icon, .builder = std::move(builder) }; ViewStackProcessor::GetInstance()->PushTabBar(tabBarParam); } diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.h b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h index 8b7713a8ee7..6f758568fde 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_content_view.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h @@ -21,15 +21,16 @@ #include "base/memory/referenced.h" #include "base/utils/macros.h" #include "core/components/common/layout/constants.h" +#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" namespace OHOS::Ace::NG { class ACE_EXPORT TabContentView { public: - static void Create(std::function&& deepRenderFunc); + static void Create(std::function&& deepRenderFunc); static void Create(); static void Pop(); - static void SetTabBar(const std::string& text, const std::string& icon); + static void SetTabBar(const std::string& text, const std::string& icon, TabBarBuilderFunc&& builder); }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp index bcd75357337..8da21bfb223 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_layout_algorithm.cpp @@ -36,6 +36,11 @@ void TabsLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL); auto constraint = layoutProperty->GetLayoutConstraint(); auto idealSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true); + if (GreatOrEqual(idealSize.Width(), Infinity()) || GreatOrEqual(idealSize.Height(), Infinity())) { + LOGW("Size is infinity."); + geometryNode->SetFrameSize(SizeF()); + return; + } geometryNode->SetFrameSize(idealSize); auto childLayoutConstraint = layoutProperty->CreateChildConstraint(); childLayoutConstraint.parentIdealSize = OptionalSizeF(idealSize); @@ -47,7 +52,6 @@ void TabsLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) tabBarWrapper->Measure(childLayoutConstraint); tabBarSize = tabBarWrapper->GetGeometryNode()->GetFrameSize(); } - LOGE("CCCC Measure tabBarSize: %{public}s, childConstraint: %{public}s", tabBarSize.ToString().c_str(), childLayoutConstraint.ToString().c_str()); // Measure swiper. auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(1); @@ -62,8 +66,6 @@ void TabsLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) } childLayoutConstraint.parentIdealSize = OptionalSizeF(parentIdealSize); swiperWrapper->Measure(childLayoutConstraint); - LOGE("CCCC Measure swiper size: %{public}s, childLayoutConstraint: %{public}s", - swiperWrapper->GetGeometryNode()->GetFrameSize().ToString().c_str(), childLayoutConstraint.ToString().c_str()); } } @@ -73,6 +75,10 @@ void TabsLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto geometryNode = layoutWrapper->GetGeometryNode(); CHECK_NULL_VOID(geometryNode); auto frameSize = geometryNode->GetFrameSize(); + if (!frameSize.IsPositive()) { + LOGW("Frame size is not positive."); + return; + } auto tabBarWrapper = layoutWrapper->GetOrCreateChildByIndex(0); auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(1); @@ -101,7 +107,8 @@ void TabsLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) tabBarOffset = OffsetF(); swiperOffset = OffsetF(tabBarFrameSize.MainSize(Axis::HORIZONTAL), 0.0f); } else { - tabBarOffset = OffsetF(frameSize.MainSize(Axis::HORIZONTAL) - tabBarFrameSize.MainSize(Axis::HORIZONTAL), 0.0); + tabBarOffset = + OffsetF(frameSize.MainSize(Axis::HORIZONTAL) - tabBarFrameSize.MainSize(Axis::HORIZONTAL), 0.0f); swiperOffset = OffsetF(); } } @@ -109,7 +116,6 @@ void TabsLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto parentOffset = geometryNode->GetParentGlobalOffset() + geometryNode->GetFrameOffset(); tabBarGeometryNode->SetFrameOffset(tabBarOffset); tabBarWrapper->Layout(parentOffset); - LOGE("CCCC Layout tabBarOffset: %{public}s, parentOffset: %{public}s", tabBarOffset.ToString().c_str(), parentOffset.ToString().c_str()); swiperWrapper->GetGeometryNode()->SetFrameOffset(swiperOffset); swiperWrapper->Layout(parentOffset); diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.h b/frameworks/core/components_ng/pattern/tabs/tabs_node.h index 2167b7a95a6..7eca1e54d9e 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_node.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.h @@ -25,7 +25,8 @@ class ACE_EXPORT TabsNode : public GroupNode { public: TabsNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot = false) - : GroupNode(tag, nodeId, pattern, isRoot) {} + : GroupNode(tag, nodeId, pattern, isRoot) + {} ~TabsNode() override = default; void AddChildToGroup(const RefPtr& child) override; }; diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h index 0e9aa923ccf..45b8b0b45bc 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h @@ -55,6 +55,6 @@ private: void OnAttachToFrameNode() override; bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; }; -} // namespace OHOS::Ace::NG +} // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp index bfcbfc4ea56..031a67f6b6d 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp @@ -14,6 +14,7 @@ */ #include "core/components_ng/pattern/tabs/tabs_view.h" + #include #include "base/memory/referenced.h" @@ -38,12 +39,11 @@ void TabsView::Create() { auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); - auto groupNode = GetOrCreateGroupNode(V2::TABS_ETS_TAG, nodeId, - []() { return AceType::MakeRefPtr(); }); + auto groupNode = CreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); // Create Swiper node to contain TabContent. - auto swiperNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - []() { return AceType::MakeRefPtr(); }); + auto swiperNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); auto swiperPaintProperty = swiperNode->GetPaintProperty(); swiperPaintProperty->UpdateLoop(false); auto swiperPattern = swiperNode->GetPattern(); @@ -51,8 +51,9 @@ void TabsView::Create() auto swiperController = swiperPattern->GetSwiperController(); // Create TabBar to contain TabBar of TabContent. - auto tabBarNode = FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - [swiperController]() { return AceType::MakeRefPtr(swiperController); }); + auto tabBarNode = + FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + [swiperController]() { return AceType::MakeRefPtr(swiperController); }); auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); tabBarNode->MountToParent(groupNode); @@ -61,24 +62,6 @@ void TabsView::Create() ViewStackProcessor::GetInstance()->Push(groupNode); } -RefPtr TabsView::GetGroupNode(const std::string& tag, int32_t nodeId) -{ - auto groupNode = ElementRegister::GetInstance()->GetSpecificItemById(nodeId); - if (!groupNode) { - return nullptr; - } - if (groupNode->GetTag() != tag) { - LOGE("the tag is changed"); - ElementRegister::GetInstance()->RemoveItemSilently(nodeId); - auto parent = groupNode->GetParent(); - if (parent) { - parent->RemoveChild(groupNode); - } - return nullptr; - } - return groupNode; -} - void TabsView::SetTabBarPosition(BarPosition tabBarPosition) { ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarPosition, tabBarPosition); @@ -149,6 +132,17 @@ void TabsView::SetAnimationDuration(int32_t duration) swiperPaintProperty->UpdateDuration(duration); } +void TabsView::SetOnChange(ChangeEvent&& onChange) +{ + auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(tabsNode); + auto swiperNode = AceType::DynamicCast(tabsNode->GetChildren().back()); + CHECK_NULL_VOID(swiperNode); + auto eventHub = swiperNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnChange(std::move(onChange)); +} + RefPtr TabsView::GetTabBarLayoutProperty() { auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); @@ -206,24 +200,27 @@ void TabsView::Pop() swiperNode->MarkModifyDone(); } -RefPtr TabsView::CreateGroupNode( - const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot) -{ - auto groupNode = AceType::MakeRefPtr(tag, nodeId, pattern, isRoot); - groupNode->InitializePatternAndContext(); - ElementRegister::GetInstance()->AddUINode(groupNode); - return groupNode; -} - -RefPtr TabsView::GetOrCreateGroupNode( +RefPtr TabsView::CreateTabsNode( const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator) { - auto groupNode = GetGroupNode(tag, nodeId); + RefPtr groupNode; + groupNode = ElementRegister::GetInstance()->GetSpecificItemById(nodeId); if (groupNode) { - return groupNode; + if (groupNode->GetTag() == tag) { + return groupNode; + } + ElementRegister::GetInstance()->RemoveItemSilently(nodeId); + auto parent = groupNode->GetParent(); + if (parent) { + parent->RemoveChild(groupNode); + } } + auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr(); - return CreateGroupNode(tag, nodeId, pattern); + groupNode = AceType::MakeRefPtr(tag, nodeId, pattern, false); + groupNode->InitializePatternAndContext(); + ElementRegister::GetInstance()->AddUINode(groupNode); + return groupNode; } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.h b/frameworks/core/components_ng/pattern/tabs/tabs_view.h index 15a9319698c..d52a3473737 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.h @@ -22,6 +22,7 @@ #include "base/utils/macros.h" #include "core/components/common/layout/constants.h" #include "core/components_ng/base/group_node.h" +#include "core/components_ng/pattern/swiper/swiper_event_hub.h" #include "core/components_ng/pattern/swiper/swiper_layout_property.h" #include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" @@ -40,17 +41,13 @@ public: static void SetAxis(Axis axis); static void SetScrollable(bool scrollable); static void SetAnimationDuration(int32_t duration); + static void SetOnChange(ChangeEvent&& onChange); static RefPtr GetSwiperController(); - static RefPtr GetOrCreateGroupNode( + static RefPtr CreateTabsNode( const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator); - static RefPtr CreateGroupNode( - const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot = false); - - static RefPtr GetGroupNode(const std::string& tag, int32_t nodeId); - private: static RefPtr GetTabBarLayoutProperty(); static RefPtr GetSwiperLayoutProperty(); -- Gitee From 250a33b0af8b0354ddc3a2fb98bc0fda935b1eaf Mon Sep 17 00:00:00 2001 From: caocan Date: Wed, 7 Sep 2022 17:36:10 +0800 Subject: [PATCH 4/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]Tab?= =?UTF-8?q?s=E5=AF=B9=E6=8E=A5=E6=87=92=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: Ic8f62cb111e1026744456a536ab3e649efbad80b --- .../jsview/js_lazy_foreach.cpp | 15 +++++++++++++++ .../core/components_ng/syntax/lazy_for_each.h | 8 +++++++- .../components_ng/syntax/lazy_for_each_builder.h | 6 ++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp b/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp index cb41c6a543b..8921b9aef6a 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp @@ -494,6 +494,21 @@ public: return GetTotalIndexCount(); } + void OnExpandChildrenOnInitial() override + { + auto totalIndex = GetTotalIndexCount(); + auto* stack = NG::ViewStackProcessor::GetInstance(); + JSRef params[2]; + for (auto index = 0; index < totalIndex; index++) { + params[0] = CallJSFunction(getDataFunc_, dataSourceObj_, index); + params[1] = JSRef::Make(ToJSValue(index)); + std::string key = keyGenFunc_(params[0], index); + stack->PushKey(key); + itemGenFunc_->Call(JSRef(), 2, params); + stack->PopKey(); + } + } + std::pair> OnGetChildByIndex(int32_t index) override { std::pair> info; diff --git a/frameworks/core/components_ng/syntax/lazy_for_each.h b/frameworks/core/components_ng/syntax/lazy_for_each.h index 817ca064c75..c09f6925a65 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each.h +++ b/frameworks/core/components_ng/syntax/lazy_for_each.h @@ -28,8 +28,14 @@ public: { auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); + + if (stack->GetMainFrameNode()->GetTag() == V2::TABS_ETS_TAG) { + forEachBuilder->ExpandChildrenOnInitial(); + return; + } + auto lazyForEach = LazyForEachNode::GetOrCreateLazyForEachNode(nodeId, forEachBuilder); - ViewStackProcessor::GetInstance()->Push(lazyForEach); + stack->Push(lazyForEach); } }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h index 98b657f905c..ffa29eebed6 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h +++ b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h @@ -64,6 +64,11 @@ public: return cachedItems_; } + void ExpandChildrenOnInitial() + { + OnExpandChildrenOnInitial(); + } + void OnDataReloaded() override {} void OnDataAdded(size_t index) override {} void OnDataDeleted(size_t index) override {} @@ -77,6 +82,7 @@ public: protected: virtual int32_t OnGetTotalCount() = 0; virtual std::pair> OnGetChildByIndex(int32_t index) = 0; + virtual void OnExpandChildrenOnInitial() = 0; private: // [index : [key, UINode]] -- Gitee From 6c5338b7639ee0639fd8bd9026c9f08ec632c7d1 Mon Sep 17 00:00:00 2001 From: caocan Date: Fri, 9 Sep 2022 10:15:25 +0800 Subject: [PATCH 5/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: I9088c543447f59c53e585b857d3ee55a0ef27f66 --- .../jsview/js_lazy_foreach.cpp | 2 +- .../jsview/js_tab_content.cpp | 10 ++- .../declarative_frontend/jsview/js_tabs.cpp | 1 + .../jsview/js_tabs_controller.h | 2 +- .../core/components_ng/base/ui_node.cpp | 35 +++++++- frameworks/core/components_ng/base/ui_node.h | 3 +- .../components_ng/base/view_stack_processor.h | 2 +- .../pattern/swiper/swiper_pattern.cpp | 1 + .../pattern/tabs/tab_bar_layout_algorithm.cpp | 20 ++--- .../pattern/tabs/tab_bar_layout_property.h | 25 +++--- .../pattern/tabs/tab_bar_pattern.h | 9 +- .../pattern/tabs/tab_content_view.cpp | 89 +++++++++++-------- .../pattern/tabs/tab_content_view.h | 4 +- .../components_ng/pattern/tabs/tabs_node.cpp | 6 ++ .../components_ng/pattern/tabs/tabs_node.h | 57 ++++++++++++ .../pattern/tabs/tabs_pattern.cpp | 12 --- .../components_ng/pattern/tabs/tabs_pattern.h | 2 - .../components_ng/pattern/tabs/tabs_view.cpp | 54 ++++++----- .../components_ng/pattern/tabs/tabs_view.h | 8 +- .../pattern/text/text_paint_method.h | 3 +- .../syntax/lazy_for_each_builder.h | 4 +- 21 files changed, 227 insertions(+), 122 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp b/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp index 8921b9aef6a..2f7ee5091d3 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.cpp @@ -494,7 +494,7 @@ public: return GetTotalIndexCount(); } - void OnExpandChildrenOnInitial() override + void OnExpandChildrenOnInitialInNG() override { auto totalIndex = GetTotalIndexCount(); auto* stack = NG::ViewStackProcessor::GetInstance(); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp index 32aac82a0ea..ca91bd94977 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tab_content.cpp @@ -16,6 +16,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_tab_content.h" #include "base/log/ace_trace.h" +#include "core/components_ng/base/view_stack_processor.h" #include "core/components_ng/pattern/tabs/tab_content_view.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" @@ -295,8 +296,13 @@ RefPtr JSTabContent::ProcessTabBarTextIconPair( void JSTabContent::Pop() { - JSContainerBase::Pop(); - NG::TabContentView::Pop(); + if (Container::IsCurrentUseNewPipeline()) { + auto tabContent = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode(); + NG::ViewStackProcessor::GetInstance()->PopContainer(); + NG::TabContentView::Pop(tabContent); + } else { + JSContainerBase::Pop(); + } } void JSTabContent::JSBind(BindingTarget globalObj) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp index d5b02971139..b6742f5c783 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp @@ -158,6 +158,7 @@ void JSTabs::CreateForNG(const JSCallbackInfo& info) void JSTabs::Pop() { + LOGE("CCCC JSTabs::Pop"); if (Container::IsCurrentUseNewPipeline()) { NG::TabsView::Pop(); NG::ViewStackProcessor::GetInstance()->PopContainer(); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h index fa4a2219232..e2dc571ad74 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs_controller.h @@ -48,7 +48,7 @@ public: private: RefPtr controller_; - RefPtr swiperController_; + RefPtr swiperController_; // used by ng structure ACE_DISALLOW_COPY_AND_MOVE(JSTabsController); }; diff --git a/frameworks/core/components_ng/base/ui_node.cpp b/frameworks/core/components_ng/base/ui_node.cpp index 958bba320f4..db284269519 100644 --- a/frameworks/core/components_ng/base/ui_node.cpp +++ b/frameworks/core/components_ng/base/ui_node.cpp @@ -14,6 +14,7 @@ */ #include "core/components_ng/base/ui_node.h" +#include #include "base/geometry/ng/point_t.h" #include "base/log/ace_trace.h" @@ -58,15 +59,45 @@ void UINode::AddChild(const RefPtr& child, int32_t slot) MarkNeedSyncRenderTree(); } -void UINode::RemoveChild(const RefPtr& child) +std::list>::iterator UINode::RemoveChild(const RefPtr& child) { - CHECK_NULL_VOID(child); + CHECK_NULL_RETURN(child, children_.end()); + + auto iter = std::find(children_.begin(), children_.end(), child); + if (iter == children_.end()) { + LOGE("child is not exist."); + return children_.end(); + } + + auto result = children_.erase(iter); if (onMainTree_) { child->DetachFromMainTree(); } OnChildRemoved(child); children_.remove(child); MarkNeedSyncRenderTree(); + return result; +} + +void UINode::ReplaceChild(const RefPtr& oldNode, const RefPtr& newNode) +{ + if (!oldNode) { + if (newNode) { + AddChild(newNode); + } + return; + } + + + auto iter = RemoveChild(oldNode); + children_.insert(iter, newNode); + newNode->SetParent(Claim(this)); + newNode->SetDepth(GetDepth() + 1); + if (onMainTree_) { + newNode->AttachToMainTree(); + } + OnChildAdded(newNode); + MarkNeedSyncRenderTree(); } void UINode::MountToParent(const RefPtr& parent, int32_t slot) diff --git a/frameworks/core/components_ng/base/ui_node.h b/frameworks/core/components_ng/base/ui_node.h index d7ecdf59eeb..bcdaf7706d3 100644 --- a/frameworks/core/components_ng/base/ui_node.h +++ b/frameworks/core/components_ng/base/ui_node.h @@ -47,7 +47,8 @@ public: // Tree operation start. void AddChild(const RefPtr& child, int32_t slot = DEFAULT_NODE_SLOT); - void RemoveChild(const RefPtr& child); + std::list>::iterator RemoveChild(const RefPtr& child); + void ReplaceChild(const RefPtr& oldNode, const RefPtr& newNode); void MovePosition(int32_t slot); void MountToParent(const RefPtr& parent, int32_t slot = DEFAULT_NODE_SLOT); diff --git a/frameworks/core/components_ng/base/view_stack_processor.h b/frameworks/core/components_ng/base/view_stack_processor.h index 0b6866603a2..6402aaa476c 100644 --- a/frameworks/core/components_ng/base/view_stack_processor.h +++ b/frameworks/core/components_ng/base/view_stack_processor.h @@ -26,7 +26,7 @@ #include "core/components_ng/base/ui_node.h" #include "core/components_ng/layout/layout_property.h" #include "core/components_ng/pattern/custom/custom_node.h" -#include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" +#include "core/components_ng/pattern/tabs/tab_bar_pattern.h" #include "core/gestures/gesture_processor.h" #include "core/pipeline/base/render_context.h" diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp index 582f43bcaad..b4e6cc6c350 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.cpp @@ -87,6 +87,7 @@ void SwiperPattern::OnModifyDone() if (IsDisableSwipe()) { if (panEvent_) { gestureHub->RemovePanEvent(panEvent_); + panEvent_.Reset(); } return; } diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp index 235af85dae3..71361574e6d 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_algorithm.cpp @@ -29,6 +29,7 @@ namespace OHOS::Ace::NG { namespace { +// TODO use theme constexpr Dimension TAB_BAR_DEFAULT_SIZE = 56.0_vp; } // namespace @@ -37,7 +38,7 @@ void TabBarLayoutAlgorithm::UpdateChildConstraint(LayoutConstraintF& childConstr const RefPtr& layoutProperty, const SizeF& ideaSize, int32_t childCount, Axis axis) { childConstraint.parentIdealSize = OptionalSizeF(ideaSize); - auto barMode = layoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED); + const auto& barMode = layoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED); if (barMode == TabBarMode::FIXED) { auto childIdeaSize = ideaSize; if (axis == Axis::HORIZONTAL) { @@ -65,8 +66,7 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) auto constraint = layoutProperty->GetLayoutConstraint(); auto idealSize = CreateIdealSize(constraint.value(), axis, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)); - auto scale = layoutProperty->GetLayoutConstraint()->scaleProperty; - auto defaultSize = ConvertToPx(TAB_BAR_DEFAULT_SIZE, scale, 0).value_or(0); + auto defaultSize = static_cast(TAB_BAR_DEFAULT_SIZE.ConvertToPx()); if (!constraint->selfIdealSize.Width().has_value() && axis == Axis::VERTICAL) { idealSize.SetWidth(defaultSize); } @@ -86,14 +86,10 @@ void TabBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index); if (!childWrapper) { LOGI("Child %{public}d is null.", index); - return; + continue; } childWrapper->Measure(childLayoutConstraint); - - auto childGeometryNode = childWrapper->GetGeometryNode(); - if (childGeometryNode) { - childrenMainSize_ += childGeometryNode->GetFrameSize().MainSize(axis); - } + childrenMainSize_ += childWrapper->GetGeometryNode()->GetFrameSize().MainSize(axis); } } @@ -117,11 +113,9 @@ void TabBarLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) continue; } auto childGeometryNode = childWrapper->GetGeometryNode(); - if (!childGeometryNode) { - continue; - } auto childFrameSize = childGeometryNode->GetFrameSize(); - auto centerOffset = OffsetF(0, (frameSize.Height() - childFrameSize.Height()) / 2.0); // Center child in vertical. + auto centerOffset = + OffsetF(0, (frameSize.Height() - childFrameSize.Height()) / 2.0); // Center child in vertical. childGeometryNode->SetFrameOffset(childOffset + centerOffset); childWrapper->Layout(parentOffset); tabItemOffset_.emplace_back(childOffset); diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h index 242d59d0297..d6e0332d0bd 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_layout_property.h @@ -25,11 +25,10 @@ namespace OHOS::Ace::NG { -using TabBarBuilderFunc = std::function; -struct TabBarParam { - std::string text; - std::string icon; - TabBarBuilderFunc builder; +struct TabBarProperty { + ACE_DEFINE_PROPERTY_GROUP_ITEM(TabBarMode, TabBarMode); + ACE_DEFINE_PROPERTY_GROUP_ITEM(TabBarWidth, Dimension); + ACE_DEFINE_PROPERTY_GROUP_ITEM(TabBarHeight, Dimension); }; class ACE_EXPORT TabBarLayoutProperty : public LayoutProperty { @@ -43,9 +42,7 @@ public: { auto value = MakeRefPtr(); value->LayoutProperty::UpdateLayoutProperty(AceType::DynamicCast(this)); - value->propTabBarMode_ = CloneTabBarMode(); - value->propTabBarWidth_ = CloneTabBarWidth(); - value->propTabBarHeight_ = CloneTabBarHeight(); + value->propTabBarProperty_ = CloneTabBarProperty(); value->propAxis_ = CloneAxis(); return value; } @@ -53,15 +50,15 @@ public: void Reset() override { LayoutProperty::Reset(); - ResetTabBarMode(); - ResetTabBarWidth(); - ResetTabBarHeight(); + ResetTabBarProperty(); ResetAxis(); } - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarMode, TabBarMode, PROPERTY_UPDATE_LAYOUT); - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarWidth, Dimension, PROPERTY_UPDATE_LAYOUT); - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(TabBarHeight, Dimension, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_GROUP(TabBarProperty, TabBarProperty); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TabBarProperty, TabBarMode, TabBarMode, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TabBarProperty, TabBarWidth, Dimension, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TabBarProperty, TabBarHeight, Dimension, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Axis, Axis, PROPERTY_UPDATE_LAYOUT); }; diff --git a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h index 5fff67ec055..9469771b6be 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_bar_pattern.h @@ -29,6 +29,13 @@ namespace OHOS::Ace::NG { +using TabBarBuilderFunc = std::function; +struct TabBarParam { + std::string text; + std::string icon; + TabBarBuilderFunc builder; +}; + class TabBarPattern : public Pattern { DECLARE_ACE_TYPE(TabBarPattern, Pattern); @@ -71,7 +78,7 @@ private: RefPtr scrollableEvent_; RefPtr swiperController_; - float currentOffset_; + float currentOffset_ = 0.0f; Axis axis_ = Axis::HORIZONTAL; std::vector tabItemOffsets_; diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp index d3e8dbb734e..23198ba52cb 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.cpp @@ -23,7 +23,9 @@ #include "core/components_ng/pattern/image/image_pattern.h" #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" #include "core/components_ng/pattern/swiper/swiper_pattern.h" +#include "core/components_ng/pattern/tabs/tab_bar_pattern.h" #include "core/components_ng/pattern/tabs/tab_content_pattern.h" +#include "core/components_ng/pattern/tabs/tabs_node.h" #include "core/components_ng/pattern/text/text_pattern.h" #include "core/components_v2/inspector/inspector_constants.h" @@ -64,19 +66,24 @@ void TabContentView::Create(std::function&& deepRenderFunc) void TabContentView::Create() { auto* stack = ViewStackProcessor::GetInstance(); - int32_t nodeId = (stack == nullptr ? 0 : stack->ClaimNodeId()); + int32_t nodeId = stack->ClaimNodeId(); auto frameNode = FrameNode::GetOrCreateFrameNode( V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(nullptr); }); stack->Push(frameNode); } -void TabContentView::Pop() +void TabContentView::Pop(const RefPtr& tabContent) { - auto* stack = ViewStackProcessor::GetInstance(); - auto tabsNode = stack->GetMainFrameNode(); + CHECK_NULL_VOID(tabContent); + auto tabContentId = tabContent->GetId(); + auto swiperNode = tabContent->GetParent(); + CHECK_NULL_VOID(swiperNode); + auto tabsNode = AceType::DynamicCast(swiperNode->GetParent()); CHECK_NULL_VOID(tabsNode); auto tabBarNode = tabsNode->GetChildren().front(); CHECK_NULL_VOID(tabBarNode); + + auto* stack = ViewStackProcessor::GetInstance(); auto tabBarParam = stack->PopTabBar(); // Create tab bar with builder. @@ -84,9 +91,7 @@ void TabContentView::Pop() ScopedViewStackProcessor builderViewStackProcessor; tabBarParam.builder(); auto builderNode = ViewStackProcessor::GetInstance()->Finish(); - if (builderNode) { - builderNode->MountToParent(tabBarNode); - } + tabBarNode->ReplaceChild(tabsNode->GetBuilderByContentId(tabContentId, builderNode), builderNode); return; } @@ -95,50 +100,60 @@ void TabContentView::Pop() return; } - // Create text node. - auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - []() { return AceType::MakeRefPtr(); }); + // Create column node to contain image and text node. + auto columnNode = FrameNode::GetOrCreateFrameNode(V2::COLUMN_ETS_TAG, tabsNode->GetTabBarByContentId(tabContentId), + []() { return AceType::MakeRefPtr(true); }); + auto linearLayoutProperty = columnNode->GetLayoutProperty(); + CHECK_NULL_VOID(linearLayoutProperty); + linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); + linearLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER); + linearLayoutProperty->UpdateSpace(TAB_BAR_SPACE); + columnNode->GetRenderContext()->UpdateBackgroundColor(Color::BLUE); + + // Create text node and image node. + RefPtr textNode; + RefPtr imageNode; + if (static_cast(columnNode->GetChildren().size()) == 0) { + ImageSourceInfo imageSourceInfo(tabBarParam.icon); + imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + [imageSourceInfo]() { return AceType::MakeRefPtr(imageSourceInfo); }); + textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + []() { return AceType::MakeRefPtr(); }); + columnNode->MountToParent(tabBarNode); + imageNode->MountToParent(columnNode); + textNode->MountToParent(columnNode); + } else { + imageNode = AceType::DynamicCast(columnNode->GetChildren().front()); + textNode = AceType::DynamicCast(columnNode->GetChildren().back()); + } + CHECK_NULL_VOID(textNode); + CHECK_NULL_VOID(imageNode); + + // Update property of text. auto textLayoutProperty = textNode->GetLayoutProperty(); + CHECK_NULL_VOID(textLayoutProperty); textLayoutProperty->UpdateContent(tabBarParam.text); textLayoutProperty->UpdateFontSize(DEFAULT_SINGLE_TEXT_FONT_SIZE); textLayoutProperty->UpdateTextAlign(TextAlign::CENTER); textLayoutProperty->UpdateMaxLines(1); textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS); + // Update property of image. + auto imageProperty = imageNode->GetLayoutProperty(); + CHECK_NULL_VOID(imageProperty); if (!tabBarParam.icon.empty()) { textLayoutProperty->UpdateFontSize(DEFAULT_SMALL_TEXT_FONT_SIZE); - // Create column node to contain image and text node. - auto columnNode = - FrameNode::GetOrCreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - []() { return AceType::MakeRefPtr(true); }); - auto linearLayoutProperty = columnNode->GetLayoutProperty(); - CHECK_NULL_VOID(linearLayoutProperty); - linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); - linearLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER); - linearLayoutProperty->UpdateSpace(TAB_BAR_SPACE); - - // Create image node. - ImageSourceInfo imageSourceInfo(tabBarParam.icon); - auto imageNode = - FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - [imageSourceInfo]() { return AceType::MakeRefPtr(imageSourceInfo); }); - auto imageProperty = imageNode->GetLayoutProperty(); - CHECK_NULL_VOID(imageProperty); - imageProperty->UpdateImageSourceInfo(imageSourceInfo); imageProperty->UpdateCalcSelfIdealSize( CalcSize(NG::CalcLength(DEFAULT_IMAGE_SIZE), NG::CalcLength(DEFAULT_IMAGE_SIZE))); - - columnNode->MountToParent(tabBarNode); - imageNode->MountToParent(columnNode); - imageNode->MarkModifyDone(); - textNode->MountToParent(columnNode); - textNode->MarkModifyDone(); - columnNode->MarkModifyDone(); - return; + } else { + imageProperty->UpdateCalcSelfIdealSize(CalcSize()); } + ImageSourceInfo imageSourceInfo(tabBarParam.icon); + imageProperty->UpdateImageSourceInfo(imageSourceInfo); - textNode->MountToParent(tabBarNode); + imageNode->MarkModifyDone(); textNode->MarkModifyDone(); + columnNode->MarkModifyDone(); } void TabContentView::SetTabBar(const std::string& text, const std::string& icon, TabBarBuilderFunc&& builder) diff --git a/frameworks/core/components_ng/pattern/tabs/tab_content_view.h b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h index 6f758568fde..7a53ee8c201 100644 --- a/frameworks/core/components_ng/pattern/tabs/tab_content_view.h +++ b/frameworks/core/components_ng/pattern/tabs/tab_content_view.h @@ -22,6 +22,7 @@ #include "base/utils/macros.h" #include "core/components/common/layout/constants.h" #include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" +#include "core/components_ng/pattern/tabs/tab_bar_pattern.h" namespace OHOS::Ace::NG { @@ -29,10 +30,9 @@ class ACE_EXPORT TabContentView { public: static void Create(std::function&& deepRenderFunc); static void Create(); - static void Pop(); + static void Pop(const RefPtr& tabContent); static void SetTabBar(const std::string& text, const std::string& icon, TabBarBuilderFunc&& builder); }; } // namespace OHOS::Ace::NG - #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_VIEW_H diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp index 810a09eab9e..c2861e6df0a 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp @@ -19,6 +19,12 @@ namespace OHOS::Ace::NG { void TabsNode::AddChildToGroup(const RefPtr& child) { + if (swiperChildren_.find(child->GetId()) != swiperChildren_.end()) { + LOGW("Child has already exist."); + return; + } + + swiperChildren_.emplace(child->GetId()); auto swiperNode = GetChildren().back(); if (swiperNode) { child->MountToParent(swiperNode); diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.h b/frameworks/core/components_ng/pattern/tabs/tabs_node.h index 7eca1e54d9e..92a03b17a3b 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_node.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.h @@ -16,6 +16,7 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H +#include #include "core/components_ng/base/group_node.h" namespace OHOS::Ace::NG { @@ -29,6 +30,62 @@ public: {} ~TabsNode() override = default; void AddChildToGroup(const RefPtr& child) override; + + bool HasSwiperNode() const + { + return swiperId_.has_value(); + } + + bool HasTabBarNode() const + { + return tabBarId_.has_value(); + } + + int32_t GetSwiperId() + { + if (!swiperId_.has_value()) { + swiperId_ = ElementRegister::GetInstance()->MakeUniqueId(); + } + return swiperId_.value(); + } + + int32_t GetTabBarId() + { + if (!tabBarId_.has_value()) { + tabBarId_ = ElementRegister::GetInstance()->MakeUniqueId(); + } + return tabBarId_.value(); + } + + int32_t GetTabBarByContentId(int32_t tabContentId) + { + auto iter = tabBarNode_.find(tabContentId); + if (iter == tabBarNode_.end()) { + auto tabBarId = ElementRegister::GetInstance()->MakeUniqueId(); + tabBarNode_.try_emplace(tabContentId, tabBarId); + return tabBarId; + } + return iter->second; + } + + RefPtr GetBuilderByContentId(int32_t tabContentId, const RefPtr& builderNode) + { + auto iter = builderNode_.find(tabContentId); + if (iter == builderNode_.end()) { + builderNode_.try_emplace(tabContentId, builderNode); + return nullptr; + } + auto result = iter->second; + builderNode_[tabContentId] = builderNode; + return result; + } + +private: + std::optional swiperId_; + std::optional tabBarId_; + std::set swiperChildren_; + std::map tabBarNode_; // Key is id of TabContent, value is id of Column of TabBar. + std::map> builderNode_; // Key is id of TabContent, value is id of builder of TabBar. }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp index a994d417c7f..5900ca65faf 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp @@ -31,16 +31,4 @@ void TabsPattern::OnAttachToFrameNode() host->GetRenderContext()->SetClipToFrame(true); } -void TabsPattern::OnModifyDone() {} - -bool TabsPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) -{ - if (skipMeasure && skipLayout) { - return false; - } - auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); - CHECK_NULL_RETURN(layoutAlgorithmWrapper, false); - return false; -} - } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h index 45b8b0b45bc..db865c4eb8c 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_pattern.h @@ -51,9 +51,7 @@ public: } private: - void OnModifyDone() override; void OnAttachToFrameNode() override; - bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp index 031a67f6b6d..d3df1598974 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp @@ -39,27 +39,34 @@ void TabsView::Create() { auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); - auto groupNode = CreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + LOGE("CCCC TabsView::Create: %{public}d", nodeId); + auto tabsNode = GetOrCreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + bool hasSwiperNode = tabsNode->HasSwiperNode(); + bool hasTabBarNode = tabsNode->HasTabBarNode(); + auto swiperId = tabsNode->GetSwiperId(); + auto tabBarId = tabsNode->GetTabBarId(); // Create Swiper node to contain TabContent. - auto swiperNode = FrameNode::GetOrCreateFrameNode(V2::SWIPER_ETS_TAG, - ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); + auto swiperNode = FrameNode::GetOrCreateFrameNode( + V2::SWIPER_ETS_TAG, swiperId, []() { return AceType::MakeRefPtr(); }); auto swiperPaintProperty = swiperNode->GetPaintProperty(); swiperPaintProperty->UpdateLoop(false); + swiperPaintProperty->UpdateEdgeEffect(EdgeEffect::NONE); auto swiperPattern = swiperNode->GetPattern(); CHECK_NULL_VOID(swiperPattern); auto swiperController = swiperPattern->GetSwiperController(); // Create TabBar to contain TabBar of TabContent. - auto tabBarNode = - FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), - [swiperController]() { return AceType::MakeRefPtr(swiperController); }); - auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty(); - - tabBarNode->MountToParent(groupNode); - swiperNode->MountToParent(groupNode); - - ViewStackProcessor::GetInstance()->Push(groupNode); + auto tabBarNode = FrameNode::GetOrCreateFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId, + [swiperController]() { return AceType::MakeRefPtr(swiperController); }); + if (!hasSwiperNode) { + tabBarNode->MountToParent(tabsNode); + } + if (!hasTabBarNode) { + swiperNode->MountToParent(tabsNode); + } + LOGE("CCCC Create: %{public}d", static_cast(tabsNode->GetChildren().size())); + ViewStackProcessor::GetInstance()->Push(tabsNode); } void TabsView::SetTabBarPosition(BarPosition tabBarPosition) @@ -200,27 +207,26 @@ void TabsView::Pop() swiperNode->MarkModifyDone(); } -RefPtr TabsView::CreateTabsNode( +RefPtr TabsView::GetOrCreateTabsNode( const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator) { - RefPtr groupNode; - groupNode = ElementRegister::GetInstance()->GetSpecificItemById(nodeId); - if (groupNode) { - if (groupNode->GetTag() == tag) { - return groupNode; + auto tabsNode = ElementRegister::GetInstance()->GetSpecificItemById(nodeId); + if (tabsNode) { + if (tabsNode->GetTag() == tag) { + return tabsNode; } ElementRegister::GetInstance()->RemoveItemSilently(nodeId); - auto parent = groupNode->GetParent(); + auto parent = tabsNode->GetParent(); if (parent) { - parent->RemoveChild(groupNode); + parent->RemoveChild(tabsNode); } } auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr(); - groupNode = AceType::MakeRefPtr(tag, nodeId, pattern, false); - groupNode->InitializePatternAndContext(); - ElementRegister::GetInstance()->AddUINode(groupNode); - return groupNode; + tabsNode = AceType::MakeRefPtr(tag, nodeId, pattern, false); + tabsNode->InitializePatternAndContext(); + ElementRegister::GetInstance()->AddUINode(tabsNode); + return tabsNode; } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.h b/frameworks/core/components_ng/pattern/tabs/tabs_view.h index d52a3473737..0ec65d2cea3 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.h @@ -21,7 +21,7 @@ #include "base/memory/referenced.h" #include "base/utils/macros.h" #include "core/components/common/layout/constants.h" -#include "core/components_ng/base/group_node.h" +#include "core/components_ng/pattern/tabs/tabs_node.h" #include "core/components_ng/pattern/swiper/swiper_event_hub.h" #include "core/components_ng/pattern/swiper/swiper_layout_property.h" #include "core/components_ng/pattern/tabs/tab_bar_layout_property.h" @@ -42,13 +42,11 @@ public: static void SetScrollable(bool scrollable); static void SetAnimationDuration(int32_t duration); static void SetOnChange(ChangeEvent&& onChange); - static RefPtr GetSwiperController(); - static RefPtr CreateTabsNode( - const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator); - private: + static RefPtr GetOrCreateTabsNode( + const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator); static RefPtr GetTabBarLayoutProperty(); static RefPtr GetSwiperLayoutProperty(); static RefPtr GetSwiperPaintProperty(); diff --git a/frameworks/core/components_ng/pattern/text/text_paint_method.h b/frameworks/core/components_ng/pattern/text/text_paint_method.h index 3e69e99921c..90812e564fc 100644 --- a/frameworks/core/components_ng/pattern/text/text_paint_method.h +++ b/frameworks/core/components_ng/pattern/text/text_paint_method.h @@ -38,8 +38,7 @@ public: CanvasDrawFunction GetContentDrawFunction(PaintWrapper* paintWrapper) override { CHECK_NULL_RETURN(paragraph_, nullptr); - auto offset = paintWrapper->GetContentOffset(); - auto paintOffset = offset - OffsetF(0.0, baselineOffset_); + auto paintOffset = OffsetF(0.0, baselineOffset_); return [paragraph = paragraph_, paintOffset]( RSCanvas& canvas) { paragraph->Paint(&canvas, paintOffset.GetX(), paintOffset.GetY()); }; } diff --git a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h index ffa29eebed6..4a7ad8a22aa 100644 --- a/frameworks/core/components_ng/syntax/lazy_for_each_builder.h +++ b/frameworks/core/components_ng/syntax/lazy_for_each_builder.h @@ -66,7 +66,7 @@ public: void ExpandChildrenOnInitial() { - OnExpandChildrenOnInitial(); + OnExpandChildrenOnInitialInNG(); } void OnDataReloaded() override {} @@ -82,7 +82,7 @@ public: protected: virtual int32_t OnGetTotalCount() = 0; virtual std::pair> OnGetChildByIndex(int32_t index) = 0; - virtual void OnExpandChildrenOnInitial() = 0; + virtual void OnExpandChildrenOnInitialInNG() = 0; private: // [index : [key, UINode]] -- Gitee From 558d4d5f5db1c163d6adcfef45c2a03f97a5c913 Mon Sep 17 00:00:00 2001 From: caocan Date: Fri, 9 Sep 2022 22:26:55 +0800 Subject: [PATCH 6/6] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]Tab?= =?UTF-8?q?s=E8=AF=84=E8=AE=BA=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: caocan Change-Id: Ifa27090ecc74617bccbe81291f955c7e4e2ee80b --- frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp | 1 - frameworks/core/components_ng/base/ui_node.cpp | 5 ++--- frameworks/core/components_ng/pattern/tabs/tabs_node.h | 3 ++- frameworks/core/components_ng/pattern/tabs/tabs_view.cpp | 2 -- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp index b6742f5c783..d5b02971139 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_tabs.cpp @@ -158,7 +158,6 @@ void JSTabs::CreateForNG(const JSCallbackInfo& info) void JSTabs::Pop() { - LOGE("CCCC JSTabs::Pop"); if (Container::IsCurrentUseNewPipeline()) { NG::TabsView::Pop(); NG::ViewStackProcessor::GetInstance()->PopContainer(); diff --git a/frameworks/core/components_ng/base/ui_node.cpp b/frameworks/core/components_ng/base/ui_node.cpp index db284269519..194bff344ed 100644 --- a/frameworks/core/components_ng/base/ui_node.cpp +++ b/frameworks/core/components_ng/base/ui_node.cpp @@ -14,6 +14,7 @@ */ #include "core/components_ng/base/ui_node.h" + #include #include "base/geometry/ng/point_t.h" @@ -69,12 +70,11 @@ std::list>::iterator UINode::RemoveChild(const RefPtr& ch return children_.end(); } - auto result = children_.erase(iter); if (onMainTree_) { child->DetachFromMainTree(); } OnChildRemoved(child); - children_.remove(child); + auto result = children_.erase(iter); MarkNeedSyncRenderTree(); return result; } @@ -88,7 +88,6 @@ void UINode::ReplaceChild(const RefPtr& oldNode, const RefPtr& n return; } - auto iter = RemoveChild(oldNode); children_.insert(iter, newNode); newNode->SetParent(Claim(this)); diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_node.h b/frameworks/core/components_ng/pattern/tabs/tabs_node.h index 92a03b17a3b..a5b2a132211 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_node.h +++ b/frameworks/core/components_ng/pattern/tabs/tabs_node.h @@ -17,6 +17,7 @@ #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TABS_NODE_H #include + #include "core/components_ng/base/group_node.h" namespace OHOS::Ace::NG { @@ -84,7 +85,7 @@ private: std::optional swiperId_; std::optional tabBarId_; std::set swiperChildren_; - std::map tabBarNode_; // Key is id of TabContent, value is id of Column of TabBar. + std::map tabBarNode_; // Key is id of TabContent, value is id of Column of TabBar. std::map> builderNode_; // Key is id of TabContent, value is id of builder of TabBar. }; diff --git a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp index d3df1598974..9c28e69998e 100644 --- a/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp +++ b/frameworks/core/components_ng/pattern/tabs/tabs_view.cpp @@ -39,7 +39,6 @@ void TabsView::Create() { auto* stack = ViewStackProcessor::GetInstance(); auto nodeId = stack->ClaimNodeId(); - LOGE("CCCC TabsView::Create: %{public}d", nodeId); auto tabsNode = GetOrCreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); bool hasSwiperNode = tabsNode->HasSwiperNode(); @@ -65,7 +64,6 @@ void TabsView::Create() if (!hasTabBarNode) { swiperNode->MountToParent(tabsNode); } - LOGE("CCCC Create: %{public}d", static_cast(tabsNode->GetChildren().size())); ViewStackProcessor::GetInstance()->Push(tabsNode); } -- Gitee