[应用开发]HarmonyOS鸿蒙Next中List页面设计开发
[应用开发]HarmonyOS鸿蒙Next中List页面设计开发 随易App开发实战 :List页面设计开发
项目地址:app_EasyRandom: 随易app (gitee.com)
本案例,将通过List组件ForEach循环渲染配合断点功能,设计实现一个完整的响应式的列表渲染的List页面案例,该页面的主体List组件会在大设备中显示3列,在中小设备分别显示2列和3列。希望能助力您的应用开发,完整代码在文章末尾。
相关技术要素:
本案例依照本人开发的原生应用随易,本案例完整代码将写在文章最后,项目的完整代码和详情请访问:随易Gitee项目地址(本案例文件位于项目product/default/src/main/ets/pages/MorePage文件中)
项目整体结构:
├── common/src/main/ets /公共库
│ ├── components //公共组件
│ └── utils //公共函数库
├── product/default/src/main/ets // 代码区
│ ├── entryability //页面Ability
│ ├── components //子组件
│ ├── constants //公共常量
│ ├── datas //页面数据
│ ├── pages //主要页面
│ ├── defaultformability //卡片Ability
│ └── widgets //卡片组件
└── product/default/src/main/resources // 资源文件目录
具体实现:
- 首先要进行对于组件的数据类型进行分析,通过统一的数据类型方便后续的循环渲染,数据显示方面需要图片和标题,在功能性上则需要根据需求设计(例如需要路由功能可添加路由路径与参数)。为了后续的样式定义还可以预留一个颜色类型,因此设计如下数据结构并建立示例数据:
class AppItem {
name: string
img: Resource
url: string | null
params: string | null
colors: Array<[ResourceColor, number]> | null
constructor(name: string, img: Resource, url: string, params: string | null,
colors: Array<[ResourceColor, number]> | null) {
this.name = name;
this.img = img;
this.url = url
this.params = params
this.colors = colors
}
}
let Apps: Array<AppItem> = [
new AppItem('八卦', $r("app.media.icon_DevineBaGua"),
'components/DevineBaGua', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
new AppItem('祝福木鱼', $r("app.media.MuYu"),
'components/RollBlessings', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
new AppItem('人生必去的100个地方', $r("app.media.icon_RandomPlace"),
'components/RandomPlaces', '', null),
new AppItem('二维码转换', $r("app.media.QRcode"),
'components/TransQR', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
];
- 使用List、ListItem组件配合列表渲染完成组件基础搭建
2.1 子组件ListItem封装
通过子组件的封装和统一的数据结构,方便后续的列表渲染。在组件添加onClick事件函数,如此处为组件添加router功能,在数据定义时便可统一给组件的跳转位置和附带参数进行赋值,方便后续的修改添加等。
@Builder
ListItem(app: AppItem) {
Row() {
Column() {
Row() {
Image(app.img)
.height('96%')
.margin('2%')
.aspectRatio(1)
.border({
color: Color.Blue,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
Text(app.name.toString())
.opacity(0.88)
.fontColor(0x000000)
.fontSize('80%')
.fontWeight(800)
.textAlign(TextAlign.Center)
}
.position({ left: 0 })
}
.width('98%')
.margin({ left: '1%', right: '1%', top: '5%' })
.aspectRatio(5 / 2)
.backgroundColor($r("app.color.view_bgc_1"))
.border({
color: Color.Red,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
}
.width('100%')
.border({
color: Color.Blue,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.onClick(() => {
router.pushUrl({ url: app.url, params: app.params })
})
}
之前规范定义的参数在此便能够充分发挥作用,通过合理的赋值关系方便后续统一的进行列表渲染
2.2 forEach循环渲染
通过forEach循环渲染,我们可以方便的通过数据驱动来修改页面内容,方便后续的更改与维护。
List() {
ForEach(this.DataList, (app: AppItem) => {
ListItem() {
this.ListItem(app)
}
})
}
2.3 调整组件样式
外观样式比较主观,仅作简单参考(完整示例代码在文章末尾)。List组件的具体开发细节可查看官方文档,在此列举几个重要的属性和用法:
- lanes():列表列数,此属性为后续的响应式布局提供基础,内部传入number类型可决列表的列数
- padding():
- 响应式(通过监听断点实现)
首先要了解ArkUI有很多种实现响应式和监听的方式:可在此链接选择响应式布局-布局能力,这里选择使用断点BreakPoint来实现,断点的基础使用方式如下:
import { BreakpointState, BreakpointSystem } from '@ohos/common'
//以上文件为从官网案例中下载
@State currentBreakpoint: BreakpointState<string> = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })
aboutToAppear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().start()
}
aboutToDisappear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().stop()
}
此响应式的关键点便在于将断点值与上文提到的重要属性lanes()
有机结合,使用三元运算符this.currentBreakpoint.value === 'sm' ? 1 : (this.currentBreakpoint.value === 'md' ? 2 : 3)
。便可轻松实现小设备显示1列,中设备显示两列,大设备显示三列的效果。可根据实际情况进行调整,使用其它监听方式也同样可以使用此方法完成响应式操作,完整写法如下:
@Entry
@Component
struct MorePage {
@State DataList: Array<AppItem> = Apps;
@State currentBreakpoint: BreakpointState<string> = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })
@State fontSize: number = 16;
aboutToAppear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().start()
}
aboutToDisappear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().stop()
}
build() {
Column() {
List() {
ForEach(this.DataList, (app: AppItem) => {
ListItem() {
this.ListItem(app)
}
})
}
.width('100%')
.height('100%')
.lanes(this.currentBreakpoint.value === 'sm' ? 1 : (this.currentBreakpoint.value === 'md' ? 2 : 3))
.padding({ left:this.currentBreakpoint.value=='sm'?6:12,right:this.currentBreakpoint.value=='sm'?6:12})
}
}
}
项目完整代码可前往app_EasyRandom - 码云 - 开源中国 (gitee.com)
页面完整代码:
import { BreakpointState, BreakpointSystem } from '@ohos/common';
import router from '@ohos/router';
class AppItem {
name: string
img: Resource
url: string | null
params: string | null
colors: Array<[ResourceColor, number]> | null
constructor(name: string, img: Resource, url: string, params: string | null,
colors: Array<[ResourceColor, number]> | null) {
this.name = name;
this.img = img;
this.url = url
this.params = params
this.colors = colors
}
}
let Apps: Array<AppItem> = [
new AppItem('八卦', $r("app.media.icon_DevineBaGua"),
'components/DevineBaGua', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
new AppItem('祝福木鱼', $r("app.media.MuYu"),
'components/RollBlessings', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
new AppItem('人生必去的100个地方', $r("app.media.icon_RandomPlace"),
'components/RandomPlaces', '', null),
new AppItem('二维码转换', $r("app.media.QRcode"),
'components/TransQR', '', [[0x00beff, 0], [0xffeb00, 0.5], [0xffff00, 1]]),
];
@Entry
@Component
struct MorePage {
@State DataList: Array<AppItem> = Apps;
@State currentBreakpoint: BreakpointState<string> = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })
@State fontSize: number = 16;
aboutToAppear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().start()
}
aboutToDisappear() {
BreakpointSystem.getInstance().attach(this.currentBreakpoint)
BreakpointSystem.getInstance().stop()
}
@Builder
ListItem(app: AppItem) {
Row() {
Column() {
Row() {
Image(app.img)
.height('96%')
.margin('2%')
.aspectRatio(1)
.border({
color: Color.Blue,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
Text(app.name.toString())
.opacity(0.88)
.fontColor(0x000000)
.fontSize('80%')
.fontWeight(800)
.textAlign(TextAlign.Center)
}
.position({ left: 0 })
}
.width('98%')
.margin({ left: '1%', right: '1%', top: '5%' })
.aspectRatio(5 / 2)
.backgroundColor($r("app.color.view_bgc_1"))
.border({
color: Color.Red,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
}
.width('100%')
.border({
color: Color.Blue,
width: 0,
style: BorderStyle.Solid,
radius: 12
})
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.onClick(() => {
router.pushUrl({ url: app.url, params: app.params })
})
}
build() {
Column() {
List() {
ForEach(this.DataList, (app: AppItem) => {
ListItem() {
this.ListItem(app)
}
})
}
.width('100%')
.height('100%')
.lanes(this.currentBreakpoint.value === 'sm' ? 1 : (this.currentBreakpoint.value === 'md' ? 2 : 3))
.padding({ left:this.currentBreakpoint.value=='sm'?6:12,right:this.currentBreakpoint.value=='sm'?6:12})
}
}
}
export default MorePage
更多关于[应用开发]HarmonyOS鸿蒙Next中List页面设计开发的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,List页面的设计开发主要涉及使用ArkUI框架进行界面构建。ArkUI是鸿蒙系统提供的一套声明式UI开发框架,支持使用TypeScript或JavaScript进行开发。
-
页面布局:List页面通常使用
List
组件来展示数据列表。List
组件支持垂直和水平滚动,可以通过ListItem
组件定义每个列表项的布局。布局可以使用Flex
、Column
、Row
等组件进行灵活配置。 -
数据绑定:List页面中的数据通常通过
@State
、@Prop
、@Link
等装饰器进行状态管理。可以使用ForEach
组件遍历数据源,动态生成列表项。数据源可以是数组、对象等数据结构。 -
交互事件:List页面中的交互事件可以通过
onClick
、onSwipe
等事件处理器进行处理。例如,点击列表项可以跳转到详情页面,滑动列表项可以触发删除操作。 -
样式与主题:List页面的样式可以通过
Style
组件进行定义,支持使用CSS-like的语法。鸿蒙系统还提供了主题机制,可以根据系统主题自动适配页面样式。 -
性能优化:为了提高List页面的渲染性能,可以使用
LazyForEach
组件进行懒加载,减少不必要的渲染操作。此外,还可以通过RecyclerView
组件实现列表项的复用,进一步提升性能。 -
API调用:List页面中可能需要调用鸿蒙系统提供的API,例如网络请求、本地存储等。可以使用
@ohos
命名空间下的模块进行相关操作。
通过以上步骤,可以在HarmonyOS鸿蒙Next中完成List页面的设计开发。
更多关于[应用开发]HarmonyOS鸿蒙Next中List页面设计开发的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中开发List页面,首先使用ListContainer
组件作为列表容器。通过ListContainer.ItemProvider
提供数据源,并在onItemBind
方法中绑定数据到UI。可以使用ListContainer.ItemAnimator
实现列表项动画效果。为了提高性能,建议使用RecycleItemProvider
进行列表项复用。通过ListContainer.setOrientation
设置列表方向,支持垂直和水平布局。最后,通过ListContainer.setItemClickListener
处理列表项点击事件,实现交互逻辑。