【鸿蒙应用ArkTS开发系列】- 导航栏Tab组件使用讲解

news/2024/7/21 8:51:28 标签: harmonyos, 华为, ArkTS, ArkUI

目录

    • Tabs介绍
    • Tabs使用例子
    • TabBar 样式设置
      • 定义菜单样式对象-NavigationItem
      • 定义一个底部菜单栏集合数据-NavigationList
      • 修改TabBuilder
    • Tab 组件控制
    • 题外话

现在市场上的大部分应用,主页都是才用底部导航栏菜单作为页面主体框架来展示,
在这里插入图片描述
在鸿蒙中是使用Tabs组件实现,下面我们开始讲解Tab组件的使用。

Tabs介绍

Tabs是一个通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图,它仅可包含子组件TabContent,同时搭配 TabsController使用。

TabsController 是Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。
具体可查看官网介绍,这里就不多描述。

Tabs使用例子

@Entry
@Component
export struct MainPage {
  @State mCurrentPage: number = 0;
  private mTabController: TabsController = new TabsController()

  build() {
    Tabs({ barPosition: BarPosition.End, controller: this.mTabController }) {

      TabContent() {
        Text('第一个页面')
      }
      .tabBar(this.TabBuilder(0))

      TabContent() {
        Text('第二个页面')
      }
      .tabBar(this.TabBuilder(1))

      TabContent() {
        Text('第三个页面')
      }
      .tabBar(this.TabBuilder(2))

    }
    .scrollable(true)
    .vertical(false)
    .barMode(BarMode.Fixed)
    .onChange((index) => {
      this.mCurrentPage = index;
    })

  }

  @Builder TabBuilder(index: number) {
    Column() {
      Image(index == this.mCurrentPage ? $r('app.media.icon_selected'): $r('app.media.icon_normal'))
        .width('24vp')
        .height('24vp')
        .objectFit(ImageFit.Contain)
      Text('菜单')
        .fontSize('10fp')
        .fontWeight(500)
        .fontColor(this.mCurrentPage === index ? $r('app.color.blue_3d9dff') : $r('app.color.gray_999999'))
        .margin({ top: '4vp' })
    }.justifyContent(FlexAlign.Center)
  }
}

这里对上面代码进行讲解,

  1. 首先定义一个Tab容器组件,在其中摆放了三个TabContent子组件;
  2. 使用vertical属性跟barPosition: BarPosition.End配合即可以将导航栏显示在页面底部;
  3. 使用scrollable开启手势滑动切换tab页;
  4. 定义 onChange函数,可以监听tab页面切换事件,这里我们定义了一个全局变量记录当前tab显示子页索引,通过该值可对底部栏的图标跟文本进行样式高亮处理。
  5. 使用@Builder注解定义了一个TabBuilder的布局绘制方法,进行tab底部导航栏的绘制

上面代码是一个比较粗糙的例子,由于tabBar设置调用同一个TabBuilder,因此绘制后,每个底部菜单是一模一样的效果。

下面我们对其进行修改,让它支持多个不同菜单绘制

TabBar 样式设置

定义菜单样式对象-NavigationItem

export interface NavigationItem {
  id: number; 
  text: Resource; //文本
  icon_normal: Resource; // 默认图标
  icon_selected: Resource; // 选中图标
}

定义一个底部菜单栏集合数据-NavigationList

export const NavigationList: NavigationItem[] = [
  {
    icon_normal: $r('app.media.main_icon_home'),
    icon_selected: $r('app.media.main_icon_home'),
    text: $r('app.string.tab_home'),
    id: 0
  },
  {
    icon_normal: $r('app.media.main_icon_life'),
    icon_selected: $r('app.media.main_icon_life'),
    text: $r('app.string.tab_life'),
    id: 1
  },
  {
    icon_normal: $r('app.media.main_icon_user'),
    icon_selected: $r('app.media.main_icon_user'),
    text: $r('app.string.tab_user'),
    id: 2
  },
]

修改TabBuilder

