04鸿蒙APP开发之创建一个底部菜单栏及首页列表

1、概述

构建一个带有底部四个菜单的导航栏,首页显示一个列表,并添加测试数据,及点击事件。

1.1、需要用到的组件

1.1.1、List

列表(List)是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。
列表的组件及子组件的关系,如下图所示:
在这里插入图片描述

1.1.2、Tabs

Tabs组件的页面组成包含两个部分,分别是TabContent和TabBar。可以用来制作底部菜单导航栏。
Tabs支持不同位置的导航,如下图所示:
在这里插入图片描述

1.2、用到新的关键字及语法

1.2.1、ForEach语句

ForEach(
  arr: any[], 
  itemGenerator: (item: any, index?: number) => void,
  keyGenerator?: (item: any, index?: number) => string 
)

arr:必须是数组,允许设置为空数组; itemGenerator:数据项,即ltem的布局;
keyGenerator:指定列表项的唯一键,布局视图复用,避免重复渲染,提升性能。

1.2.2、@Builder装饰器

自定义构建函数,有这个注解的地函数可以直接被调用,如

//调用tabMe
TabContent() .tabBar(this.tabMe)

//自建的带注解的函数
@Builder tabSub() {
    Column() {
    }
}

其中CustomBuilder就支持这种写法。

1.2.3、import 导入类

import { News } from '../pages/News';

注意:可使用as 关键字进行重命名

import { News as NewInfo } from '../pages/News';

也可以导入指定类的函数,对应的函数天机export 关键字

export function testFun(name: string): void {
  console.log('this is a export fun');
}

调用导出的函数:

import { testFun} from './MyClassName.ets';
// 调用导入的函数
testFun('Alice'); 

2、创建首页

创建首页文件Index.ets,及自定义一个测试类,用于构造测试数据,包目录如下图所示:
在这里插入图片描述

3、编写代码

Index.ets文件内容如下:

import prompt from '@ohos.promptAction'
//引入自定义类
import { News } from '../pages/News';

@Entry
@Component
struct Index {
  private tabsController = new TabsController();
  @State index: number = 0; // 选项卡下标,默认为第一个

  private newsList = [
    new News('title1', 'abstract', $r("app.media.app_icon")),
    new News('title2', 'abstract', $r("app.media.app_icon")),
    new News('title3', 'abstract', $r("app.media.app_icon")),
    new News('title4', 'abstract', $r("app.media.app_icon"))
  ]

  @Builder tabHome() {
    Column() {
      Image(this.index == 0 ? $r('app.media.ic_menu_home_focus') : $r('app.media.ic_menu_home_normal'))
        .size({ width: 25, height: 25 }).margin({ top: 5, bottom: 5 })
      Text("首页").fontSize(16).fontColor(this.index == 0 ? "#2a58d0" : "#6b6b6b")
    }.width('100%').height('100%').onClick(() => {
      this.index = 0;
      this.tabsController.changeIndex(this.index)
    })
  }

  @Builder tabSub() {
    Column() {
      Image(this.index == 1 ? $r('app.media.ic_menu_sub_focus') : $r('app.media.ic_menu_sub_normal'))
        .size({ width: 25, height: 25 }).margin({ top: 5, bottom: 5 })
      Text("订阅").fontSize(16).fontColor(this.index == 1 ? "#2a58d0" : "#6b6b6b")
    }.width('100%').height('100%').onClick(() => {
      this.index = 1;
      this.tabsController.changeIndex(this.index)
    })
  }

  @Builder tabMe() {
    Column() {
      Image(this.index == 2 ? $r('app.media.ic_menu_me_focus') : $r('app.media.ic_menu_me_normal'))
        .size({ width: 25, height: 25 }).margin({ top: 5, bottom: 5 })
      Text("我的").fontSize(16).fontColor(this.index == 2 ? "#2a58d0" : "#6b6b6b")
    }.width('100%').height('100%').onClick(() => {
      this.index = 2;
      this.tabsController.changeIndex(this.index)
    })
  }

