HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决
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(()=>{
// 跳转成功
});
}
更多关于HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next的Navigation,跳转子页面后底部Tab不隐藏问题解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
看他思路还是有可行性的 怎么会不能跳转
在HarmonyOS鸿蒙Next系统中,针对Navigation组件跳转子页面后底部Tab不隐藏的问题,可以通过调整页面栈管理逻辑来解决。
底部Tab不隐藏通常是因为页面跳转逻辑未正确设置,导致父页面与子页面在同一页面栈中。为确保Tab页在跳转子页面后隐藏,可采取以下措施:
-
使用不同的页面栈:确保Tab页与其子页面位于不同的页面栈中。在Navigation配置中,为Tab页和其子页面分别指定不同的页面栈标识。
-
页面跳转方式:在代码中控制跳转方式,确保子页面以模态对话框或独立页面的形式呈现,而非作为Tab页的子页面。
-
Tab页生命周期管理:在Tab页的生命周期方法中,监听页面栈变化,适时隐藏或显示Tab。但通常,正确配置页面栈后,此步骤非必需。
-
检查路由配置:确保路由配置正确,无冗余或错误的页面跳转路径。
通过上述方法,应能解决HarmonyOS鸿蒙Next系统中Navigation组件跳转子页面后底部Tab不隐藏的问题。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html