目录
2. 自定义弹窗组件UserPrivacyDialog.ets
3. EntryAbility.ets用户首选项配置同时修改默认进入页面Index改为WelcomePage
一、 启动页效果展示
二、 功能概述
1. 欢迎页设计
(1)展示“#用黑马 减更多#”的图片,并突出显示在首页中央,引起用户注意。
(2)展示logo图片,提高品牌识别度。
(3)加入文字描述,包括使用边框包裹的IPV6文字效果和透明度渐变效果,吸引用户阅读并了解更多信息。
2.用户同意设计
(1)使用自定义弹窗展示用户使用服务协议,提供同意和不同意选项按钮。如果用户之前选择了同意(isAgree为true),则直接跳转到主页面。如果用户之前选择了不同意或是首次进入应用,弹出弹窗等待用户选择。
(2)当用户点击同意按钮时,保存用户首选项,并跳转到主页面。当用户点击不同意按钮时,退出应用。
(3)使用用户首选项来判断用户进入界面时是否需要弹出同意黑马服务协议弹窗。
三、 组件实现
1. 欢迎页设计
首页以浅绿色为背景色,使用Column有序放置中央图片、logo图片、文字描述。
(1) 在此背景上加载了“#用黑马 减更多#”的图片,并使用.layoutWeight(1)使它占据其他组件之外的所有空间,形成展示效果中占据中央突出视觉的效果。
(2) 加载logo图片,设置合适大小,使其美观。
(3) 加入文字描述,其中第一条文字描述带有IPV6被边框包裹的效果,这条文字描述整体放在Row容器中达成一体效果。同时逐条文字调整透明度达成渐变效果。
详细代码展示:
//字体统一样式
@Extend(Text) function opacityWhiteText(opacity: number, fontSize: number = 10) {
.fontSize(fontSize)
.opacity(opacity)
.fontColor(Color.White)
}
@Entry
@Component
struct WelcomePage {
build() {
Column({ space: 10 }) {
// 1.中央Slogan
Row() {
Image($r('app.media.home_slogan')).width(260)
}
.layoutWeight(1)//权重为1让它占据剩下的所有空间。
// 2.logo
Image($r('app.media.home_logo')).width(150)
// 3.文字描述
Row() {
Text('黑马健康支持').opacityWhiteText(0.8, 12)
Text('IPv6')
.opacityWhiteText(0.8)
//IPV6的边框
.border({ style: BorderStyle.Solid, width: 1, color: Color.White, radius: 15 })
//左右内边距
.padding({ left: 5, right: 5 })
Text('网络').opacityWhiteText(0.8, 12)
}
Text(`'减更多'指黑马健康App希望通过软件工具的形式,帮助更多用户实现身材管理`)
//透明度
.opacityWhiteText(0.6)
Text('浙ICP备0000000号-36D')
.opacityWhiteText(0.4)
.margin({ bottom: 35 })//不让最下面的字体垫底
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.welcome_page_background'))
}
}
}
2.用户同意设计
在WelcomePage结构体中,通过调用自定义弹窗控制器CustomDialogController和构建器UserPrivacyDialog来实现弹窗功能,展示了用户使用服务协议,提供同意onConfirm()或不同意cancel() 选项按钮.
同意则跳转主页面this.jumpToIndex(),不同意则退出应用this.exitApp()下次进入时再重新弹窗,同时使用了用户首选项在aboutToAppear()方法中,加载用户首选项并根据其值判断是否需要弹出弹窗,在build主函数前面执行,弹出弹窗。
若数据isAgree 是true即用户之前选择了同意,则以后可以直接进入页面,否则为不同意,重新弹窗。
@Entry
@Component
struct WelcomePage {
//上下文
context = getContext(this) as common.UIAbilityContext
//调用自定义弹窗
controller: CustomDialogController = new CustomDialogController({//弹窗控制器
builder: UserPrivacyDialog({//使用自定义弹窗
confirm: () => this.onConfirm(),
cancel: () => this.exitApp()
})
})
//用户首选项,在build前面
async aboutToAppear(){
// 1.加载首选项
let isAgree = await PreferenceUtil.getPreferenceValue(PREF_KEY, false)
// 2.判断是否同意
if(isAgree){
// 2.1.同意,跳转首页
this.jumpToIndex()
}else{
// 2.2.不同意,弹窗
this.controller.open()
}
}
jumpToIndex(){
setTimeout(() => {//首页停留延时
router.replaceUrl({//欢迎页面不适用压栈,使用replace覆盖即可
url: 'pages/Index'
})
}, 2000)//延时2000ms
}
onConfirm(){
// 1.保存首选项
PreferenceUtil.putPreferenceValue(PREF_KEY, true)
// 2.跳转到首页
this.jumpToIndex()
}
exitApp(){
// 退出APP
this.context.terminateSelf()//终结
}
}
四、 完整代码展示
1. 欢迎界面WelcomePage.ets
import common from '@ohos.app.ability.common'
import router from '@ohos.router'
import PreferenceUtil from '../common/utils/PreferenceUtil'
import UserPrivacyDialog from '../view/welcome/UserPrivacyDialog'
//字体统一样式
@Extend(Text) function opacityWhiteText(opacity: number, fontSize: number = 10) {
.fontSize(fontSize)
.opacity(opacity)
.fontColor(Color.White)
}
const PREF_KEY = 'userPrivacyKey'
@Entry
@Component
struct WelcomePage {
//上下文
context = getContext(this) as common.UIAbilityContext
//调用自定义弹窗
controller: CustomDialogController = new CustomDialogController({//弹窗控制器
builder: UserPrivacyDialog({//使用自定义弹窗
confirm: () => this.onConfirm(),
cancel: () => this.exitApp()
})
})
//用户首选项,在build前面
async aboutToAppear(){
// 1.加载首选项
let isAgree = await PreferenceUtil.getPreferenceValue(PREF_KEY, false)
// 2.判断是否同意
if(isAgree){
// 2.1.同意,跳转首页
this.jumpToIndex()
}else{
// 2.2.不同意,弹窗
this.controller.open()
}
}
jumpToIndex(){
setTimeout(() => {//首页停留延时
router.replaceUrl({//欢迎页面不适用压栈,使用replace覆盖即可
url: 'pages/Index'
})
}, 2000)//延时2000ms
}
onConfirm(){
// 1.保存首选项
PreferenceUtil.putPreferenceValue(PREF_KEY, true)
// 2.跳转到首页
this.jumpToIndex()
}
exitApp(){
// 退出APP
this.context.terminateSelf()//终结
}
build() {
Column({ space: 10 }) {
// 1.中央Slogan
Row() {
Image($r('app.media.home_slogan')).width(260)
}
.layoutWeight(1)//权重为1让它占据剩下的所有空间。
// 2.logo
Image($r('app.media.home_logo')).width(150)
// 3.文字描述
Row() {
Text('黑马健康支持').opacityWhiteText(0.8, 12)
Text('IPv6')
.opacityWhiteText(0.8)
//IPV6的边框
.border({ style: BorderStyle.Solid, width: 1, color: Color.White, radius: 15 })
//左右内边距
.padding({ left: 5, right: 5 })
Text('网络').opacityWhiteText(0.8, 12)
}
Text(`'减更多'指黑马健康App希望通过软件工具的形式,帮助更多用户实现身材管理`)
//透明度
.opacityWhiteText(0.6)
Text('浙ICP备0000000号-36D')
.opacityWhiteText(0.4)
.margin({ bottom: 35 })//不让最下面的字体垫底
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.welcome_page_background'))
}
}
2. 自定义弹窗组件UserPrivacyDialog.ets
import { CommonConstants } from '../../common/constants/CommonConstants'
//@Preview//加上可预览
@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. EntryAbility.ets用户首选项配置同时修改默认进入页面Index改为WelcomePage
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import { CommonConstants } from '../common/constants/CommonConstants';
import DateUtil from '../common/utils/DateUtil';
import DbUtil from '../common/utils/DbUtil';
import PreferenceUtil from '../common/utils/PreferenceUtil';
import RecordModel from '../model/RecordModel';
export default class EntryAbility extends UIAbility {
async onCreate(want, launchParam) {
// 1.加载用户首选项
PreferenceUtil.loadPreference(this.context)
// 2.初始化日期
AppStorage.SetOrCreate(CommonConstants.RECORD_DATE, DateUtil.beginTimeOfDay(new Date()))
// 3.初始化RDB工具
await DbUtil.initDB(this.context)
// 4.创建record表
DbUtil.createTable(RecordModel.getCreateTableSql())
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
//默认进入页面改为WelcomePage
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) ?? '');
});
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground() {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}
五、 问题记录与收获
1.关于自定义弹窗
对于自定义的弹窗的控制器一开始不是很明白,通过学习与使用后逐渐理解了,如果你要使用一个自定义弹窗,需要先自己设计你的弹窗组件或者使用默认的,使用@CustomDialog装饰器声明,然后在你的页面里去调用它,实例化弹窗控制器,然后用builder 使用你的自定义弹窗,我的启动页里面这里调用的是我的自定义弹窗UserPrivacyDialog.
2.默认进入页面改为WelcomePage
这里也是之前模拟器进入后的空白问题的部分原因,需要修改Index。
3.页面停留延时setTimeOut
这个方法用在用户同意弹窗以后的跳转页面方法里,作用是停留设定时间ms,我的代码里为了让效果显示的更明显,改成了延时3s去展示一下欢迎页。
4. 预览设置
在设计自定义弹窗内容时,使用@Preview装饰器可以实现预览弹窗的效果。