  build() {
    Column() {
      Tabs({ controller: this.tabsController }) {
        TabContent() {
          Column() {
            List({ space: 10, initialIndex: 0 }) {
              ForEach(this.newsList, (item: News, index: number) => {
                // 循环渲染ListItem
                ListItem() {
                  Row() {
                    Image(item.icon).width(40).height(40).margin(10)
                    Column() {
                      Text(item.title).fontSize(16).fontColor($r("app.color.color_list_title"))
                      Text(item.abstract).fontSize(14).fontColor($r("app.color.color_list_abstract"))
                    }.width('100%').alignItems(HorizontalAlign.Start)
                  }.width('100%').justifyContent(FlexAlign.Start)
                  .onClick(() => {
                    //选项单击事件
                    prompt.showToast({ message: this.newsList[index].title, duration: 2000 })
                  })
                }
              }, item => item.id)
            }.width("100%").listDirection(Axis.Vertical).scrollBar(BarState.Auto)

          }.width('100%').height('100%').justifyContent(FlexAlign.Start).backgroundColor("#eeeeee")
        }.tabBar(this.tabHome())

        TabContent() {
          Column() {
            Text("订阅内容").fontSize(32)
          }.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor("#eeeeee")
        }.tabBar(this.tabSub)

        TabContent() {
          Column() {
            Text("我的内容").fontSize(32)
          }.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor("#eeeeee")
        }.tabBar(this.tabMe)

      }.barPosition(BarPosition.End)
    }.width('100%').height('100%')
  }
}

自定义的News.ets实体类,内容如下:

import util from '@ohos.util';
//创建一个实体类
export class News {
  id: string = util.generateRandomUUID(true);
  title: string;
  abstract: string;
  icon: Resource;

  constructor(title: string, abstract: string, icon: Resource) {
    this.title = title;
    this.abstract = abstract;
    this.icon = icon;
  }
}

BarState.Auto表示按需显示滚动条;
Axis.Horizontal表示水平滚动列表。

4、运行效果

最终执行的效果图如下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

后续继续完善这个测试项目

5、参考文档:

ArkTS UI文档:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-rendering-control-foreach-0000001524537153-V2






原创不易,求个关注。

在这里插入图片描述

微信公众号:一粒尘埃的漫旅
里面有很多想对大家说的话,就像和朋友聊聊天。
写代码,做设计,聊生活,聊工作,聊职场。
我见到的世界是什么样子的?
搜索关注我吧。

公众号与博客的内容不同。

  • 18
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是uni-app自定义底部菜单栏的步骤: 1.下载uni-app-bottom-navigation-master.zip并解压缩。 2.将解压后的文件夹复制到你的uni-app项目的static目录下。 3.在pages.json文件中添加如下代码: ```json "tabBar": { "custom": true, "color": "#7A7E83", "selectedColor": "#3cc51f", "backgroundColor": "#ffffff", "list": [ { "pagePath": "pages/index/index", "text": "首页", "iconPath": "/static/uni-app-bottom-navigation-master/static/home.png", "selectedIconPath": "/static/uni-app-bottom-navigation-master/static/home_selected.png" }, { "pagePath": "pages/logs/logs", "text": "日志", "iconPath": "/static/uni-app-bottom-navigation-master/static/logs.png", "selectedIconPath": "/static/uni-app-bottom-navigation-master/static/logs_selected.png" }, { "pagePath": "pages/user/user", "text": "我的", "iconPath": "/static/uni-app-bottom-navigation-master/static/user.png", "selectedIconPath": "/static/uni-app-bottom-navigation-master/static/user_selected.png" } ] } ``` 4.在App.vue文件中添加如下代码: ```html <template> <div> <tab-bar></tab-bar> <router-view></router-view> </div> </template> <script> import tabBar from '@/components/tab-bar.vue' export default { components: { tabBar } } </script> ``` 5.在components目录下创建tab-bar.vue文件,并添加如下代码: ```html <template> <div class="tab-bar"> <div v-for="(item, index) in list" :key="index" class="tab-bar-item" :class="{active: item.pagePath === currentPath}" @click="switchTab(item.pagePath)"> <img :src="item.pagePath === currentPath ? item.selectedIconPath : item.iconPath" alt=""> <p>{{item.text}}</p> </div> </div> </template> <script> export default { props: { list: { type: Array, default: () => [] } }, data() { return { currentPath: '' } }, created() { this.currentPath = this.$mp.page.route }, methods: { switchTab(path) { if (path !== this.currentPath) { uni.switchTab({ url: '/' + path }) } } } } </script> <style> .tab-bar { display: flex; justify-content: space-between; align-items: center; height: 50px; background-color: #fff; border-top: 1px solid #ddd; position: fixed; bottom: 0; left: 0; right: 0; z-index: 999; } .tab-bar-item { display: flex; flex-direction: column; justify-content: center; align-items: center; flex: 1; height: 100%; color: #7A7E83; } .tab-bar-item.active { color: #3cc51f; } .tab-bar-item img { width: 24px; height: 24px; } .tab-bar-item p { font-size: 12px; margin-top: 4px; } </style> ``` 以上就是uni-app自定义底部菜单栏的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值