[HarmonyOS NEXT 实战案例:旅行应用] 基础篇 - 水平分割布局打造旅行规划应用
[HarmonyOS NEXT 实战案例:旅行应用] 基础篇 - 水平分割布局打造旅行规划应用
项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
组件概述
在本案例中,我们将使用以下HarmonyOS NEXT组件:
组件名称 | 功能描述 |
---|---|
RowSplit |
水平分割布局容器,将界面分为左右两部分 |
Column |
垂直布局容器,用于垂直排列子组件 |
Row |
水平布局容器,用于水平排列子组件 |
Scroll |
滚动容器,用于在有限空间内展示更多内容 |
Image |
图片组件,用于显示景点图片和图标 |
Text |
文本组件,用于显示行程信息和描述 |
Button |
按钮组件,用于添加行程、导航和分享操作 |
ForEach |
循环渲染组件,用于渲染行程列表和活动项 |
数据模型定义
在实现旅行规划应用之前,我们首先定义了两个接口来描述数据结构:
// 类型定义
interface TripDay {
day: string
date: string
location: string
description: string
hotel: string
restaurant: string
image: Resource
activities: Activity[]
}
interface Activity {
time: string
title: string
icon: Resource
}
这两个接口定义了旅行规划应用所需的数据结构:
TripDay
:表示一天的行程信息,包含日期、地点、描述、住宿、餐饮、图片和活动列表Activity
:表示一个具体的活动项,包含时间、标题和图标
代码实现
外层容器
我们使用RowSplit
组件作为最外层容器,将界面分为左右两部分:
RowSplit() {
// 左侧行程列表 (40%)
Column() {
// 行程列表内容
}
.width('40%')
.backgroundColor('#f1f8e9')
.padding(10)
// 右侧详情 (60%)
Column() {
// 详情内容
}
.padding(15)
.width('60%')
}
.height(600)
.width('100%')
RowSplit
设置了600的高度和100%的宽度,确保整个界面有足够的显示空间。左侧的行程列表区域占总宽度的40%,背景色为浅绿色,设置了10的内边距。右侧的详情区域占总宽度的60%,设置了15的内边距。
左侧行程列表
左侧行程列表区域包含标题、行程列表和添加按钮:
Column() {
Text('我的行程')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 15 })
Scroll() {
Column() {
ForEach(this.tripDays, (item: TripDay, index: number) => {
Column() {
Row() {
Text(item.day)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Text(item.date)
.fontSize(12)
.fontColor('#666666')
}
Text(item.location)
.fontSize(14)
.fontColor('#4CAF50')
.margin({ top: 2 })
}
.padding(5)
.width('100%')
.backgroundColor(index === this.selectedDay ? '#e8f5e9' : 'transparent')
.borderRadius(8)
.onClick(() => this.selectedDay = index)
})
}
}
.margin({ bottom: 10 })
Button('添加新行程')
.width('80%')
.margin({ bottom: 20 })
}
在这个区域中:
- 顶部是一个标题文本"我的行程",设置了字体大小、粗细和边距
- 中间是一个
Scroll
滚动容器,包含一个Column
,使用ForEach
循环渲染行程列表 - 每个行程项包含天数、日期和地点信息,设置了点击事件处理函数,点击时更新
selectedDay
状态 - 底部是一个"添加新行程"按钮
右侧详情区域
右侧详情区域包含顶部操作栏、内容区和底部操作按钮:
Column() {
// 顶部操作栏
Row() {
Text(this.tripDays[this.selectedDay].day + ' · ' + this.tripDays[this.selectedDay].location)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Image(this.showMap ? $r('app.media.big15') : $r('app.media.big14'))
.width(24)
.height(24)
.onClick(() => this.showMap = !this.showMap)
}
.padding({ bottom: 15 })
// 内容区(条件渲染)
if (this.showMap) {
// 地图视图
// ...
} else {
// 详情视图
// ...
}
// 底部操作按钮
Row() {
Button('导航')
.width(120)
.height(40)
Button('分享行程')
.width(120)
.height(40)
.margin({ left: 10 })
}
.margin({ top: 15 })
.justifyContent(FlexAlign.Center)
}
在这个区域中:
- 顶部操作栏显示当前选中的行程信息和一个切换按钮,用于切换地图视图和详情视图
- 内容区根据
showMap
状态条件渲染不同的内容 - 底部操作按钮包含"导航"和"分享行程"两个按钮
地图视图
当showMap
为true
时,显示地图视图:
Column() {
Image($r('app.media.big13'))
.width('100%')
.height(300)
.objectFit(ImageFit.Cover)
.borderRadius(8)
Text('地图位置')
.fontSize(16)
.margin({ top: 15 })
}
.height('100%')
地图视图包含一个地图图片和一个位置文本。
详情视图
当showMap
为false
时,显示详情视图:
Scroll() {
Column() {
// 景点图片
Image(this.tripDays[this.selectedDay].image)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(8)
.margin({ bottom: 15 })
// 行程描述
Text(this.tripDays[this.selectedDay].description)
.fontSize(16)
.lineHeight(24)
.margin({ bottom: 20 })
// 活动时间表
Text('当日行程')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Column() {
ForEach(this.tripDays[this.selectedDay].activities, (activity: Activity) => {
Row() {
Image(activity.icon)
.width(20)
.height(20)
.margin({ right: 15 })
Text(activity.time)
.fontSize(14)
.width(60)
Text(activity.title)
.fontSize(16)
}
.padding(10)
.margin({ bottom: 5 })
.backgroundColor('#f5f5f5')
.borderRadius(8)
})
}
.margin({ bottom: 20 })
// 住宿和餐饮
Column() {
// 住宿信息
Row() {
Image($r('app.media.01'))
.width(24)
.height(24)
.margin({ right: 10 })
Column() {
Text('住宿')
.fontSize(12)
.fontColor('#666666')
Text(this.tripDays[this.selectedDay].hotel)
.fontSize(16)
}
}
.padding(10)
.margin({ bottom: 5 })
.backgroundColor('#f5f5f5')
.borderRadius(8)
// 餐饮信息
Row() {
Image($r('app.media.02'))
.width(24)
.height(24)
.margin({ right: 10 })
Column() {
Text('餐饮')
.fontSize(12)
.fontColor('#666666')
Text(this.tripDays[this.selectedDay].restaurant)
.fontSize(16)
}
}
.padding(10)
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
}
}
详情视图包含以下内容:
- 景点图片:显示当前选中行程的图片
- 行程描述:显示当前选中行程的描述文本
- 活动时间表:使用
ForEach
循环渲染当前选中行程的活动列表 - 住宿和餐饮信息:显示当前选中行程的住宿和餐饮信息
布局技巧
1. 使用RowSplit实现左右分栏
RowSplit
组件是HarmonyOS NEXT中用于实现水平分割布局的容器组件,它可以将界面分为左右两部分,每部分可以设置不同的宽度比例。在本案例中,我们将左侧行程列表区域设置为总宽度的40%,右侧详情区域设置为总宽度的60%。
2. 使用Scroll处理溢出内容
在左侧行程列表和右侧详情视图中,我们都使用了Scroll
组件来处理可能的内容溢出情况。这样,当内容超出可视区域时,用户可以通过滚动来查看所有内容。
3. 使用条件渲染切换视图
在右侧详情区域,我们使用条件渲染来切换地图视图和详情视图:
if (this.showMap) {
// 地图视图
// ...
} else {
// 详情视图
// ...
}
这样,用户可以通过点击顶部操作栏中的切换按钮来切换不同的视图。
4. 使用ForEach循环渲染列表
在左侧行程列表和右侧详情视图的活动时间表中,我们都使用了ForEach
组件来循环渲染列表数据。这样,我们可以根据数据数组的长度动态生成列表项,而不需要手动编写重复的代码。
交互实现
1. 行程选择
在左侧行程列表中,我们为每个行程项添加了点击事件处理函数:
.onClick(() => this.selectedDay = index)
当用户点击一个行程项时,会更新selectedDay
状态,从而触发界面更新,显示对应的行程详情。
2. 视图切换
在右侧详情区域的顶部操作栏中,我们为切换按钮添加了点击事件处理函数:
.onClick(() => this.showMap = !this.showMap)
当用户点击切换按钮时,会切换showMap
状态,从而触发界面更新,切换地图视图和详情视图。
3. 状态管理
在本案例中,我们使用了@State
装饰器来定义组件的状态变量:
@State selectedDay: number = 0
@State showMap: boolean = false
@State tripDays: TripDay[] = [ /* ... */ ]
这些状态变量的变化会触发界面的自动更新,实现响应式的用户界面。
小结
在本教程中,我们学习了如何使用HarmonyOS NEXT的RowSplit
组件构建一个旅行规划应用。通过水平分割布局,我们将界面分为左侧行程列表和右侧详情区域,实现了行程选择、视图切换等交互功能。
- 0回答
- 4粉丝
- 0关注
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 水平分割布局RowSplit详解
- [HarmonyOS NEXT 实战案例:健康应用] 基础篇 - 水平分割布局打造健康数据仪表盘
- [HarmonyOS NEXT 实战案例:旅行应用] 进阶篇 - 旅行规划应用的交互功能与状态管理
- [HarmonyOS NEXT 实战案例:新闻阅读应用] 基础篇 - 水平分割布局构建新闻阅读界面
- [HarmonyOS NEXT 实战案例:音乐播放器] 基础篇 - 水平分割布局打造音乐播放器界面
- [HarmonyOS NEXT 实战案例:教育应用] 基础篇 - 垂直分割布局打造课程学习平台
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 垂直分割布局ColumnSplit详解
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 邮件应用布局设计
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 打造现代化设置中心界面
- 94.[HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 三栏垂直分割布局
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 可调整分割比例的垂直布局
- [HarmonyOS NEXT 实战案例:聊天应用] 基础篇 - 垂直分割布局构建聊天界面
- [HarmonyOS NEXT 实战案例:设置页面] 基础篇 - 垂直分割布局构建设置中心