鸿蒙(HarmonyOS)实现隐私政策弹窗

在实现用户协议弹窗时,通常我们会想到使用系统自定义弹窗,并在弹窗中点击跳转到Web页面。但在HarmonyOS中,由于系统弹窗的显示优先级高于其他组件,即使跳转到Web页面,弹窗依然会显示在最上层。

为了解决这个问题,我们可以自定义一个组件来模拟弹窗,这样当跳转到Web页面时,Web内容会覆盖这个模拟的弹窗。

效果图如下:

首先,我们来看程序的入口代码。最外层使用了一个RelativeContainer容器组件,通过showAgreePrivacyPolicy变量控制隐私政策弹窗的显示状态。每次启动应用时,该变量默认设置为true,以显示隐私政策弹窗。在实际开发中,你可以通过preferences保存这个变量的状态。

struct Index {
@State showAgreePrivacyPolicy:boolean=true;
build() {
RelativeContainer(){
Row({space:10}){
Image($r('app.media.app_icon')).width(60).height(60)
Column({space:5}){
Text($r('app.string.app_name')).fontSize(22).fontColor($r('app.color.title_color'))
Text($r('app.string.launcher_tip')).fontSize(14).fontColor($r('app.color.other_color'))
}.alignItems(HorizontalAlign.Start)
}.alignRules({
bottom: {anchor: "__container__", align: VerticalAlign.Bottom},
middle: { anchor: '__container__', align: HorizontalAlign.Center } //以父容器为锚点,水平方向居中对齐
}).margin({
bottom:30
})
if(this.showAgreePrivacyPolicy){//通过变量控制隐私政策弹窗是否显示
PrivacyPolicyDialog({
cancel:this.onCancel.bind(this),//取消按钮点击
confirm:this.onAgree.bind(this),//确定按钮点击
})
}
}.width('100%')
.height('100%').backgroundColor($r('app.color.white'))
}
onCancel():void {
(getContext(this) as common.UIAbilityContext)?.terminateSelf()
}
onAgree():void {//同意隐私政策
this.showAgreePrivacyPolicy = false;
}
}
struct Index {
    @State showAgreePrivacyPolicy:boolean=true;

    build() {
        RelativeContainer(){
            Row({space:10}){
                Image($r('app.media.app_icon')).width(60).height(60)

                Column({space:5}){
                    Text($r('app.string.app_name')).fontSize(22).fontColor($r('app.color.title_color'))
                    Text($r('app.string.launcher_tip')).fontSize(14).fontColor($r('app.color.other_color'))
                }.alignItems(HorizontalAlign.Start)
            }.alignRules({
                bottom: {anchor: "__container__", align: VerticalAlign.Bottom},
                middle: { anchor: '__container__', align: HorizontalAlign.Center }  //以父容器为锚点,水平方向居中对齐
            }).margin({
                bottom:30
            })

            if(this.showAgreePrivacyPolicy){//通过变量控制隐私政策弹窗是否显示
                PrivacyPolicyDialog({
                    cancel:this.onCancel.bind(this),//取消按钮点击
                    confirm:this.onAgree.bind(this),//确定按钮点击
                })
            }
        }.width('100%')
        .height('100%').backgroundColor($r('app.color.white'))
    }

    onCancel():void {
        (getContext(this) as common.UIAbilityContext)?.terminateSelf()
    }

