HarmonyOS鸿蒙Next中请教跳到主界面对应tab怎么实现
HarmonyOS鸿蒙Next中请教跳到主界面对应tab怎么实现 假如我现在某个子界面需要登录,我点登录就跳转到主界面Main对应的我的tab界面,应该怎么实现。例如像安卓可以设置界面singleTask模式可以回主界面。鸿蒙怎么实现
如下是我的主界面,我在某个子界面点击登录,然后杀死子界面 回到Index对应的我的界面。用什么比较好实现?页面跳转大多是用Nav跳转的
@Entry
@Component
struct Index {
@Provide('pageIndex') pageIndex: NavPathStack = new NavPathStack()
collectController: CollectController = new CollectController()
@State currentIndex: number = 0;
@State menus: MenuItemType[] = [
{ icon: 'svg_home', text: '首页'},
{ icon: 'svg_find', text: '教程' },
{ icon: 'svg_collect', text: '收藏' },
{ icon: 'svg_me', text: '我的' },
]
@Builder
tabBuilderBar(item: MenuItemType, index: number) {
Column({ space: 4 }) {
Image($r(`app.media.${item.icon}`))
.width(25)
.fillColor(index === this.currentIndex ? $r('app.color.color_load') : '#808182')
Text(item.text)
.fontSize(12)
.fontColor(index === this.currentIndex ? $r('app.color.color_load') : '#808182')
}
}
@Builder
tabBuilderContent(index: number) {
if (index === 0) { // 首页界面
HomeIndex()
} else if (index === 1) { // 发现界面
FindIndex()
} else if (index === 2) { // 我的收藏
CollectIndex({controller : this.collectController})
}else if (index ===3) { // 个人信息界面
MeIndex({controller : this.collectController})
}
}
aboutToAppear(): void {
HttpComWrapper.getInstance().getCityResult()
if (UserUtils.loginNoNot()) { // 如果是登录状态,请求下用户的等级
HttpComWrapper.getInstance().getUserLevel()
}
}
build() {
Navigation(this.pageIndex) {
Column() {
Tabs({ barPosition: BarPosition.End, index: this.currentIndex }) {
ForEach(this.menus, (item: MenuItemType, index: number) => {
TabContent() {
this.tabBuilderContent(index)
}
.tabBar(this.tabBuilderBar(item, index))
})
}
.scrollable(false) // 制滑动切换
.animationDuration(0)
.barBackgroundColor($r('app.color.main_bg'))
.onChange((index: number) => {
this.currentIndex = index
if (index === 2) {
this.collectController.onRefresh?.()
}else if (index === 3) {
this.collectController.onRefreshPay?.()
}
})
.divider({
strokeWidth: 1,
color: '#ffeaeaea'
})
}
.width('100%')
.height('100%')
}
.hideToolBar(true)
.width('100%')
.height('100%')
}
}
更多关于HarmonyOS鸿蒙Next中请教跳到主界面对应tab怎么实现的实战教程也可以访问 https://www.itying.com/category-93-b0.html
Navigation导航采用push方法入栈后,页面实例会存储在路由栈内,即使采用push方法跳转到其它页面,之前的页面实例依旧在路由栈内,当采用pop/clear等删除路由栈页面实例的方法删除页面后,之前创建的页面实例就没办法再找回。若想要不刷新页面,跳转到之前已经创建过的页面,可以考虑采用以下方式代替pop方法:
可以采用LaunchMode中的单例模式(MOVE_TO_TOP_SINGLETON、POP_TO_SINGLETON)将路由栈内已有的页面实例替换到栈顶显示。实现方式参考:示例2。
更多关于HarmonyOS鸿蒙Next中请教跳到主界面对应tab怎么实现的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
1.楼主可以参考一下这个项目LoginAndLogout: 本示例是基于Navigation实现导航跳转,采用PromptAction实现弹窗。模拟登录和注销的场景实现,且界面满足一多适配。
2.基于Navigation组件实现导航跳转,采用PromptAction实现弹窗。模拟登录和注销的场景实现,且界面满足一多适配。应用登录符合隐私要求,实现正确的跳转逻辑,满足更好的用户体验。
3.这里面会涉及到如何拦截登录已经登录成功后的逻辑处理
清空路由,打开指定路由页面试试
背景知识:
首页我们需要知道 Tabs 的切换方式是在属性中绑定一个 index 参数。现在我们只要记录一下当前的index是什么,将值传入到登录页面,在登录页面获取完登录信息后直接将值传回来,通过 Tabs 中与index参数绑定的值,修改这个值就可以回到原位了。不过其中涉及到一个页面的销毁和重新加载,在跳转到登录页面是使用getRouter().pushUrl,在登录页面跳转回来首页是要清理之前的页面,使用getRouter().clear() + getRouter().replaceUrl 进行处理。
问题解决:
代码如下:
//1、 我的/个人页面操作判断是否要去登录
import { ToastUtil } from "@yunkss/eftool"
import { MyAccount } from "../LoginPage"
@Component
export struct Mine {
@State message: string = "我的"
aboutToAppear(): void {
console.log("MyApp: Mine -> aboutToAppear")
console.log("MyApp: Mine -> 获取到的用户信息:" + JSON.stringify(this.user))
}
build() {
Column() {
Button(this.message)
.fontSize(20)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
Button("判断是否要登录")
.fontSize(20)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
.onClick(() => {
//判断是否登录成功
let ac = AppStorage.get("myAccount") as MyAccount
if (ac) {
ToastUtil.showToast("登录成功")
} else {
this.getUIContext().getRouter().pushUrl({
url: "pages/LoginPage",
params: { index: 1 }
})
}
})
}
.width("100%")
.height("100%")
.backgroundColor(Color.Yellow)
}
}
//登录页面 2、
//封装的登录信息实体
export class MyAccount {
nick: string = ""
avatar: string = ""
userId: string = ""
}
@Entry
@Component
struct LoginPage {
@State message: string = '登录页面';
index = 0
aboutToAppear(): void {
let p = this.getUIContext().getRouter().getParams() as Record<string, number>
this.index = p["index"]
}
build() {
Column({ space: 15 }) {
Text(this.message)
.width("100%")
.height("150")
.textAlign(TextAlign.Center)
.fontSize(20)
.fontColor(Color.Black)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
Button("登录")
.fontSize(20)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
.onClick(() => {
//模拟登录获取的值
let ac = new MyAccount()
ac.nick = "测试昵称"
ac.avatar = "xx.png"
ac.userId = "123456"
AppStorage.setOrCreate("myAccount", ac)
//跳转到首页
this.getUIContext().getRouter().clear()
this.getUIContext().getRouter().replaceUrl({
url: "pages/TabsPage",
params: { index: this.index }
})
})
}
.height('100%')
.width('100%')
}
}
// 3、tab主页面
import { AppStorageV2, Font } from '@kit.ArkUI';
import { HomePage } from './content/HomePage';
import { Mine } from './content/Mine';
@Entry
@Component
struct TabsPage {
private tabsController: TabsController = new TabsController();
@State currentIndex: number = 0;
pathStack: NavPathStack =
AppStorageV2.connect(NavPathStack, 'navStack', () => new NavPathStack())!
aboutToAppear(): void {
let p = this.getUIContext().getRouter().getParams() as Record<string, number>
if (p) {
//获取到参数登录页过来的参数切换
this.currentIndex = p["index"]
}
}
@Builder
tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource,
unselectIcon: Resource) {
Column({ space: 5 }) {
Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon)
.width(24)
Text(title)
.fontSize(14)
.fontColor(this.currentIndex === targetIndex ? '#0A59F7' : '#63AAAA')
.textAlign(TextAlign.Center)
.fontWeight(500)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
build() {
NavDestination() {
Tabs({
barPosition: BarPosition.End,
controller: this.tabsController,
//绑定一个 状态变量进行提切换 tab
index: this.currentIndex
}) {
TabContent() {
HomePage()
}
.tabBar(this.tabBarBuilder('主页', 0, $r('app.media.ic_home_sel'),
$r('app.media.ic_home_normal')))
TabContent() {
Mine()
}
.tabBar(this.tabBarBuilder('我的', 1, $r('app.media.ic_friend_sel'),
$r('app.media.ic_friend_normal')))
}
.width("100%")
.height("100%")
.divider({
strokeWidth: '2vp',
color: Color.Gray,
})
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
.scrollable(false)
.vertical(false)
.onChange((index: number) => {
this.currentIndex = index
})
}
.width("100%")
.height("100%")
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack;
})
}
}
真机演示:
修整后代码
@Entry
@Component
struct Index {
@Provide('pageIndex') pageIndex: NavPathStack = new NavPathStack()
collectController: CollectController = new CollectController()
@State currentIndex: number = 0;
@State menus: MenuItemType[] = [
{ icon: 'svg_home', text: '首页'},
{ icon: 'svg_find', text: '教程' },
{ icon: 'svg_collect', text: '收藏' },
{ icon: 'svg_me', text: '我的' },
]
// 新增参数接收逻辑
aboutToAppear(): void {
const params = Router.getParams();
if (params?.tabIndex !== undefined) {
this.currentIndex = params.tabIndex
}
HttpComWrapper.getInstance().getCityResult()
if (UserUtils.loginNoNot()) {
HttpComWrapper.getInstance().getUserLevel()
}
}
// 新增页面显示时参数监听
onPageShow(): void {
const params = Router.getParams();
if (params?.tabIndex !== undefined) {
this.currentIndex = params.tabIndex
}
}
// 原有布局保持不变
build() {
Navigation(this.pageIndex) {
Column() {
Tabs({ barPosition: BarPosition.End, index: this.currentIndex }) {
ForEach(this.menus, (item: MenuItemType, index: number) => {
TabContent() {
this.tabBuilderContent(index)
}
.tabBar(this.tabBuilderBar(item, index))
})
}
.onChange((index: number) => {
this.currentIndex = index
// 原有逻辑...
})
}
}
}
}
子界面登录跳转逻辑
// 在登录按钮点击事件中实现
Button('登录')
.onClick(() => {
Router.clear()
Router.replace({
url: 'pages/Index',
params: { tabIndex: 3 } // 对应"我的"页签
})
})
主界面接收参数
@Entry
@Component
struct Index {
@State currentIndex: number = 0;
aboutToAppear() {
const params = router.getParams();
if (params?.targetTab) {
this.currentIndex = Number(params.targetTab);
}
}
onPageShow() {
const params = router.getParams();
if (params?.targetTab) { // 防止页面恢复时状态丢失
this.currentIndex = Number(params.targetTab);
}
}
build() {
// 原有界面结构不变...
Tabs({ index: this.currentIndex })
.onChange((index: number) => {
this.currentIndex = index;
})
}
}
登录页面实现
// 在登录按钮点击事件中处理跳转
onLoginSuccess() {
router.clear(); // 清除历史路由栈
router.replaceUrl({
url: 'pages/Index',
params: { targetTab: 3 } // 指定跳转到"我的"Tab页
}, (err) => {
if (err) console.error('跳转失败:', err);
});
}
返回的首页,再push到登录页
this.pageIndex.clear()
setTimeout(()=>{
this.pageIndex.pushPathByName('login')
}, 300)
在HarmonyOS Next中,通过Router
模块的pushUrl
方法实现跳转。使用router.pushUrl
并指定目标页面的URL,结合tab
参数定位到具体标签页。例如:
import router from '@ohos.router';
router.pushUrl({
url: 'pages/TabPage',
params: { tab: 'home' }
});
在目标页面通过router.getParams
获取参数并切换tab。
在HarmonyOS Next中,可以通过路由管理实现从子界面跳转到主界面指定Tab。建议使用router.clear()
清除当前页面栈,然后通过router.pushUrl()
跳转到主界面并传递参数指定目标Tab。
在你的代码中,可以在登录成功后调用:
import router from '@ohos.router';
// 登录成功后执行
router.clear();
router.pushUrl({
url: 'pages/Index',
params: { targetTab: 3 } // 3对应"我的"Tab
});
在主界面Index中,需要在aboutToAppear()
或onPageShow()
生命周期中接收参数:
aboutToAppear(): void {
const params = router.getParams();
if (params && params['targetTab']) {
this.currentIndex = params['targetTab'];
}
// 其他初始化代码...
}
这种方式会清空导航栈,确保返回主界面后无法通过返回键回到登录页,符合你的需求。