一、分析欢迎页面业务逻辑
1.思路分析
欢迎页面业务逻辑:判断用户是否同意用户隐私协议,同意与否的状态通过使用用户持久化将其保存。也就是,当我们打开某个软件时,通常会弹出一个窗口询问你是否同意某个用户隐私协议,若同意我们直接就进入软件并记住你的选项,下次不会再弹出窗口对你进行询问;若不同意直接退出软件。
看完我这段清晰描述后还是看不懂的同学建议重开哦(bushi)
逻辑图如下:
2.关键技术
那么我们分析完这个过程后,我们需要了解一下实现这个过程所需要的技术。
(1)用户首选项
(2)自定义弹窗
与自定义组件语法及其相似
①使用@CustomDialog装饰器声明弹窗组件
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
build(){
Column(){
Text('弹窗内中的内容')
.fontSize(20)
}
}
}
②在页面中声明弹窗控制器,并利用其控制弹窗
@Entry
@Component
struct IndexPage {
dialogController: CustomDialogController = new CustomDialogController({//弹窗控制器
builder:CustomDialogExample({/*此处可以传入弹窗需要的参数*/}),//使用自定义弹窗
])
build() {
Column(){
Button('打开')
.onClick(()=> {
this.dialogController.open()//利用弹窗控制器进行开关
})
}
}
}
二、正式开发
当我们了解过所需的技术后就可以进行实际的开发了
由于我们本次的任务是制作一个自定义弹窗,为了方便大家在制作过程中去预览查看自己自定义弹窗的效果,我们可以添加一个@Preview,这样我们就可以正常的在预览器中去看到我们自定义弹窗的内容了。
1.将文件创建在合适的位置下
由于一些中小型的项目开发过程中仍然需要大量的不同类型的文件,这里建议创建不同的文件夹将这些文件归类,这里建议ets文件如下图分类:
我们新建一个名为UserPrivacyDialog的ets文件保存到view下
2.按照所需书写代码
如果同学你看过我上一篇文章的话应该明白这些文本引用的这些乱七八糟的东西是什么,也就是$r后面引用的内容是黑马为了方便我们实际开发过程所提前准备好的文字颜色和文本内容之类的,如果你没有看过我的上一篇文章那么现在就回去看吧,不然你不明白我在讲什么。。。
@CustomDialog
export default struct UserPrivacyDialog {
controller: CustomDialogController//声明类型
confirm: () => void//同意逻辑
cancel: () => void//不同意逻辑
build() {
Column({space: CommonConstants.SPACE_10}){
// 1.标题
Text($r('app.string.user_privacy_title'))//引用字符串
.fontSize(20)
.fontWeight(CommonConstants.FONT_WEIGHT_700)
// 2.内容
Text($r('app.string.user_privacy_content'))
// 3.按钮
Button($r('app.string.agree_label'))
.width(150)
.backgroundColor($r('app.color.primary_color'))
.onClick(() => {
this.confirm()
this.controller.close()
})
Button($r('app.string.refuse_label'))
.width(150)
.backgroundColor($r('app.color.lightest_primary_color'))
.fontColor($r('app.color.light_gray'))
.onClick(() => {
this.cancel()
this.controller.close()
})
}
.width('100%')
.padding(10)
}
}
3.在欢迎页面中使用对话框
(1)声明对话框
在欢迎页面中声明对话框:
controller: CustomDialogController = new CustomDialogController({
builder: UserPrivacyDialog({//传入的参数
confirm: () => this.onConfirm(),
cancel: () => this.exitApp()
})
})
(2)设置对话框出现的时机
我们需要在页面一加载的时候就弹出对话框,由于我们想要数据持久化也就是记录用户已经同意用户隐私协议的这个状态,前面的文章就已经提到黑马已经为我们准备好了一个工具类,其中,用户首选项的各种操作已经为我们写好
首选项代码如下:
import preferences from '@ohos.data.preferences';
import { CommonConstants } from '../constants/CommonConstants';
import Logger from './Logger';
class PreferenceUtil{
private pref: preferences.Preferences
async loadPreference(context){
try { // 加载preferences
this.pref = await preferences.getPreferences(context, CommonConstants.H_STORE)
Logger.debug(`加载Preferences[${CommonConstants.H_STORE}]成功`)
} catch (e) {
Logger.debug(`加载Preferences[${CommonConstants.H_STORE}]失败`, JSON.stringify(e))
}
}
async putPreferenceValue(key: string, value: preferences.ValueType){
if (!this.pref) {
Logger.debug(`Preferences[${CommonConstants.H_STORE}]尚未初始化!`)
return
}
try {
// 写入数据
await this.pref.put(key, value)
// 刷盘
await this.pref.flush()
Logger.debug(`保存Preferences[${key} = ${value}]成功`)
} catch (e) {
Logger.debug(`保存Preferences[${key} = ${value}]失败`, JSON.stringify(e))
}
}
async getPreferenceValue(key: string, defaultValue: preferences.ValueType){
if (!this.pref) {
Logger.debug(`Preferences[${CommonConstants.H_STORE}]尚未初始化!`)
return
}
try {
// 读数据
let value = await this.pref.get(key, defaultValue)
Logger.debug(`读取Preferences[${key} = ${value}]成功`)
return value
} catch (e) {
Logger.debug(`读取Preferences[${key}]失败`, JSON.stringify(e))
}
}
}
const preferenceUtil = new PreferenceUtil()
export default preferenceUtil as PreferenceUtil
我们需要在应用启动时加载loadPreference函数,这个步骤在EntryAbility中的onCreate生命周期钩子中做
onCreate(want, launchParam) {
加载用户首选项
PreferenceUtil.loadPreference(this.context)
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
由于我们在将弹窗展示后需要等待用户进行选择,所以在生命周期函数中,通过异步处理判断是否同意
async aboutToAppear(){//异步函数,它可以在执行过程中暂停,并在稍后的时间点继续执行。async 函数的返回值是一个 Promise 对象,用于表示异步操作的结果。
// 1.加载首选项
let isAgree = await PreferenceUtil.getPreferenceValue(PREF_KEY, false)//默认为不弹窗,await异步读取
// 2.判断是否同意
if(isAgree){
// 2.1.同意,跳转首页
this.jumpToIndex()
}else{
// 2.2.不同意,弹窗
this.controller.open()
}
}
这里我们单独写了一个跳转页面方便调用:
jumpToIndex(){//跳转到首页
setTimeout(() => {
router.replaceUrl({//直接压栈破坏
url: 'pages/Index'
})
}, 1000)//延迟跳转,缓冲数据加载及让用户看会首页
}
这里的PREF_KEY是一个参数用来保存是否同意
const PREF_KEY = 'userPrivacyKey'
(3)点击同意按钮后的逻辑
onConfirm(){
// 1.保存首选项
PreferenceUtil.putPreferenceValue(PREF_KEY, true)
// 2.跳转到首页
this.jumpToIndex()
}
(4)点击不同意按钮后的逻辑
当用户点击不同意时无论啥情况我们都需要关闭软件,这里的关闭我们使用了一个叫context的API,它使用getContext去获取,类型为common下的UIAbilityContext。
添加之后的声明与关闭软件如下:
context = getContext(this) as common.UIAbilityContext//上下文
controller: CustomDialogController = new CustomDialogController({
builder: UserPrivacyDialog({//传入的参数
confirm: () => this.onConfirm(),
cancel: () => this.exitApp()
})
})
exitApp(){
// 退出APP
this.context.terminateSelf()
}
(5)在EntryAbility中的windowStage.loadContent去修改默认加载页面
EntryAbility的默认加载页面为index,因为我们现在只关心欢迎页面并不需要它展示首页,所以我们把这个默认加载页面修改为欢迎页面,好让模拟器先加载欢迎页面。
windowStage.loadContent('pages/WelcomePage', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
});
三、测试逻辑功能
经过我们的一番操作之后呢,我们打开鸿蒙模拟器并运行一下。
经过我们的测试呢,目前制作好的页面逻辑完全符合预期。
OK,我们下篇文章接着讲,我们这里附上黑马程序员欢迎页面业务的视频链接,文章配合视频更好理解哦。