应用场景


  我们在app开发中经常需要用到定位、地图的功能,想要在应用中使用,我们需要在应用中进行权限的动态请求,在app管理相对严格的今天,我们申请权限请求还需要对权限进行一个同步的说明弹窗,说明清楚我们为什么要申请这个权限,以及用到什么地方,这时候我们就需要用到鸿蒙开发中的自定义弹窗技术。下面我将详细讲解如何通过自定义弹窗来实现我们的需求


我们要实现的效果

 #HarmonyOS NEXT体验官#如何使用自定义弹窗实现一个跟系统权限弹窗同步呼出的权限说明弹窗_Text

看到需求的一瞬间,整个人都清爽了,啊~就是个简单的弹窗而已,分分钟写完开始摸鱼。


“需要与系统的权限请求弹窗进行同步开启,和同步关闭”


????问号脸(把产品叫过来 !!!!)


还要跟系统的权限一起?这在别的开发里可是要第三方开源库引用后还要写一堆自己的逻辑啊,而且还要维护自己的资源文件,又要对相同的弹窗进行封装,又要熬夜加班了(小拳头越握越紧~~)


当前应用合规比较严格的条件下,相关条例规定在权限申请时要弹出权限使用说明,我们需要通知用户我们的app当前需要拿到手机的什么权限,获取什么数据,如何使用,那么在鸿蒙开发中我们如何实现图中描述的功能呢?



这个时候,我们的 CustomDialog 他来了


无惧复杂逻辑,横扫需求做回自己!!

鸿蒙自定义弹窗,一个组件通通搞定!!

爱就码上行动!!!


相对应的技术

安卓开发中我们知道弹窗可以使用Dialog去实现,但是你想要跟系统的弹窗一起实现的就会比较的复杂,程序员的头发往往就是被这些需求整掉的


今天,在鸿蒙中,仅需一个组件,用自定义弹窗,保住乌黑浓密好头发。并且创建和使用都比安卓更加高效和方便,真是有手就行



什么是自定义弹窗

CustomDialog是自定义弹窗,可用于广告、中奖、警告、软件更新等与用户交互响应操作。开发者可以通过CustomDialogController类显示自定义弹窗

1.如何创建自定义弹窗

使用@CustomDialog装饰器装饰自定义弹窗。

@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义内容

@CustomDialog
export  default  struct PermissionDialogWidget{
@State titleText:string='';
@State contentText:string='';
controller: CustomDialogController
build(){
Column(){
Text(this.titleText).margin({top:10})
Text(this.contentText).margin({top:20,bottom:10})
}.justifyContent(FlexAlign.Start).padding({left:20,right:20})
}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

如何声明用我们创建的自定义弹窗


permissionController:CustomDialogController=new CustomDialogController({
builder:PermissionDialogWidget({
titleText:"权限说明",
contentText: 'XXAPP想要申请位置权限,XXAPP地址选择。同意该权限后,选择地址时会复用此权限,不会重新申请,不授权上述权限,不影响APP其他功能使用。',
}),
//这里我们需要弹窗内容在顶部显示,所以要设置DialogAlignment为Top
alignment: DialogAlignment.Top,
})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
同时要在组件的生命周期将dialogController置空

aboutToDisappear() {
this.permissionController=undefined
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.


4.实现权限请求

在成功和失败时都要对弹窗进行关闭```

reqPermissionsFromUser(permissions: Array<Permissions>): void {
let context = getContext(this) as common.UIAbilityContext;
let atManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
this.permissionController.close()
} else {
this.permissionController.close()
return;
}
}
}).catch((err) => {
console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`);
})
}
```
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.


申请权限


我们以动态申请定位权限为例:

1.

官方介绍中可知

我们申请定位权限,需要申请ohos.permission.APPROXIMATELY_LOCATION或者同时申请ohos.permission.APPROXIMATELY_LOCATION和ohos.permission.LOCATION;无法单独申请ohos.permission.LOCATION。

所以我们需要在资源文件夹下的Module.json5中添加

ohos.permission.APPROXIMATELY_LOCATION

和ohos.permission.LOCATION

 #HarmonyOS NEXT体验官#如何使用自定义弹窗实现一个跟系统权限弹窗同步呼出的权限说明弹窗_自定义_02

在项目中的位置如上图


添加完成后如下图所示

 #HarmonyOS NEXT体验官#如何使用自定义弹窗实现一个跟系统权限弹窗同步呼出的权限说明弹窗_自定义_03


接下来我们需要在刚才声明弹窗的Page中,创建一个按钮,来对我们刚才声明的自定义弹窗进行测试,并且添加上我们对经纬度处理的代码


我们需要引入的依赖如下


import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';
import geoLocationManager from '@ohos.geoLocationManager';
import dialog from '../widget/dialog/PermissionDialogWidget';
let context = getContext(this) as common.UIAbilityContext;
const permissions: Array<Permissions> = ['ohos.permission.APPROXIMATELY_LOCATION','ohos.permission.LOCATION'];
同时我们还需要实现一个初始化成功后获取经纬度的方法
initLocation():void{
let requestInfo = {'priority': 0x203, 'scenario': 0x300,'maxAccuracy': 0};
try {
geoLocationManager.getCurrentLocation(requestInfo).then((result) => {
console.log('current location: ' + JSON.stringify(result));
let jsonData=JSON.stringify(result);
let data= JSON.parse(jsonData)
let longitude= data['longitude']
let latitude= data['latitude']
//这里获取经纬度
console.log('promise, getCurrentLocation: error='+longitude+latitude);

})
.catch((error) => {
console.log('promise, getCurrentLocation: error=' + JSON.stringify(error));
});
} catch (err) {
console.error("errCode:" + err.code + ",errMessage:" + err.message);
}
}

Text("开启定位")
.padding($r('app.float.size_5'))
.fontColor(Color.Black)
.fontSize($r('app.float.size_12'))
.borderRadius($r('app.float.size_4'))
.backgroundColor($r('app.color.app_color'))
.margin({right:$r('app.float.size_10')})
.onClick(()=>{
this.reqPermissionsFromUser(permissions)
})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.

当我们点击开启定位的组件实现的效果如下:

 #HarmonyOS NEXT体验官#如何使用自定义弹窗实现一个跟系统权限弹窗同步呼出的权限说明弹窗_JSON_04

当我们在真机上请求定位权限成功后,我们的自定义弹窗会通过我们定义好的this.permissionController.close()进行关闭,这样我们的需求就实现了


`