介紹
本示例介紹如何使用bindSheet,changeIndex,onAreaChange實現帶切換動效的自定義地址選擇組件。
效果圖預覽
使用說明
進入頁面,點擊場景一中“所在地區”一欄,可拉起省市區的地址選擇彈窗。選擇完區后,彈窗自動關閉,“所在地區”一欄顯示當前選擇的省市區名。
進入頁面,點擊場景二中的'獲取地址信息'按鈕,可以查看省市區名和相應的id。點擊“所在地區”一欄,在拉起的地址選擇彈窗里選擇另一個省市區后,再次點擊'獲取地址信息'按鈕,會顯示最新選擇的省市區的信息。
實現思路
- 使用getRawFileContentSync從rawfile目錄下讀取省市區json文件數據,使用util.TextDecoder進行解碼。
getAddressData(): Array<Province> {
// 從rawfile本地json文件中獲取數據
const value = getContext().resourceManager.getRawFileContentSync(this.jsonFileDir);
// 解碼為utf-8格式
const textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
const textDecoderResult = textDecoder.decodeToString(new Uint8Array(value.buffer));
const jsonObj: JsonObjType = JSON.parse(textDecoderResult) as JsonObjType;
const modelBuckets: Array<Province> = [];
// 映射json數據為model對象
const modelObj = jsonObj.addressList;
for (let i = 0; i < modelObj.length; i++) {
const contactTemp = new Province(modelObj[i].code, modelObj[i].name, modelObj[i].children);
// 從json中讀取每個省數據寫入modelBuckets
modelBuckets.push(contactTemp);
}
return modelBuckets;
}
- 使用bindSheet綁定地址選擇半模態彈窗頁面。
Row() {
// ...
}
.width($r('app.string.custom_address_picker_full_size'))
.height($r('app.float.custom_address_picker_size_forty_eight'))
.onClick(() => {
// 顯示地址選擇半模態彈窗頁面
this.isShow = true;
this.currentIndex = AddressType.Province;
})
.bindSheet($$this.isShow, this.addressSelectPage(), {
height: $r('app.string.custom_address_picker_percent_seventy'), // 半模態彈窗高度
showClose: false, // 設置不顯示自帶的關閉圖標
dragBar: false,
onDisappear: () => {
// 退出地址選擇半模態彈窗頁面時,重置相關參數
this.animationDuration = 0;
// 如果當前省市區沒選全,則清空當前選擇的地址信息
if (this.currentSelectInfo.region === '') {
this.currentSelectInfo.provinceId = '';
this.currentSelectInfo.cityId = '';
this.currentSelectInfo.regionId = '';
this.currentSelectInfo.province = '';
this.currentSelectInfo.city = '';
this.currentSelectInfo.region = '';
this.cityList = [];
this.regionList = [];
}
}
})
- 使用changeIndex控制省市區列表TabContent切換。使用組件區域變化回調onAreaChange獲取選擇的省市區Text組件寬度,存入textInfos數組,用于后續計算選擇省市區名后下方下滑線動畫水平偏移量leftMargin。
Text(`${params.name === '' ? '請選擇' : params.name} `)
.height($r('app.string.custom_address_picker_full_size'))
.fontSize($r('app.float.custom_address_picker_size_sixteen'))
.fontWeight(this.currentIndex === params.index ? Constants.FONT_WEIGHT_FIVE_HUNDRED :
Constants.FONT_WEIGHT_FOUR_HUNDRED)
.fontColor(this.currentIndex === params.index ? $r('app.color.custom_address_picker_font_color_black') :
$r('app.color.custom_address_picker_font_color_gray'))
.constraintSize({ maxWidth: 'calc(33%)' })
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(Constants.SIZE_ONE)
.onClick(() => {
// 使用changeIndex控制省市區列表TabContent切換
this.controller.changeIndex(params.index);
})
.id(params.index.toString())
.onAreaChange((oldValue: Area, newValue: Area) => {
// 使用組件區域變化回調onAreaChange獲取選擇的省市區Text組件寬度,存入textInfos數組,用于后續計算選擇省市區名后下方下滑線動畫水平偏移量leftMargin
// 組件區域變化時獲取當前Text的寬度newValue.width和x軸相對位置newValue.position.x
this.textInfos[params.index] = [newValue.position.x as number, newValue.width as number];
if (this.currentIndex === params.index && params.index === AddressType.Province) {
// 計算選擇的省市區名下方的下滑線偏移量
this.leftMargin = (this.textInfos[this.currentIndex][1] - Constants.DIVIDER_WIDTH) / 2;
}
})
- 在選擇完區名后,使用JSON.parse(JSON.stringify(xxx))深拷貝選擇的省市區數據,用于后續操作中需要加載上一次選擇的完整省市區數據。
List() {
ForEach(this.regionList, (item: CommonAddressList) => {
ListItem() {
this.areaNameItem(AddressType.Region, item)
}.onClick(() => {
// 記錄選擇的區信息
this.currentSelectInfo.regionId = item.code;
this.currentSelectInfo.region = item.name;
this.provinceCityRegion =
this.currentSelectInfo.province + this.currentSelectInfo.city + this.currentSelectInfo.region;
// 選擇區后,退出地址選擇半模態彈窗頁面
this.isShow = false;
// 將當前選中省市區信息保存到lastSelectInfo
this.lastSelectInfo.provinceId = this.currentSelectInfo.provinceId;
this.lastSelectInfo.province = this.currentSelectInfo.province;
this.lastSelectInfo.cityId = this.currentSelectInfo.cityId;
this.lastSelectInfo.city = this.currentSelectInfo.city;
this.lastSelectInfo.regionId = this.currentSelectInfo.regionId;
this.lastSelectInfo.region = this.currentSelectInfo.region;
// TODO 知識點:在選擇完區名后,使用JSON.parse(JSON.stringify(xxx))深拷貝選擇的省市區數據,用于后續操作中需要加載上一次選擇的完整省市區數據
// 深拷貝保存到相應的變量中
this.lastCityList = JSON.parse(JSON.stringify(this.cityList));
this.lastRegionList = JSON.parse(JSON.stringify(this.regionList));
this.address = JSON.parse(JSON.stringify(this.lastSelectInfo));
})
}, (item: CommonAddressList) => JSON.stringify(item))
}
高性能知識點
本示例中如果當前點擊選擇的省或者市與之前選擇一樣,則跳過省、市數據獲取,直接調用changeIndex(AddressType.City)切換到下一級地區列表,減少冗余查詢以提升性能。
工程結構&模塊類型
customaddresspicker // har類型
|---pages
| |---AddressPickerSample.ets // 地址選擇場景頁面
|---customaddresspicker
| |---constant
| | |---Constants.ets // 常量定義
| |---model
| | |---AddressModel.ets // 地址選擇相關類
| |---utils
| | |---JsonUtils.ets // json工具類
| |---view
| | |---CustomAddressPicker.ets // 自定義地址選擇組件
模塊依賴
本示例依賴路由模塊來注冊路由。
寫在最后
- 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
- 關注小編,同時可以期待后續文章ing??,不定期分享原創知識。
- 想要獲取更多完整鴻蒙最新學習知識點,請移步前往小編:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu