动态修改tabs的controller后,未解除旧的绑定关系

Signed-off-by: yangcan <yangcan18@huawei.com>
Change-Id: Id2adc9ae7ed57af0ff48d331167c474fead51566
This commit is contained in:
yangcan 2024-11-11 21:09:25 +08:00
parent 97cc8345bd
commit 3c4ab34a7c
8 changed files with 107 additions and 50 deletions

View File

@ -219,7 +219,7 @@ void JSTabs::Create(const JSCallbackInfo& info)
{
BarPosition barPosition = BarPosition::START;
RefPtr<TabController> tabController;
RefPtr<NG::TabsControllerNG> tabsController;
RefPtr<NG::TabsControllerNG> tabsController = AceType::MakeRefPtr<NG::TabsControllerNG>();
int32_t index = -1;
JSRef<JSVal> changeEventVal;
auto jsValue = info[0];
@ -238,7 +238,7 @@ void JSTabs::Create(const JSCallbackInfo& info)
if (jsTabsController) {
jsTabsController->SetInstanceId(Container::CurrentId());
tabController = jsTabsController->GetController();
tabsController = jsTabsController->GetTabsController();
jsTabsController->SetTabsController(tabsController);
}
}
JSRef<JSVal> indexVal = obj->GetProperty("index");

View File

@ -85,7 +85,6 @@ void ReturnPromise(const JSCallbackInfo& info, napi_value result)
JSTabsController::JSTabsController()
{
controller_ = CreateController();
tabsController_ = MakeRefPtr<NG::TabsControllerNG>();
}
void JSTabsController::JSBind(BindingTarget globalObj)
@ -124,12 +123,13 @@ RefPtr<TabController> JSTabsController::CreateController()
void JSTabsController::ChangeIndex(int32_t index)
{
ContainerScope scope(instanceId_);
if (tabsController_) {
const auto& updateCubicCurveCallback = tabsController_->GetUpdateCubicCurveCallback();
auto tabsController = tabsControllerWeak_.Upgrade();
if (tabsController) {
const auto& updateCubicCurveCallback = tabsController->GetUpdateCubicCurveCallback();
if (updateCubicCurveCallback != nullptr) {
updateCubicCurveCallback();
}
tabsController_->SwipeTo(index);
tabsController->SwipeTo(index);
}
#ifndef NG_BUILD
@ -150,7 +150,8 @@ void JSTabsController::PreloadItems(const JSCallbackInfo& args)
asyncContext->env = env;
napi_value promise = nullptr;
napi_create_promise(env, &asyncContext->deferred, &promise);
if (!tabsController_) {
auto tabsController = tabsControllerWeak_.Upgrade();
if (!tabsController) {
ReturnPromise(args, promise);
return;
}
@ -171,15 +172,16 @@ void JSTabsController::PreloadItems(const JSCallbackInfo& args)
CHECK_NULL_VOID(asyncContext);
HandleDeferred(asyncContext, errorCode, message);
};
tabsController_->SetPreloadFinishCallback(onPreloadFinish);
tabsController_->PreloadItems(indexSet);
tabsController->SetPreloadFinishCallback(onPreloadFinish);
tabsController->PreloadItems(indexSet);
ReturnPromise(args, promise);
}
void JSTabsController::SetTabBarTranslate(const JSCallbackInfo& args)
{
ContainerScope scope(instanceId_);
CHECK_NULL_VOID(tabsController_);
auto tabsController = tabsControllerWeak_.Upgrade();
CHECK_NULL_VOID(tabsController);
if (args.Length() <= 0) {
return;
}
@ -196,33 +198,34 @@ void JSTabsController::SetTabBarTranslate(const JSCallbackInfo& args)
JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y)), translateY);
JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Z)), translateZ);
auto options = NG::TranslateOptions(translateX, translateY, translateZ);
tabsController_->SetTabBarTranslate(options);
tabsController->SetTabBarTranslate(options);
return;
}
}
CalcDimension value;
if (JSViewAbstract::ParseJsDimensionVp(translate, value)) {
auto options = NG::TranslateOptions(value, value, value);
tabsController_->SetTabBarTranslate(options);
tabsController->SetTabBarTranslate(options);
} else {
auto options = NG::TranslateOptions(0.0f, 0.0f, 0.0f);
tabsController_->SetTabBarTranslate(options);
tabsController->SetTabBarTranslate(options);
}
}
void JSTabsController::SetTabBarOpacity(const JSCallbackInfo& args)
{
ContainerScope scope(instanceId_);
CHECK_NULL_VOID(tabsController_);
auto tabsController = tabsControllerWeak_.Upgrade();
CHECK_NULL_VOID(tabsController);
if (args.Length() <= 0) {
return;
}
double opacity = 0.0;
if (JSViewAbstract::ParseJsDouble(args[0], opacity)) {
opacity = std::clamp(opacity, 0.0, 1.0);
tabsController_->SetTabBarOpacity(opacity);
tabsController->SetTabBarOpacity(opacity);
} else {
tabsController_->SetTabBarOpacity(1.0f);
tabsController->SetTabBarOpacity(1.0f);
}
}

