效果图
完整代码
- 实例对象
javascript
export class ProvinceBean {
id?: string
pid?: string
isSelect?: boolean
deep?: object
extName?: string
children?: ProvinceBean[]
}
- 级联代码
javascript
import { MMKV } from '@tencent/mmkv/src/main/ets/utils/MMKV'
import { ProvinceBean } from '../../../../bean/ProvinceBean'
import { MMKVHelp } from '../../../../util/MMKVHelp'
interface CascadeInterface {
onClick?: (provinc: ProvinceBean) => void
close?: () => void
}
@Preview
@CustomDialog
export struct CascadeDialog {
controller: CustomDialogController
scrollerOne: Scroller = new Scroller()
scrollerTwo: Scroller = new Scroller()
scrollerThree: Scroller = new Scroller()
callback?: CascadeInterface
@State provinceList: ProvinceBean[] = new Array<ProvinceBean>()
@State cityList: ProvinceBean[] = new Array<ProvinceBean>()
@State areaList: ProvinceBean[] = new Array<ProvinceBean>()
@State selectId: string = ''
// 记录上次选择的数据在列表中的下标,显示数据时,自动滚动到可见位置
@State provinceIndex: number = 0
@State cityIndex: number = 0
@State areaIndex: number = 0
// 跟随父级 改变数据
@Prop provinceItem: ProvinceBean = new ProvinceBean()
// 临时记录省级数据
@State tempProvinceItem: ProvinceBean = new ProvinceBean()
aboutToAppear() {
let data = MMKV.defaultMMKV().decodeString(MMKVHelp.KEY_CITY)
if (data) {
this.selectId = this.provinceItem.id ? this.provinceItem.id : ''
this.provinceList = JSON.parse(data)
if (this.provinceList) {
this.provinceList.forEach((provinceBean, provinceIndex) => {
if (provinceBean.id == this.selectId) {
this.provinceIndex = provinceIndex
// 展开式 同步最新省级临时数据
this.tempProvinceItem = provinceBean
provinceBean.isSelect = true
this.cityList = provinceBean.children ? provinceBean.children : new Array<ProvinceBean>()
/**
* @Desc 一级列表匹配上 2种场景的点击
* 二级列表点击:1.全省 2.直辖市
*/
this.cityList[0].isSelect = true
} else {
provinceBean.isSelect = false
provinceBean.children?.forEach((cityBean, cityIndex) => {
if (cityBean.id == this.selectId) {
this.cityIndex = cityIndex
this.provinceIndex = provinceIndex
// 展开时,同步省级对应的数据
this.tempProvinceItem = provinceBean
provinceBean.isSelect = true
cityBean.isSelect = true
this.cityList = provinceBean.children ? provinceBean.children : new Array<ProvinceBean>()
this.areaList = cityBean.children ? cityBean.children : new Array<ProvinceBean>()
/**
* @Desc 二级列表匹配上 存在4种场景的点击
* 1.全省 2.直辖市 3.直辖市下的区 4.三级列表的全市(第一条)
*/
if (cityBean.children && cityBean.children.length > 0) { //第4种场景:
this.areaList[0].isSelect = true
} else {
// 直辖市下的区
console.log('直辖市下的区' + cityBean.extName)
}
} else {
cityBean.isSelect = false
cityBean.children?.forEach((areaBean, areaIndex) => {
if (areaBean.id == this.selectId) {
this.areaIndex = areaIndex
this.cityIndex = cityIndex
this.provinceIndex = provinceIndex
console.log('--22222---' + this.provinceIndex + ' = ' + this.cityIndex + ' = ' + this.cityIndex)
// 展开时,同步省对应的数据
this.tempProvinceItem = provinceBean
areaBean.isSelect = true
provinceBean.isSelect = true
cityBean.isSelect = true
this.cityList = provinceBean.children ? provinceBean.children : new Array<ProvinceBean>()
this.areaList = cityBean.children ? cityBean.children : new Array<ProvinceBean>()
} else {
areaBean.isSelect = false
}
})
}
})
}
})
}
}
}
build() {
Column() {
Row() {
List({ scroller: this.scrollerOne }) {
ForEach(this.provinceList, (provinceItem: ProvinceBean, index: number) => {
ListItem() {
Text(provinceItem.extName)
.width('100%')
.fontColor(provinceItem.isSelect ? '#007FFF' : '#FF000000')
.fontSize(12)
.padding({ left: 10, top: 10, bottom: 10 })
}.onClick(() => {
if (provinceItem.isSelect) {
console.log('点击的相同地区' + provinceItem.extName)
return
} else {
this.cityList.forEach(item => {
item.isSelect = false
})
this.areaList.forEach(item => {
item.isSelect = false
})
this.areaList = new Array<ProvinceBean>()
}
this.tempProvinceItem = provinceItem
this.upProvinceList(provinceItem)
this.cityList = provinceItem.children ? provinceItem.children : new Array<ProvinceBean>()
})
})
}.layoutWeight(1)
.backgroundColor(Color.White)
.height('100%').onSizeChange(() => {
this.scrollerOne.scrollToIndex(this.provinceIndex)
})
List({ scroller: this.scrollerTwo }) {
ForEach(this.cityList, (cityItem: ProvinceBean, KEY) => {
ListItem() {
Text(cityItem.extName)
.width('100%')
.fontColor(cityItem.isSelect ? '#007FFF' : '#FF000000')
.fontSize(12)
.padding({ left: 10, top: 10, bottom: 10 })
}.onClick(() => {
// cityItem.children :无数据说明是直辖市/省 ,有数据说明是市下的区
if (cityItem.children && cityItem.children.length > 0) { // 切换省下面的市
this.upCityList(cityItem)
if (!cityItem.isSelect) {
this.areaList.forEach(item => {
item.isSelect = false
})
}
this.areaList = cityItem.children ? cityItem.children : new Array<ProvinceBean>()
} else {
//直辖市/省
this.callback?.onClick!(cityItem)
}
})
})
}.layoutWeight(1).backgroundColor('#F6F6F6').height('100%').onSizeChange(() => {
this.scrollerTwo.scrollToIndex(this.cityIndex)
})
List({ scroller: this.scrollerThree }) {
ForEach(this.areaList, (areaItem: ProvinceBean, KEY) => {
ListItem() {
Text(areaItem.extName)
.width('100%')
.fontColor(areaItem.isSelect ? '#007FFF' : '#FF000000')
.fontSize(12)
.padding({ left: 10, top: 10, bottom: 10 })
}.onClick(() => {
this.callback?.onClick!(areaItem)
})
})
}.layoutWeight(1).backgroundColor('#F0F0F0').height('100%').onSizeChange(() => {
this.scrollerThree.scrollToIndex(this.areaIndex)
})
}.alignItems(VerticalAlign.Top)
.width('100%')
.height(500)
}.onClick(() => {
this.controller?.close!()
}).backgroundColor("#90000000").height('100%')
}
/**
* @Desc 更新省:自身列表的ui状态
*/
private upProvinceList(provinceItem: ProvinceBean) {
let temp = this.provinceList
temp.forEach(item => {
if (provinceItem.id == item.id) {
item.isSelect = true
} else {
item.isSelect = false
}
})
this.provinceList = new Array<ProvinceBean>()
this.provinceList = temp
}
/**
* @Desc 更新城市:自身列表的ui状态
*/
private upCityList(itemBean: ProvinceBean) {
let temp = this.cityList
temp.forEach(item => {
if (itemBean.id == item.id) {
item.isSelect = true
} else {
item.isSelect = false
}
})
this.cityList = new Array<ProvinceBean>()
this.cityList = temp
}
}
- 使用
javascript
@State provinceItem: ProvinceBean = new ProvinceBean()
this.controller = new CustomDialogController({
builder: CascadeDialog({
provinceItem: this.provinceItem,
callback: {
onClick: (province: ProvinceBean) => {
console.log(JSON.stringify(province))
this.provinceItem = province
this.controller?.close()
}
}
}),
cancel: () => {
this.controller?.close()
},
offset: { dx: 0, dy: this.postionY },// 弹窗的偏移量
autoCancel: true,
customStyle: true,
maskColor: Color.Transparent,
openAnimation: { duration: 0 },
closeAnimation: { duration: 0 }
});
this.controller.open()
- 获取点击组件,组件底部距离屏幕顶部的高度
javascript
.onClick((event: ClickEvent) => {
this.postionY = Number(event.target.area.height) + Number(event.target.area.globalPosition.y)
})