OpenHarmony – ArkUI(TS)开发之下拉选择菜单

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前言

鸿蒙3.0推出了一种新的开发方式ETS,本文通过采用ETS实现我们项目开发中比较常见的下拉选择菜单组件来初步了解和体验下ETS的开发规范和方法,主要用到的TS知识点有Flex布局、文本展示、样式绑定、图片引入、父子组件变量共享、参数传递、ForEach循环遍历、事件绑定。

实现效果

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

用到的装饰

装饰器

装饰内容

说明

@Component

struct

结构体在装饰后具有基于组件的能力,需要实现build方法来更新UI。

@Entry

struct

组件被装饰后作为页面的入口,页面加载时将被渲染显示。

@Builder

方法

在@Builder装饰的方法用通过声明式UI描述,可以在一个自定义组件内快速生成多个布局内容。

@Provide

基本数据类型,类,数组

@Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。

@Consume

基本数据类型,类,数组

@Consume装饰的变量在感知到@Provide装饰的变量更新后,会触发当前自定义组件的重新渲染。

创建ETS工程

  1. 在DevEco Studio中新建一个ETS工程,语言选择ets

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

  1. 在entry -> src -> main -> ets -> default -> pages目录下新建自己的.ets文件,即可以开始编写ets代码。

OpenHarmony - ArkUI(TS)开发之下拉选择菜单

功能分解

  1. 创建一个Flex布局的卡片。
Flex({justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center}) {
}
.height(64)
.width('100%')
.backgroundColor('#fff')
.borderRadius(16)
.padding({
left: 16,
right: 16
})
  1. 在卡片中填充内容。
Column() {
Text('模式选择')
.fontSize(16)
Text('清洁模式')
.fontSize(12)
.alignSelf(ItemAlign.Start)
.fontColor('rgba(0, 0, 0, 0.6)')
.margin({
top: 2
})
}
  1. 图片资源的引入,icon.png存在resources->base->media目录下。
Column() {
Flex(){
Image($r('app.media.icon'))
.objectFit(ImageFit.Contain)
}
.height(24)
.width(24)
}
  1. 绑定点击事件。
.onClick(() => {
this.showSelector = !this.showSelector;
console.log('showSelector==='+this.showSelector)
})
  1. 循环输出标签。
ForEach(this.modesData, item => {
Flex(){
ModeItem({ mode: item })
}
// 为每一项绑定点击事件
.onClick(() => {
if (this.modeId !== item.id) {
this.modeId = item.id
console.info('this.modeId==='+this.modeId)
}
this.showSelector = false
})

}, item => item.id.toString())
  1. 父子组件共享变量。

父组件中使用@Provide修饰变量,子组件使用@Consume修饰同一个变量名,即可以实现共享。

// 父组件
@Entry
@Component
struct SelectorIndex {
@Provide modeId: number = 0 // 定义当前选中项id
build() {
Flex() {
SelectorList() // 显示子组件
}
}
}
// 子组件
@Component
struct SelectorList {
@Consume modeId: number // 共享父组件属性
build() {
Flex(){

}.onClick(() => {
console.log(this.modeId) // 打印当前选中项id
})
}
}

完整代码

