HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决

发布于 1周前 作者 bupafengyu 来自 鸿蒙OS

HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决
<markdown _ngcontent-blb-c147="" class="markdownPreContainer">

在开发HarmonyOS应用时,我们通常会使用Tabs组件来创建底部导航栏。但在某些情况下,当我们使用Navigation组件进行子页面跳转后,底部的Tabs并没有自动隐藏,这可能会影响到用户体验。本文将讨论如何解决这个问题。

问题复现

一直以来,首页的Tabs是这么用的:

深色代码主题
复制
import Home from "../pages/home/Home"
import ZhiHu from "../pages/song/Song"
import Mine from "../pages/mine/Mine"

@Entry @Component struct Index { @State currentIndex: number = 0 private controller: TabsController = new TabsController()

// 只有被@Entry装饰的组件才可以调用页面的生命周期 onPageShow() { console.info(‘Index onPageShow’); } // 只有被@Entry装饰的组件才可以调用页面的生命周期 onPageHide() { console.info(‘Index onPageHide’); }

// 只有被@Entry装饰的组件才可以调用页面的生命周期 onBackPress() { console.info(‘Index onBackPress’); }

build() { Column() { Tabs({ barPosition: BarPosition.End, controller: this.controller }) { TabContent() { Home() }.tabBar(this.TabBuilder(‘首页’, 0, $r(‘app.media.icon_sort’), $r(‘app.media.icon_sort_default’)))

    <span class="hljs-title class_">TabContent</span>() {
      <span class="hljs-title class_">ZhiHu</span>()
    }.<span class="hljs-title function_">tabBar</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-title class_">TabBuilder</span>(<span class="hljs-string">'原声'</span>, <span class="hljs-number">1</span>, $r(<span class="hljs-string">'app.media.ks_selected'</span>), $r(<span class="hljs-string">'app.media.ks'</span>)))

    <span class="hljs-title class_">TabContent</span>() {
       <span class="hljs-title class_">Mine</span>()
    }.<span class="hljs-title function_">tabBar</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-title class_">TabBuilder</span>(<span class="hljs-string">'我的'</span>, <span class="hljs-number">2</span>, $r(<span class="hljs-string">'app.media.user_selected'</span>), $r(<span class="hljs-string">'app.media.user'</span>)))
  }.<span class="hljs-title function_">scrollable</span>(<span class="hljs-literal">false</span>) <span class="hljs-comment">// 禁止滑动切换</span>
}
.<span class="hljs-title function_">width</span>(<span class="hljs-string">'100%'</span>)
.<span class="hljs-title function_">height</span>(<span class="hljs-string">'100%'</span>)

}

// 自定义导航页签的样式 @Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) { Column() { Image(this.currentIndex === targetIndex ? selectedImg : normalImg) .size({ width: 25, height: 25 }) Text(title) .fontColor(this.currentIndex === targetIndex ? ‘#28bff1’ : ‘#8a8a8a’) } .width(‘100%’) .height(50) .justifyContent(FlexAlign.Center) .onClick(() => { this.currentIndex = targetIndex this.controller.changeIndex(this.currentIndex) }) } }

之前一直没留意到,跳转到 子页面后,这底部的几个tab竟然还在,没有隐藏掉。这是什么情况?其实是用法问题。

在元服务的也存在这个问题,之前Index页是这么写的:

深色代码主题
复制
import Home from "./home/Home";
import Mine from "./mine/Mine";
import { AtomicServiceTabs, OnContentWillChangeCallback, TabBarOptions, TabBarPosition } from '@kit.ArkUI';
import { Log } from "../utils/logutil";
import { authentication } from "@kit.AccountKit";
import { BusinessError } from "@kit.BasicServicesKit";

@Entry @Component struct Index { // 组件生命周期 aboutToAppear() { Log.info(‘Index aboutToAppear’); this.loginWithHuaweiID(); }

// 组件生命周期 aboutToDisappear() { Log.info(‘Index aboutToDisappear’); }

@State currentIndex: number = 0 onContentWillChangeCallBack: OnContentWillChangeCallback = (currentIndex: number, comingIndex: number): boolean => { this.currentIndex = currentIndex;

<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'OnContentWillChangeCallback'</span>)
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;

} onTabClick: Callback<number> = (index: number) => {

<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'onTabClick'</span>);

}

@Builder Mine() { Column() { Mine() }.width(‘100%’).height(‘100%’) }

@Builder Home() { Column() { Home() }.width(‘100%’).height(‘100%’) }