    onAgree():void {//同意隐私政策
        this.showAgreePrivacyPolicy = false;
    }
}
struct Index { @State showAgreePrivacyPolicy:boolean=true; build() { RelativeContainer(){ Row({space:10}){ Image($r('app.media.app_icon')).width(60).height(60) Column({space:5}){ Text($r('app.string.app_name')).fontSize(22).fontColor($r('app.color.title_color')) Text($r('app.string.launcher_tip')).fontSize(14).fontColor($r('app.color.other_color')) }.alignItems(HorizontalAlign.Start) }.alignRules({ bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, middle: { anchor: '__container__', align: HorizontalAlign.Center } //以父容器为锚点,水平方向居中对齐 }).margin({ bottom:30 }) if(this.showAgreePrivacyPolicy){//通过变量控制隐私政策弹窗是否显示 PrivacyPolicyDialog({ cancel:this.onCancel.bind(this),//取消按钮点击 confirm:this.onAgree.bind(this),//确定按钮点击 }) } }.width('100%') .height('100%').backgroundColor($r('app.color.white')) } onCancel():void { (getContext(this) as common.UIAbilityContext)?.terminateSelf() } onAgree():void {//同意隐私政策 this.showAgreePrivacyPolicy = false; } }

接下来是PrivacyPolicyDialog组件代码:

  • 根组件填充100%宽高,设置黑色背景,透明度30%
  • 内容区域使用Stack组件,背景为白色,圆角边框,宽度占父组件的80%。
  • 文字内容用Text和Span组件包裹,支持滚动功能。点击用户协议和隐私政策的文字时,使用router打开Web页面。
@Component
export default struct PrivacyPolicyDialog{
cancel!: () => void
confirm!: () => void
build() {
Stack(){
Column() {
Text($r('app.string.simple_user_policy')).fontSize(18).fontColor($r('app.color.title_color')).margin({ top: 30, bottom: 19 })
Scroll(){
Text(){
Span($r('app.string.privacy_policy_start'))
Span($r('app.string.user_agreement_two')).fontColor($r('app.color.mainColor')).onClick(() => {
this.openWebUrl("/useragreement.html");
})
Span($r('app.string.and'))
Span($r('app.string.privacy_policy_two')).fontColor($r('app.color.mainColor')).onClick(() => {
this.openWebUrl("/privacypolicy.html");
})
Span($r('app.string.simple_privacy_policy'))
}.fontSize(16).fontColor($r('app.color.body_color')).margin({
left:25,
right:25
})
}.height(120)
Column(){
Button($r('app.string.disagree_privacy_policy')).onClick(() => {
this.cancel();
}).fontColor($r('app.color.other_color')).fontSize(15).backgroundColor(Color.Transparent)
Button($r('app.string.agree_privacy_policy')).onClick(() => {
this.confirm();
}).fontColor($r('app.color.white')).fontSize(17)
.linearGradient({
direction: GradientDirection.Right, colors:[[$r('app.color.start_main_color'),0.0],[$r('app.color.end_main_color'),1.0]]
}).width('80%').margin({
top:15,bottom:21
}).borderRadius(24)
}
}.backgroundColor($r('app.color.white')).borderRadius(13).width('80%')
}.width('100%')
.height('100%').backgroundColor("#4D000000")//黑色背景 透明度约为 30%
}
openWebUrl(urlSuffix:string){
let url= "https://www.srzs.top"+urlSuffix;
router.pushUrl({
url: 'pages/WebViewPage',
params:{
data1: 'message',
url: url // 传递的 URL 参数
}
}, router.RouterMode.Single)
}
}
@Component
export default struct PrivacyPolicyDialog{
    cancel!: () => void
    confirm!: () => void

    build() {
        Stack(){
            Column() {
                Text($r('app.string.simple_user_policy')).fontSize(18).fontColor($r('app.color.title_color')).margin({ top: 30, bottom: 19 })

                Scroll(){
                    Text(){
                        Span($r('app.string.privacy_policy_start'))
                        Span($r('app.string.user_agreement_two')).fontColor($r('app.color.mainColor')).onClick(() => {
                            this.openWebUrl("/useragreement.html");
                        })
                        Span($r('app.string.and'))
                        Span($r('app.string.privacy_policy_two')).fontColor($r('app.color.mainColor')).onClick(() => {
                            this.openWebUrl("/privacypolicy.html");
                        })
                        Span($r('app.string.simple_privacy_policy'))
                    }.fontSize(16).fontColor($r('app.color.body_color')).margin({
                        left:25,
                        right:25
                    })
                }.height(120)

                Column(){
                    Button($r('app.string.disagree_privacy_policy')).onClick(() => {
                        this.cancel();
                    }).fontColor($r('app.color.other_color')).fontSize(15).backgroundColor(Color.Transparent)

                    Button($r('app.string.agree_privacy_policy')).onClick(() => {
                        this.confirm();
                    }).fontColor($r('app.color.white')).fontSize(17)
                        .linearGradient({
                            direction: GradientDirection.Right, colors:[[$r('app.color.start_main_color'),0.0],[$r('app.color.end_main_color'),1.0]]
                        }).width('80%').margin({
                        top:15,bottom:21
                    }).borderRadius(24)
                }
            }.backgroundColor($r('app.color.white')).borderRadius(13).width('80%')
        }.width('100%')
        .height('100%').backgroundColor("#4D000000")//黑色背景 透明度约为 30%
    }

    openWebUrl(urlSuffix:string){
        let url= "https://www.srzs.top"+urlSuffix;
        router.pushUrl({
            url: 'pages/WebViewPage',
            params:{
                data1: 'message',
                url: url  // 传递的 URL 参数
            }
        }, router.RouterMode.Single)
    }
}
@Component export default struct PrivacyPolicyDialog{ cancel!: () => void confirm!: () => void build() { Stack(){ Column() { Text($r('app.string.simple_user_policy')).fontSize(18).fontColor($r('app.color.title_color')).margin({ top: 30, bottom: 19 }) Scroll(){ Text(){ Span($r('app.string.privacy_policy_start')) Span($r('app.string.user_agreement_two')).fontColor($r('app.color.mainColor')).onClick(() => { this.openWebUrl("/useragreement.html"); }) Span($r('app.string.and')) Span($r('app.string.privacy_policy_two')).fontColor($r('app.color.mainColor')).onClick(() => { this.openWebUrl("/privacypolicy.html"); }) Span($r('app.string.simple_privacy_policy')) }.fontSize(16).fontColor($r('app.color.body_color')).margin({ left:25, right:25 }) }.height(120) Column(){ Button($r('app.string.disagree_privacy_policy')).onClick(() => { this.cancel(); }).fontColor($r('app.color.other_color')).fontSize(15).backgroundColor(Color.Transparent) Button($r('app.string.agree_privacy_policy')).onClick(() => { this.confirm(); }).fontColor($r('app.color.white')).fontSize(17) .linearGradient({ direction: GradientDirection.Right, colors:[[$r('app.color.start_main_color'),0.0],[$r('app.color.end_main_color'),1.0]] }).width('80%').margin({ top:15,bottom:21 }).borderRadius(24) } }.backgroundColor($r('app.color.white')).borderRadius(13).width('80%') }.width('100%') .height('100%').backgroundColor("#4D000000")//黑色背景 透明度约为 30% } openWebUrl(urlSuffix:string){ let url= "https://www.srzs.top"+urlSuffix; router.pushUrl({ url: 'pages/WebViewPage', params:{ data1: 'message', url: url // 传递的 URL 参数 } }, router.RouterMode.Single) } }

WebViewPage展示Web网页的代码就不贴出来了,大家可直接下载源码。还有加载网页一定要网络权限,在entry/module.json5这个文件中配置。

源码下载

https://github.com/ansen666/PrivacyPolicy

如果您想第一时间看我的后期文章,扫码关注公众号

安辉编程笔记 - 开发技术分享
扫描二维码加关注
      安辉编程笔记 - 开发技术分享
             扫描二维码加关注
安辉编程笔记 - 开发技术分享 扫描二维码加关注

© 版权声明
THE END
支持一下吧
点赞6 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容