@Builder TabBuilder(item: NavigationItem) {

     Column() {
        Image(this.mCurrentPage === this.getTabIndexByItem(item) ? item.icon_selected : item.icon_normal)
          .width('24vp')
          .height('24vp')
          .objectFit(ImageFit.Contain)

        Text(item.text)
          .fontSize('10fp')
          .fontWeight(500)
          .fontColor(this.mCurrentPage === this.getTabIndexByItem(item) ? $r('app.color_blue_3d9dff') : $r('app.color.gray_999999'))
          .margin({ top: '4vp' })
      }
      .justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
    }
  }

这里是根据NavigationItem ID动态找在数组中的索引。

getTabIndexByItem(navigationItem: NavigationItem): number {
    return this.mTabDataList.findIndex(item => item.id === navigationItem.id);
  }

通过传入一个NavigationItem,对TabBuilder中的组件样式进行动态配置。

Tab 组件控制

如果想要通过代码去控制tab切换到指定子页,可以使用 TabController来对tab进行控制,使用changeIndex函数进行切换。

题外话

本文到此结束,谢谢阅读,由于时间匆忙,只能进行简单讲解,一些tab滑动动画、tabItem的点击样式、tabbar分隔线的问题,后续有时间再进行补充。如有疑问,评论区沟通探讨。


http://www.niftyadmin.cn/n/294267.html

相关文章

体验 langchain-ChatGLM

体验 langchain-ChatGLM 1. 什么是 langchain-ChatGLM2. 什么是 langchain3. Github 地址4. 安装 Miniconda35. 创建虚拟环境6. 部署 langchain-ChatGLM7. 启动 langchain-ChatGLM8. 访问 langchain-ChatGLM9. API部署10. 命令行部署11. 其他,LangChain Document Lo…

yoloV2细节改进

文章目录 1 v2 细节升级概述2 .网络结构特点3. 架构细节解读4. 基于聚类来选择先验框尺寸5. 偏移量计算方法6. 坐标映射与还原7 感受野8. 特征融合的改进其他知识点filter 是什么? 1 v2 细节升级概述 2 .网络结构特点 使用dropout,杀死部分神经元&#…

Android开发名企真实面试经历

作为一名Android开发,在各种初创公司工作了几年后,我觉得是时候开始去大公司探索机会了。 当前国内大厂人人都想挤进去,在我综合考量之下,我选择了投外企,幸运的是,没过多长时间我就接到了某著名外企面试官…

消息队列中间件 - Docker安装RabbitMQ、AMQP协议、和主要角色

概述 不管是微服务还是分布式的系统架构中,消息队列中间件都是不可缺少的一个重要环节,主流的消息队列中间件有RabbitMQ、RocketMQ等等,从这篇开始详细介绍以RabbitMQ为代表的消息队列中间件。 AMQP协议 AMQP协议是一个提供统一消息服务的应…

Vue 2.0 学习笔记

Vue学习笔记 文章目录 Vue学习笔记[toc]一、数据代理实现二、事件相关1.事件修饰符2.键盘事件 三、计算属性与监视1.计算属性-computed2.监视-watch 四、条件渲染1.v-show2.v-if,v-else-if 五、循环遍历1.v-for语法2.key的作用与原理 六、内置指令1.v-cloak指令&…

三十多岁程序员的难熬时刻

从帝都回来的这两三年,工作、生活、日常琐事几乎让人崩溃。 总是感觉生活无望,工作让人难以忍受,难以处理家庭、夫妻关系。 有了孩子以后,夫妻之间频繁吵架、甚至闹到要离婚。我无法对目前的状况抱有积极态度。我总感觉我们无法…

Js算法篇

1.防抖与节流 function antiShake(fn, wait) {let timeOut null;return args > {if (timeOut) clearTimeout(timeOut)timeOut setTimeout(fn, wait)} } 2.深拷贝 function deepClone(obj) {// 基本数据类型和null不需要处理if (typeof obj ! object || !obj) {// undef…

Java简介和基础语法

文章目录 一、java简介二、Java 基础语法总结 一、java简介 通过一个简单的实例来展示 Java 编程,创建文件 HelloWorld.java(文件名需与类名一致), 代码如下: public class HelloWorld {public static void main(String[] args) {System.out.println(&q…