View File

@ -49,12 +49,21 @@ public:
void SetTabsController(const RefPtr<NG::TabsControllerNG>& tabsController)
{
tabsController_ = tabsController;
auto oldTabsController = tabsControllerWeak_.Upgrade();
if (oldTabsController) {
// old controller bind another tabs.
oldTabsController->StartShowTabBar();
oldTabsController->SetOnChangeImpl(nullptr);
}
if (tabsController) {
tabsController->SetOnChangeImpl(onChangeImpl_);
}
tabsControllerWeak_ = tabsController;
}
const RefPtr<NG::TabsControllerNG>& GetTabsController() const
const WeakPtr<NG::TabsControllerNG>& GetTabsController() const
{
return tabsController_;
return tabsControllerWeak_;
}
void SetInstanceId(int32_t id)
@ -62,10 +71,20 @@ public:
instanceId_ = id;
}
void SetOnChangeImpl(const OnChangeFunc& onChangeImpl)
{
onChangeImpl_ = onChangeImpl;
auto tabsController = tabsControllerWeak_.Upgrade();
if (tabsController) {
tabsController->SetOnChangeImpl(onChangeImpl);
}
}
private:
int32_t instanceId_ = INSTANCE_ID_UNDEFINED;
RefPtr<TabController> controller_;
RefPtr<NG::TabsControllerNG> tabsController_; // used by ng structure
WeakPtr<NG::TabsControllerNG> tabsControllerWeak_; // used by ng structure
OnChangeFunc onChangeImpl_;
ACE_DISALLOW_COPY_AND_MOVE(JSTabsController);
};

View File

