想了解更多关于开源的内容,请访问:
鸿蒙开发者社区
前言
hello 大家好,我是无言,因为地址级联选择功能其实还是非常常见的,而且官方有TextPicker文本选择组件也可以实现地址级联选择,但是我发现超过3级之后,文字就太多了,会很难看,不好操作等相关问题。所以有必要自己来实现一个好看的省市区镇-四级地址级联选择组件。
目的
通过本篇文章小伙伴们能学到什么?我简单的总结了一下大概有以下几点。
效果提前看一看:
实现过程
一、准备工作
二、实现自定义弹窗
// xxx.ets@CustomDialogstruct CustomDialogExample {controller?: CustomDialogControllercancel: () => void = () => {}confirm: () => void = () => {}build() {Column() {Text('这是自定义弹窗').fontSize(30).height(100)Button('点我关闭弹窗').onClick(() => {if (this.controller != undefined) {this.controller.close()}}).margin(20)}}}// @Entry去掉入口页面标志@Componentexportstruct CustomDialogCascade { //修改命名 注意前面加了 export 需要暴露组件dialogController: CustomDialogController | null = new CustomDialogController({builder: CustomDialogExample({cancel: ()=> { this.onCancel() },confirm: ()=> { this.onAccept() }}),cancel: this.existApp,autoCancel: true,onWillDismiss:(dismissDialogAction: DismissDialogAction)=> {console.info("reason=" + JSON.stringify(dismissDialogAction.reason))console.log("dialog onWillDismiss")if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {dismissDialogAction.dismiss()}if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {dismissDialogAction.dismiss()}},alignment: DialogAlignment.Center,offset: { dx: 0, dy: -20 },customStyle: false,cornerRadius: 20,width: 300,height: 200,borderWidth: 1,borderStyle: BorderStyle.Dashed,//使用borderStyle属性,需要和borderWidth属性一起使用borderColor: Color.Blue,//使用borderColor属性,需要和borderWidth属性一起使用backgroundColor: Color.White,shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}),})// 在自定义组件即将析构销毁时将dialogController置空aboutToDisappear() {this.dialogController = null // 将dialogController置空}onCancel() {console.info('Callback when the first button is clicked')}onAccept() {console.info('Callback when the second button is clicked')}existApp() {console.info('Click the callback in the blank area')}build() {Column() {Button('click me').onClick(() => {if (this.dialogController != null) {this.dialogController.open()}}).backgroundColor(0x317aff)}.width('100%').margin({ top: 5 })}}
import {CustomDialogCascade} from "../components/cascade/index"@Entry@Componentstruct Index {build() {RelativeContainer() {CustomDialogCascade()}.height('100%').width('100%')}}
预览一下看看效果。
三、实现父子组件的通信
在讲后续功能前,这里有必要讲一下鸿蒙开发组件状态。
@State @Watch('onCountChange') count: number = 0/** * 一旦count变化,此回调函数就会自动调用 * @param count被监视的状态属性名 */onCountChange (count) {// 可以在此做特定处理}
四、完善逻辑
好了回到我们的主题,前面我们的示例中,只是子组件自己调用弹窗了,我们要实现以下几个功能。
修改/ets/components/cascade/index.ets,实现父组件传参给子组件,子组件回调方法传值给父组件。然后还修改了弹窗的样式以及位置,详细请看下面代码。
// xxx.ets@CustomDialogstruct CustomDialogExample {controller?: CustomDialogController@Prop level: number;cancel: () => void = () => {}confirm: (data:string) => void = () => {}build() {Column() {Text('这是自定义弹窗').fontSize(30).height(100)Text('层级'+this.level)Button('点我关闭弹窗').onClick(() => {if (this.controller != undefined) {this.controller.close()}this.confirm('aaa') //回传信息}).margin(20)}}}// @Entry去掉入口页面标志@Componentexportstruct CustomDialogCascade { //修改命名 注意前面加了 export 需要暴露组件@Link CustomDialogController: CustomDialogController | null ;@Prop level: number;cancel?: () => voidconfirm?: (data:string) => void = () => {}aboutToAppear(): void {this.CustomDialogController=new CustomDialogController({builder: CustomDialogExample({cancel: this.cancel,confirm: this.confirm,level:this.level,}),autoCancel: true,onWillDismiss:(dismissDialogAction: DismissDialogAction)=> {if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {dismissDialogAction.dismiss()}if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {dismissDialogAction.dismiss()}},alignment: DialogAlignment.Bottom,offset: { dx: 0, dy:0},customStyle: false,cornerRadius: 0,width: '100%',backgroundColor: Color.White,})}aboutToDisappear() {this.CustomDialogController = null // 将dialogController置空}build() { //因为用的 自定义弹窗功能,所以这下面可以为空}}
修改/ets/pages/index.ets 文件实现功能主要是父元素调用子组件方法,以及子组件的回调方法调用。
import {CustomDialogCascade} from "../components/cascade/index"@Entry@Componentstruct Index {@State CustomDialogController :CustomDialogController|null = null;build() {Column() {Button('打开弹窗').onClick(()=>{this.CustomDialogController?.open()})CustomDialogCascade({level:3,//层级 最大4最小1CustomDialogController:this.CustomDialogController, //弹窗实体类 主要控制弹窗显示隐藏等confirm:(data)=>{console.log('data',(data))}},)}.height('100%').width('100%')}}
运行效果如下,点击点我关闭弹窗按钮可以发现 子组件的回调信息aaa在父组件中成功打印。
五、完善地址级联逻辑
export const regionDict = {"86": {"110000": "北京市","120000": "天津市","130000": "河北省",...},"110000": {"110100": "北京市"},"110100": {"110101": "东城区","110102": "西城区","110105": "朝阳区","110106": "丰台区","110107": "石景山区","110108": "海淀区","110109": "门头沟区","110111": "房山区","110112": "通州区","110113": "顺义区","110114": "昌平区","110115": "大兴区","110116": "怀柔区","110117": "平谷区","110118": "密云区","110119": "延庆区"},"110101": {"110101001": "东华门街道","110101002": "景山街道"},...};
exportinterface RegionType{code?:string;pcode?:string;name?:string}exporttype levelNumber = 1 | 2 | 3 | 4;
import { regionDict } from "./addressObj"import {RegionType,levelNumber} from './Cascade'@CustomDialogexportstruct CustomAddress {controller?: CustomDialogController@State region:RegionType[]=[]; //存放选中的结果@State>
import{CustomAddress }from"./CustomAddress"import {RegionType,levelNumber} from './Cascade'export{RegionType }from './Cascade' //重新暴露声明文件类型// @Entry去掉入口页面标志@Componentexportstruct CustomDialogCascade { //修改命名 注意前面加了 export 需要暴露组件@Link CustomDialogController: CustomDialogController | null ;@Prop level: levelNumber;cancel?: () => voidconfirm?: (data:RegionType[]) => void = () => {}aboutToAppear(): void {this.CustomDialogController=new CustomDialogController({builder: CustomAddress({cancel: this.cancel,confirm: this.confirm,level:this.level,}),autoCancel: true,onWillDismiss:(dismissDialogAction: DismissDialogAction)=> {if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {dismissDialogAction.dismiss()}if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {dismissDialogAction.dismiss()}},alignment: DialogAlignment.Bottom,offset: { dx: 0, dy:0},customStyle: false,cornerRadius: 0,width: '100%',backgroundColor: Color.White,})}aboutToDisappear() {this.CustomDialogController = null // 将dialogController置空}build() {}}
重新运行一下,当街道选好之后,即可发现弹窗自动关闭,而且选好地址信息成功拿到。
总结
本文详细介绍了关于在华为鸿蒙系统去实现一个自定义弹窗的详细教程,主要是提供一些思路,了解组件之间通信的技巧,以及如何实现一个地址级联选中的详细过程。
想了解更多关于开源的内容,请访问:
鸿蒙开发者社区
本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载者并注明出处:https://jmbhsh.com/keji/36137.html