// 数据类型定义
export class ModeType {
id: number
name: string
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
// 单个选择项的渲染
@Component
struct ModeItem {
private mode: ModeType
@Consume modeId : number
@Builder renderModeItem(fontColor: string, bgColor: string, value: string) {
Flex({direction: FlexDirection.Column}) {
Flex(){
Text(value)
.fontSize(16)
.fontColor(fontColor)
}
.height('100%')
.width('100%')
.backgroundColor(bgColor)
.borderRadius(12)
.padding({
left: 14,
top: 14,
bottom: 14
})
// 最后一项不显示分隔线
if (this.mode.id != 5) {
Flex() {
Flex() {
}.height(1).width('100%').backgroundColor('#F3F3F3')
}
.padding({
left: 12,
right: 12
})
}
}
}
build() {
Flex(){
// 选中项和其他选项的样式有不同
if (this.modeId == this.mode.id) {
this.renderModeItem('#0A59F7', '#E6EEFF', this.mode.name)
} else {
this.renderModeItem('rgba(0,0,0,0.9)', '', this.mode.name)
}
}.height(48)
}
}
// 下拉菜单组件
@Component
struct SelectorList {
@Consume modesData: any // 共享父组件属性
@Consume modeId: number // 共享父组件属性
@Consume showSelector: boolean // 共享父组件属性
build() {
Flex({direction: FlexDirection.Column, justifyContent: FlexAlign.Start}) {
// 循环产生下拉菜单
ForEach(this.modesData, item => {
Flex(){
ModeItem({ mode: item })
}
// 为每一项绑定点击事件
.onClick(() => {
if (this.modeId !== item.id) {
this.modeId = item.id
console.info('this.modeId==='+this.modeId)
}
this.showSelector = false
})

}, item => item.id.toString())
}
.height(248)
.width('100%')
.backgroundColor('#fff')
.borderRadius(16)
.shadow({
radius: 50,
color: 'rgba(0,0,30,0.1500)'
})
.padding({
left: 4,
right: 4,
top: 4,
bottom: 4
})
.position({
x: 0,
y: -260
})
.zIndex(1)
}
}
// 入口组件
@Entry
@Component
struct SelectorIndex {
@Provide showSelector: boolean = false // 是否展开下拉菜单
@Provide modesData: any = [{id: 1,name: '节能模式'},{id: 2,name: '强劲模式'},{id: 3,name: '深层模式'},{id: 4,name: '清洁模式'},{id: 5,name: '敏感模式'}]
@Provide modeId: number = 0 // 当前选中项id
build() {
Flex({direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
Text('其他内容1').fontSize(16)
}.height(88).width('100%').backgroundColor('#fff').borderRadius(16)

Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) {
if (this.showSelector) {
SelectorList()
}
Flex({justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center}) {
Column() {
Text('模式选择')
.fontSize(16)
if (this.getSelectedText()) {
Text(this.getSelectedText())
.fontSize(12)
.alignSelf(ItemAlign.Start)
.fontColor('rgba(0, 0, 0, 0.6)')
.margin({
top: 2
})
}
}
Column() {
Flex(){
Image($r('app.media.icon'))
.objectFit(ImageFit.Contain)
}
.height(24)
.width(24)
}
}
.height(64)
.width('100%')
.backgroundColor('#fff')
.borderRadius(16)
.padding({
left: 16,
right: 16
})
.onClick(() => {
this.showSelector = !this.showSelector;
console.log('showSelector==='+this.showSelector)
})

}
.height(64)
.margin({
top: 12,
bottom: 12
})

Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
Text('其他内容2').fontSize(16)
}.height(88).width('100%').backgroundColor('#fff').borderRadius(16)
}
.height('100%')
.width('100%')
.backgroundColor('#f1f3f5')
.padding({
left: 12,
right: 12,
top: 16,
bottom: 16
})
.onClick(() => {
this.showSelector = false
})
}
// 获取选中项的内容
getSelectedText() {
const selectedItem = this.modesData.find(item => {
return item.id == this.modeId
})
if (selectedItem) {
return selectedItem.name
}
return ''
}
}

总结

从上面的示例我们可以感受到基于TS扩展的声明式开发范式的方舟开发框架,采用链式调用的编程方式,可以更直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,另外也提供了丰富的系统能力接口,真正实现极简高效开发。大家感兴趣的话可以通过TS开发官方文档进行详细的了解和学习。华为鸿蒙官方也发布了3 个超级实用的基于 TS 扩展的声明式开发范式示例,分别是eTSBuildCommonView 创建简单视图示例、eTSDefiningPageLayoutAndConnection 页面布局和连接示例、eTSDrawingAndAnimation 绘图和动画示例,可以下载代码体验和学习。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

文章版权声明

 1 原创文章作者:4629,如若转载,请注明出处: https://www.52hwl.com/105626.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年1月17日 下午8:06
下一篇 2024年1月17日 下午8:07