build() { Stack() { AtomicServiceTabs({ tabContents: [ () => { this.Home() }, () => { this.Mine() },

    ],
    <span class="hljs-attr">tabBarOptionsArray</span>: [
      <span class="hljs-keyword">new</span> <span class="hljs-title class_">TabBarOptions</span>($r(<span class="hljs-string">'sys.media.leave_home_fill'</span>), <span class="hljs-string">'首页'</span>, <span class="hljs-title class_">Color</span>.<span class="hljs-property">Black</span>, <span class="hljs-title class_">Color</span>.<span class="hljs-property">Blue</span>),
      <span class="hljs-keyword">new</span> <span class="hljs-title class_">TabBarOptions</span>($r(<span class="hljs-string">'sys.media.AI_pause'</span>), <span class="hljs-string">'我的'</span>, <span class="hljs-title class_">Color</span>.<span class="hljs-property">Black</span>, <span class="hljs-title class_">Color</span>.<span class="hljs-property">Blue</span>),
    ],
    <span class="hljs-attr">tabBarPosition</span>: <span class="hljs-title class_">TabBarPosition</span>.<span class="hljs-property">BOTTOM</span>,
    <span class="hljs-attr">barBackgroundColor</span>: $r(<span class="hljs-string">'sys.color.ohos_id_color_bottom_tab_bg'</span>),
    <span class="hljs-attr">onTabBarClick</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">onTabClick</span>,
    <span class="hljs-attr">onContentWillChange</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">onContentWillChangeCallBack</span>,
  })
}.<span class="hljs-title function_">height</span>(<span class="hljs-string">'100%'</span>)

} } }

解决办法

在Index页面中,用Navigation把tabs包裹起来。然后,注意在tab的页面中,不要再用Navigation包裹了,只在这Index页这里保留一份。那么tab页的title呢?自己用个Text自定义实现就行啦。

那么tab页中,如何跳转到子页面呢?

然后重点来了,用[@Provide](/user/Provide)装饰器和[@Consume](/user/Consume)装饰器。

[@Provide](/user/Provide)和[@Consume](/user/Consume),应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,[@Provide](/user/Provide)和[@Consume](/user/Consume)摆脱参数传递机制的束缚,实现跨层级传递。

其中[@Provide](/user/Provide)装饰的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。[@Consume](/user/Consume)装饰的变量是在后代组件中,去“消费(绑定)”祖先组件提供的变量。

[@Provide](/user/Provide)/[@Consume](/user/Consume)是跨组件层级的双向同步。

在Index页面用以下方式定义个pageStack。

深色代码主题
复制
 [@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {
  [@State](/user/State) currentIndex: number = 0
  private controller: TabsController = new TabsController()
  //定义pageStack
  [@Provide](/user/Provide) pageStack: NavPathStack = new NavPathStack()
  //......
}

在tab的页面中,通过使用@Consume去获取@Provide提供的变量。

@Component export default struct Home { //Consume,去“消费(绑定)”祖先组件提供的变量 @Consume pageStack: NavPathStack

private swiperController: SwiperController = new SwiperController() private swiperData: SwiperDataSource<BannerItem> = new SwiperDataSource()

//… this.pageStack.pushDestinationByName(“MusicPlayerPage”, { item:it }).catch((e:Error)=>{ // 跳转失败,会返回错误码及错误信息 console.log(catch exception: ${JSON.stringify(e)}) }).then(()=>{ // 跳转成功 }); }

</markdown>


更多关于HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复
我按照你这个逻辑写的,直接没办法跳转了

更多关于HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


看他思路还是有可行性的 怎么会不能跳转

在HarmonyOS鸿蒙Next系统中,针对Navigation组件跳转子页面后底部Tab不隐藏的问题,可以通过调整页面栈管理逻辑来解决。

底部Tab不隐藏通常是因为页面跳转逻辑未正确设置,导致父页面与子页面在同一页面栈中。为确保Tab页在跳转子页面后隐藏,可采取以下措施:

  1. 使用不同的页面栈:确保Tab页与其子页面位于不同的页面栈中。在Navigation配置中,为Tab页和其子页面分别指定不同的页面栈标识。

  2. 页面跳转方式:在代码中控制跳转方式,确保子页面以模态对话框或独立页面的形式呈现,而非作为Tab页的子页面。

  3. Tab页生命周期管理:在Tab页的生命周期方法中,监听页面栈变化,适时隐藏或显示Tab。但通常,正确配置页面栈后,此步骤非必需。

  4. 检查路由配置:确保路由配置正确,无冗余或错误的页面跳转路径。

通过上述方法,应能解决HarmonyOS鸿蒙Next系统中Navigation组件跳转子页面后底部Tab不隐藏的问题。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部