前言
在现代应用程序中,多标签页(Tab Bar)是一种常见的导航模式,便于用户在不同功能模块之间轻松切换。接下来,我将展示一个使用 TypeScript 和一些 UI 组件构建的多标签页界面,包括标签切换、UI 布局设计以及状态管理等内容。
一、页面设计
首页UI设计代码
首页UI设计效果图
二、创建首页的TabBar
首先,创建一个名为 `Index` 的入口组件,该组件包含一个底部导航栏 `TabBar`。 `TabBar` 可以容纳多个 `TabContent`,每个 `TabContent` 对应一个页面。我定义了一个 `TabBarBuilder` 构建函数,它接受三个参数:标题、图片资源和索引。该构建函数返回一个包含图像和文本的列布局。图像和文本的颜色由 `selectColor` 函数决定,如果当前索引与传入的索引相同,则颜色为 `app.color.primary_color`,否则为 `app.color.gray`。接下来,在 `build` 函数中,我创建了一个包含三个 `TabContent` 的 `Tabs` 组件,这三个 `TabContent` 分别对应“记录”、“发现”和“我的主页”三个页面。每个 `TabContent` 都有一个对应的 `tabBar`,由 `TabBarBuilder` 生成。
Index组件在DevEcoStudio里面的位置如图:
代码如下:
import { CommonConstants } from '../common/constants/CommonConstants'
import RecordIndex from '../view/record/RecordIndex'
@Entry
@Component
struct Index {
@State currentIndex: number = 0
@Builder TabBarBuilder(title:ResourceStr,image:ResourceStr,index:number){
Column({space:CommonConstants.SPACE_8}){
Image(image)
.width(22)
.fillColor(this.selectColor(index))
Text(title)
.fontSize(14)
.fontColor(this.selectColor(index))
}
}
selectColor(index:number){
return this.currentIndex === index ? $r('app.color.primary_color'):$r('app.color.gray')
}
build() {
Tabs({barPosition:BarPosition.End}) {
TabContent(){
RecordIndex()
}
.tabBar(this.TabBarBuilder($r('app.string.tab_record'),$r('app.media.ic_calendar'),0))
TabContent(){
Text('发现页面')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_discover'),$r('app.media.discover'),1))
TabContent(){
Text('我的主页')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_user'),$r('app.media.ic_user_portrait'),2))
}
.width('100%')
.height('100%')
.onChange(index => this.currentIndex = index)
}
}
三、创建搜索栏和统计卡片
接下来,创建一个名为 `RecordIndex` 的组件,该组件包含一个搜索栏和一个统计卡片。首先,我创建了一个 `SearchHeader` 组件,这是一个行布局,包含一个搜索框和一个图标。搜索框的宽度设置为 1,即占满整个行布局,而图标的位置位于搜索框的右上方。然后,我添加了表示统计卡片和记录列表的占位文本。在实际开发中,这些占位文本需要替换为真实的统计卡片和记录列表。
代码如下:
import SearchHeader from './SearchHeader'
@Component
export default struct RecordIndex {
build() {
Column(){
//1.头部搜索栏
SearchHeader()
//2.统计卡片
Text('统计卡片')
//3.记录列表
Text('记录列表')
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.index_page_background'))
}
}
四、创建搜索栏
最后,我创建了一个名为 `SearchHeader` 的组件,其中包含一个搜索框和一个图标。首先,我建立了一个行布局,其中包括搜索框和图标。搜索框的宽度设置为 1,以充满整个行布局,而图标的位置则位于搜索框的右上方。
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct SearchHeader {
build() {
Row({space:CommonConstants.SPACE_6}) {
Search({ placeholder: '搜索饮食或运动信息' })
.textFont({ size: 18 })
.layoutWeight(1)
Badge({count:1,position:BadgePosition.RightTop,style:{fontSize:14}}) {
Image($r('app.media.ic_public_email'))
.width(24)
}
}
.width(CommonConstants.THOUSANDTH_940)
}
}
本次设计关键概念和技术:
-
1. **结构体(`struct`)**:
-
- 使用结构体(`struct`)来定义组件,每个结构体表示用户界面中的一个独立部分或组件。
-
2. **组件化**:
-
- 将用户界面分解为多个小的、可复用的组件。每个组件可以独立开发、测试和维护,从而提高代码的模块化和可维护性。
-
3. **`build()` 方法**:
-
- 每个结构体都包含一个 `build()` 方法,用于描述该组件如何呈现其内容和样式。这种方法通常返回一个表示UI布局的对象。
-
4. **入口点组件(`Index` 结构体)**:
-
- 作为应用的入口,负责整体布局的初始化和管理。在这个例子中,`Index` 结构体展示了一个标签页(`Tabs`)布局。
-
5. **标签页布局(`Tabs`)**:
-
- 多个标签页组成的布局,每个标签页由 `TabBarBuilder` 构建,能够根据当前索引显示不同的颜色和图标。通过 `currentIndex` 来动态显示不同的内容和样式。
-
6. **动态样式和状态管理**:
-
- 组件在呈现内容时根据当前状态(例如 `currentIndex`)来动态调整其样式和显示内容。`selectColor()` 方法用于确定当前选中标签的颜色。
-
7. **嵌套组件**:
-
- 复杂的组件由多个简单组件组合而成。例如,`Index` 结构体内部调用了 `RecordIndex` 和 `Text` 组件来展示页面内容,而 `RecordIndex` 结构体内部则调用了 `SearchHeader` 和其他文本组件。
-
8. **搜索栏、统计卡片和记录列表**:
-
- 在 `RecordIndex` 结构体中,通过调用 `SearchHeader` 和其他组件来构建搜索功能、统计信息展示和记录列表。
-
9. **交互式用户界面**:
-
- 利用组件化和状态管理技术,实现了一个多标签页的交互式用户界面,使得用户可以通过不同的标签页访问不同的内容和功能。
通过这些关键概念和技术,可以创建一个高效、灵活且易于维护的用户界面。每个组件负责特定的功能,状态管理确保界面响应用户的交互,并动态更新显示内容。
总结
在代码中定义了多个结构体(`struct`),这些结构体类似于组件,每个结构体都包含一个 `build()` 方法来描述其呈现的内容和样式。`Index` 结构体作为入口点,展示了一个标签页(`Tabs`)布局,其中包含多个标签页(`TabContent`)。每个标签页由 `TabBarBuilder` 构建,根据当前索引显示不同的颜色和图标。图像、文本等元素被配置为根据 `currentIndex` 的值来动态地显示不同的样式,并通过 `selectColor()` 方法确定当前选中标签的颜色。`Index` 结构体内部调用了 `RecordIndex` 和 `Text` 组件来展示不同的页面内容。`RecordIndex` 结构体内部则调用了 `SearchHeader` 和其他文本组件来构建搜索栏、统计卡片和记录列表。利用了组件化、状态管理等技术,创建了一个多标签页的交互式用户界面。