@ -29,7 +29,7 @@ struct ScrollInfo {
};
using ScrollInfoMap = std::map<WeakPtr<JSScroller>, ScrollInfo>;
using BindInfoMap = std::map<WeakPtr<NG::TabsControllerNG>, ScrollInfoMap>;
using BindInfoMap = std::map<WeakPtr<JSTabsController>, ScrollInfoMap>;
const auto INDEX_ZERO = 0;
const auto INDEX_ONE = 1;
@ -53,14 +53,17 @@ void HandleOnTouchEvent(WeakPtr<JSScroller> jsScrollerWeak, const TouchEventInfo
continue;
}
auto& scrollInfo = scrollInfoIter->second;
auto tabsController = bindInfo.first.Upgrade();
scrollInfo.isTouching = touchType == TouchType::DOWN;
auto jsTabsController = bindInfo.first.Upgrade();
if (!jsTabsController) {
continue;
}
auto tabsController = jsTabsController->GetTabsController().Upgrade();
if (touchType == TouchType::DOWN) {
scrollInfo.isTouching = true;
if (!scrollInfo.isAtTop && !scrollInfo.isAtBottom && tabsController) {
tabsController->CancelShowTabBar();
}
} else if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
scrollInfo.isTouching = false;
if (!scrollInfo.isScrolling && tabsController) {
tabsController->StartShowTabBar(SHOW_TAB_BAR_DELAY);
}
@ -95,7 +98,11 @@ void HandleOnScrollStartEvent(WeakPtr<JSScroller> jsScrollerWeak)
}
auto& scrollInfo = scrollInfoIter->second;
scrollInfo.isScrolling = true;
auto tabsController = bindInfo.first.Upgrade();
auto jsTabsController = bindInfo.first.Upgrade();
if (!jsTabsController) {
continue;
}
auto tabsController = jsTabsController->GetTabsController().Upgrade();
if (!scrollInfo.isAtTop && !scrollInfo.isAtBottom && !scrollInfo.isTouching && tabsController) {
tabsController->CancelShowTabBar();
}
@ -112,7 +119,11 @@ void HandleOnScrollStopEvent(WeakPtr<JSScroller> jsScrollerWeak)
}
auto& scrollInfo = scrollInfoIter->second;
scrollInfo.isScrolling = false;
auto tabsController = bindInfo.first.Upgrade();
auto jsTabsController = bindInfo.first.Upgrade();
if (!jsTabsController) {
continue;
}
auto tabsController = jsTabsController->GetTabsController().Upgrade();
if (!scrollInfo.parentScroller.has_value() && !scrollInfo.isTouching && tabsController) {
// start show tab bar when parent scrollable component stop scroll.
tabsController->StartShowTabBar(SHOW_TAB_BAR_DELAY);
@ -133,7 +144,13 @@ void HandleOnDidScrollEvent(
if ((scrollInfo.isAtTop && isAtTop) || (scrollInfo.isAtBottom && isAtBottom)) {
continue;
}
auto tabsController = bindInfo.first.Upgrade();
auto jsTabsController = bindInfo.first.Upgrade();
if (!jsTabsController) {
scrollInfo.isAtTop = isAtTop;
scrollInfo.isAtBottom = isAtBottom;
continue;
}
auto tabsController = jsTabsController->GetTabsController().Upgrade();
if (tabsController) {
auto offset = dimension.ConvertToPx() / SCROLL_RATIO;
if (NonPositive(offset) ||
@ -196,9 +213,9 @@ ScrollerObserver CreateObserver(WeakPtr<JSScroller> jsScrollerWeak)
return observer;
}
void HandleOnChangeEvent(WeakPtr<NG::TabsControllerNG> tabsControllerWeak, int32_t index)
void HandleOnChangeEvent(WeakPtr<JSTabsController> jsTabsControllerWeak, int32_t index)
{
auto bindInfoIter = bindInfoMap_.find(tabsControllerWeak);
auto bindInfoIter = bindInfoMap_.find(jsTabsControllerWeak);
if (bindInfoIter == bindInfoMap_.end()) {
return;
}
@ -211,7 +228,9 @@ void HandleOnChangeEvent(WeakPtr<NG::TabsControllerNG> tabsControllerWeak, int32
}
}
}
auto tabsController = tabsControllerWeak.Upgrade();
auto jsTabsController = jsTabsControllerWeak.Upgrade();
CHECK_NULL_VOID(jsTabsController);
auto tabsController = jsTabsController->GetTabsController().Upgrade();
CHECK_NULL_VOID(tabsController);
tabsController->StartShowTabBar();
}
@ -221,23 +240,21 @@ void HandleBindTabsToScrollable(const JSRef<JSObject>& jsTabsControllerVal, cons
{
auto* jsTabsController = jsTabsControllerVal->Unwrap<JSTabsController>();
CHECK_NULL_VOID(jsTabsController);
auto tabsController = jsTabsController->GetTabsController();
CHECK_NULL_VOID(tabsController);
auto tabsControllerWeak = AceType::WeakClaim(AceType::RawPtr(tabsController));
auto jsTabsControllerWeak = AceType::WeakClaim(jsTabsController);
auto* jsScroller = jsScrollerVal->Unwrap<JSScroller>();
CHECK_NULL_VOID(jsScroller);
auto jsScrollerWeak = AceType::WeakClaim(jsScroller);
ScrollInfoMap scrollInfoMap;
auto bindInfoIter = bindInfoMap_.find(tabsControllerWeak);
auto bindInfoIter = bindInfoMap_.find(jsTabsControllerWeak);
if (bindInfoIter != bindInfoMap_.end()) {
scrollInfoMap = bindInfoIter->second;
if (scrollInfoMap.find(jsScrollerWeak) != scrollInfoMap.end()) {
return;
}
}
tabsController->SetOnChangeImpl([tabsControllerWeak](int32_t index) {
HandleOnChangeEvent(tabsControllerWeak, index);
jsTabsController->SetOnChangeImpl([jsTabsControllerWeak](int32_t index) {
HandleOnChangeEvent(jsTabsControllerWeak, index);
});
auto observer = CreateObserver(jsScrollerWeak);
jsScroller->SetObserver(observer);
@ -249,7 +266,7 @@ void HandleBindTabsToScrollable(const JSRef<JSObject>& jsTabsControllerVal, cons
}
}
scrollInfoMap[jsScrollerWeak] = scrollInfo;
bindInfoMap_[tabsControllerWeak] = scrollInfoMap;
bindInfoMap_[jsTabsControllerWeak] = scrollInfoMap;
}
void HandleUnbindTabsFromScrollable(const JSRef<JSObject>& jsTabsControllerVal, const JSRef<JSObject>& jsScrollerVal,
@ -257,14 +274,13 @@ void HandleUnbindTabsFromScrollable(const JSRef<JSObject>& jsTabsControllerVal,
{
auto* jsTabsController = jsTabsControllerVal->Unwrap<JSTabsController>();
CHECK_NULL_VOID(jsTabsController);
auto tabsController = jsTabsController->GetTabsController();
CHECK_NULL_VOID(tabsController);
auto tabsControllerWeak = AceType::WeakClaim(AceType::RawPtr(tabsController));
auto tabsController = jsTabsController->GetTabsController().Upgrade();
auto jsTabsControllerWeak = AceType::WeakClaim(jsTabsController);
auto* jsScroller = jsScrollerVal->Unwrap<JSScroller>();
CHECK_NULL_VOID(jsScroller);
auto jsScrollerWeak = AceType::WeakClaim(jsScroller);
auto bindInfoIter = bindInfoMap_.find(tabsControllerWeak);
auto bindInfoIter = bindInfoMap_.find(jsTabsControllerWeak);
if (bindInfoIter == bindInfoMap_.end()) {
return;
}
@ -272,9 +288,11 @@ void HandleUnbindTabsFromScrollable(const JSRef<JSObject>& jsTabsControllerVal,
if (scrollInfoMap.find(jsScrollerWeak) != scrollInfoMap.end()) {
scrollInfoMap.erase(jsScrollerWeak);
if (scrollInfoMap.empty()) {
bindInfoMap_.erase(tabsControllerWeak);
bindInfoMap_.erase(jsTabsControllerWeak);
}
if (tabsController) {
tabsController->StartShowTabBar();
}
tabsController->StartShowTabBar();
}
if (parentJsScrollerVal.has_value()) {
@ -293,9 +311,11 @@ void HandleUnbindTabsFromScrollable(const JSRef<JSObject>& jsTabsControllerVal,
if (needRemoveParent) {
scrollInfoMap.erase(parentJsScrollerWeak);
if (scrollInfoMap.empty()) {
bindInfoMap_.erase(tabsControllerWeak);
bindInfoMap_.erase(jsTabsControllerWeak);
}
if (tabsController) {
tabsController->StartShowTabBar();
}
tabsController->StartShowTabBar();
}
}
}

View File

@ -499,7 +499,7 @@ RefPtr<UINode> DistributedUI::RestoreNode(const std::unique_ptr<NodeObject>& nod
{ V2::TAB_BAR_ETS_TAG,
[](const std::string& type, int32_t nodeId) {
return FrameNode::GetOrCreateFrameNode(
type, nodeId, []() { return AceType::MakeRefPtr<TabBarPattern>(nullptr); });
type, nodeId, []() { return AceType::MakeRefPtr<TabBarPattern>(); });
} },
{ V2::SWIPER_ETS_TAG,
[](const std::string& type, int32_t nodeId) {

View File

@ -75,8 +75,10 @@ const std::string INDICATOR_OFFSET_PROPERTY_NAME = "indicatorOffset";
const std::string INDICATOR_WIDTH_PROPERTY_NAME = "translateWidth";
} // namespace
TabBarPattern::TabBarPattern(const RefPtr<SwiperController>& swiperController) : swiperController_(swiperController)
void TabBarPattern::SetController(const RefPtr<SwiperController>& controller)
{
swiperController_ = controller;
SetTabBarFinishCallback();
auto tabsController = AceType::DynamicCast<TabsControllerNG>(swiperController_);
CHECK_NULL_VOID(tabsController);
auto weak = WeakClaim(this);
@ -370,6 +372,12 @@ void TabBarPattern::OnAttachToFrameNode()
renderContext->SetClipToFrame(true);
host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(
SafeAreaExpandOpts { .type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_BOTTOM });
InitSurfaceChangedCallback();
}
void TabBarPattern::SetTabBarFinishCallback()
{
CHECK_NULL_VOID(swiperController_);
swiperController_->SetTabBarFinishCallback([weak = WeakClaim(this)]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
@ -401,7 +409,6 @@ void TabBarPattern::OnAttachToFrameNode()
pattern->SetChangeByClick(false);
}
});
InitSurfaceChangedCallback();
}
void TabBarPattern::InitSurfaceChangedCallback()
@ -1089,6 +1096,7 @@ void TabBarPattern::OnModifyDone()
SetAccessibilityAction();
UpdateSubTabBoard(indicator_);
StopTranslateAnimation();
StartShowTabBar();
jumpIndex_ = layoutProperty->GetIndicatorValue(0);
RemoveTabBarEventCallback();

View File

@ -131,7 +131,7 @@ class TabBarPattern : public Pattern {
DECLARE_ACE_TYPE(TabBarPattern, Pattern);
public:
explicit TabBarPattern(const RefPtr<SwiperController>& swiperController);
TabBarPattern() = default;
~TabBarPattern() override = default;
bool IsAtomicNode() const override
@ -185,6 +185,8 @@ public:
return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams };
}
void SetController(const RefPtr<SwiperController>& controller);
void SetIndicator(int32_t indicator)
{
indicator_ = indicator;
@ -531,6 +533,7 @@ private:
void OnAttachToFrameNode() override;
void OnDetachFromFrameNode(FrameNode* node) override;
void BeforeCreateLayoutWrapper() override;
void SetTabBarFinishCallback();
void InitSurfaceChangedCallback();
bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
bool CustomizeExpandSafeArea() override;

View File

@ -168,7 +168,11 @@ void TabsModelNG::InitTabsNode(RefPtr<TabsNode> tabsNode, const RefPtr<SwiperCon
// Create TabBar to contain TabBar of TabContent.
auto tabBarNode = FrameNode::GetOrCreateFrameNode(
V2::TAB_BAR_ETS_TAG, tabBarId, [controller]() { return AceType::MakeRefPtr<TabBarPattern>(controller); });
V2::TAB_BAR_ETS_TAG, tabBarId, []() { return AceType::MakeRefPtr<TabBarPattern>(); });
auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
if (tabBarPattern) {
tabBarPattern->SetController(controller);
}
auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty();
CHECK_NULL_VOID(tabBarLayoutProperty);