介紹
本篇Codelab基于自定義彈框、首選項(xiàng)和頁面路由實(shí)現(xiàn)一個(gè)模擬應(yīng)用首次啟動的案例。需要完成以下功能:
- 實(shí)現(xiàn)四個(gè)頁面,啟動頁、隱私協(xié)議頁、廣告頁、應(yīng)用首頁。
- 頁面之間的跳轉(zhuǎn)。
- 實(shí)現(xiàn)自定義隱私協(xié)議彈窗,點(diǎn)擊協(xié)議可查看隱私協(xié)議具體內(nèi)容。
- 隱私協(xié)議狀態(tài)持久化存儲,再次啟動時(shí),如果沒有保存狀態(tài)會再次彈出,否則不彈出。
效果如圖所示:

相關(guān)概念
- [首選項(xiàng)] :首選項(xiàng)為應(yīng)用提供Key-Value鍵值型的數(shù)據(jù)處理能力,支持應(yīng)用持久化輕量級數(shù)據(jù),并對其修改和查詢。數(shù)據(jù)存儲形式為鍵值對,鍵的類型為字符串型,值的存儲數(shù)據(jù)類型包括數(shù)字型、字符型、布爾型以及這3種類型的數(shù)組類型。
- [自定義彈窗]: 通過CustomDialogController類顯示自定義彈窗。
- [頁面路由]:提供通過不同的url訪問不同的頁面,包括跳轉(zhuǎn)到應(yīng)用內(nèi)的指定頁面、用應(yīng)用內(nèi)的某個(gè)頁面替換當(dāng)前頁面、返回上一頁面或指定的頁面等。
環(huán)境搭建
軟件要求
- [DevEco Studio] 版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 開發(fā)板類型:[潤和RK3568開發(fā)板]。
- OpenHarmony系統(tǒng):3.2 Release。
環(huán)境搭建
完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進(jìn)行:
- [獲取OpenHarmony系統(tǒng)版本] :標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:

- 搭建燒錄環(huán)境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開發(fā)板的燒錄]
- 鴻蒙開發(fā)指導(dǎo)文檔:[
qr23.cn/AKFP8k]
- 搭建開發(fā)環(huán)境。
- 開始前請參考[工具準(zhǔn)備] ,完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
- 開發(fā)環(huán)境配置完成后,創(chuàng)建工程(模板選擇“Empty Ability”)。
- 工程創(chuàng)建完成后,選擇使用[真機(jī)進(jìn)行調(diào)測] 。

代碼結(jié)構(gòu)解讀
本篇Codelab只對核心代碼進(jìn)行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區(qū)
│ ├──common
│ │ ├──constants
│ │ │ └──CommonConstants.ets // 常量類
│ │ └──utils
│ │ ├──GlobalContext.ets // 項(xiàng)目工具類
│ │ └──Logger.ets // 日志打印工具類
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口類
│ ├──pages
│ │ ├──AdvertisingPage.ets // 廣告頁
│ │ ├──AppHomePage.ets // 應(yīng)用首頁
│ │ ├──LauncherPage.ets // 應(yīng)用啟動頁
│ │ └──PrivacyPage.ets // 隱私協(xié)議頁
│ └──view
│ └──CustomDialogComponent.ets // 自定義彈窗組件
└──entry/src/main/resources // 資源文件目錄
應(yīng)用啟動頁實(shí)現(xiàn)
打開應(yīng)用時(shí)進(jìn)入EntryAbility頁面,通過windowStage.loadContent方法加載啟動頁LauncherPage,然后在LauncherPage的build里面構(gòu)建啟動頁組件,效果如圖所示:

// LauncherPage.ets
// 啟動頁組件
build() {
Stack() {
// 背景圖
Image($r('app.media.ic_launcher_background'))
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
Column() {
// 啟動頁logo
Image($r('app.media.ic_logo'))
.width($r('app.float.launcher_logo_size'))
.height($r('app.float.launcher_logo_size'))
.margin({ top: CommonConstants.LAUNCHER_IMAGE_MARGIN_TOP })
// 健康生活文字
Text($r('app.string.healthy_life_text'))
.width($r('app.float.launcher_life_text_width'))
.height($r('app.float.launcher_life_text_height'))
.healthyLifeTextStyle(FontWeight.Bold,
CommonConstants.LAUNCHER_LIFE_TEXT_SPACING,
$r('app.float.launcher_text_title_size'),
$r('app.color.launcher_text_title_color'))
.margin({ top: CommonConstants.LAUNCHER_TEXT_TITLE_MARGIN_TOP })
// 健康生活說明
Text($r('app.string.healthy_life_introduce'))
.height(CommonConstants.LAUNCHER_TEXT_INTRODUCE_HEIGHT)
.healthyLifeTextStyle(FontWeight.Normal,
CommonConstants.LAUNCHER_TEXT_INTRODUCE_SPACING,
$r('app.float.launcher_text_introduce_size'),
$r('app.color.launcher_text_introduce_color'))
.opacity($r('app.float.launcher_text_opacity'))
.margin({ top: CommonConstants.LAUNCHER_TEXT_INTRODUCE_MARGIN_TOP })
}
.height(CommonConstants.FULL_HEIGHT)
.width(CommonConstants.FULL_WIDTH)
}
}
// 健康生活字體公共樣式
@Extend(Text) function healthyLifeTextStyle (fontWeight: number, textAttribute: number, fontSize: Resource, fontColor: Resource) {
.fontWeight(fontWeight)
.letterSpacing(textAttribute)
.fontSize(fontSize)
.fontColor(fontColor)
}
隱私彈窗實(shí)現(xiàn)
啟動頁的隱私協(xié)議內(nèi)容需要用到自定義彈窗,效果如圖所示:

// CustomDialogComponent.ets
// 自定義彈窗
@CustomDialog
export default struct CustomDialogComponent {
controller: CustomDialogController = new CustomDialogController({'builder': ''});
// 不同意按鈕回調(diào)
cancel: Function = () = > {}
// 同意按鈕回調(diào)
confirm: Function = () = > {}
build() {
Column() {
// 彈窗標(biāo)題
Text($r('app.string.dialog_text_title'))
.width(CommonConstants.DIALOG_COMPONENT_WIDTH_PERCENT)
.fontColor($r('app.color.dialog_text_color'))
.fontSize($r('app.float.dialog_text_privacy_size'))
.textAlign(TextAlign.Center)
.margin({
top: $r('app.float.dialog_text_privacy_top'),
bottom: $r('app.float.dialog_text_privacy_bottom')
})
// 彈窗內(nèi)容
Text($r('app.string.dialog_text_privacy_content'))
.fontSize($r('app.float.dialog_common_text_size'))
.width(CommonConstants.DIALOG_COMPONENT_WIDTH_PERCENT)
// 協(xié)議鏈接
Text($r('app.string.dialog_text_privacy_statement'))
.width(CommonConstants.DIALOG_COMPONENT_WIDTH_PERCENT)
.fontColor($r('app.color.dialog_text_statement_color'))
.fontSize($r('app.float.dialog_common_text_size'))
.onClick(() = > {
router.pushUrl({
url: CommonConstants.PRIVACY_PAGE_URL
}).catch((error: Error) = > {
Logger.error(CommonConstants.CUSTOM_DIALOG_TAG, 'CustomDialog pushUrl error ' + JSON.stringify(error));
});
})
// 協(xié)議聲明
Text($r('app.string.dialog_text_declaration_prompt'))
.width(CommonConstants.DIALOG_COMPONENT_WIDTH_PERCENT)
.fontColor($r('app.color.dialog_text_color'))
.fontSize($r('app.float.dialog_common_text_size'))
.opacity($r('app.float.dialog_text_opacity'))
.margin({ bottom: $r('app.float.dialog_text_declaration_bottom') })
// 按鈕組件
Row() {
// 取消按鈕
Text($r('app.string.dialog_button_disagree'))
.fancy()
.onClick(() = > {
this.controller.close();
this.cancel();
})
Blank()
.backgroundColor($r('app.color.dialog_blank_background_color'))
.width($r('app.float.dialog_blank_width'))
.height($r('app.float.dialog_blank_height'))
// 同意按鈕
Text($r('app.string.dialog_button_agree'))
.fancy()
.onClick(() = > {
this.controller.close();
this.confirm();
})
}
.margin({ bottom: CommonConstants.DIALOG_ROW_MARGIN_BOTTOM })
}
.width(CommonConstants.DIALOG_WIDTH_PERCENT)
.borderRadius(CommonConstants.DIALOG_BORDER_RADIUS)
.backgroundColor(Color.White)
}
}
// 按鈕公共樣式抽取
@Extend(Text) function fancy () {
.fontColor($r('app.color.dialog_fancy_text_color'))
.fontSize($r('app.float.dialog_fancy_text_size'))
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Medium)
.layoutWeight(CommonConstants.COMMON_LAYOUT_WEIGHT)
}
獲取隱私協(xié)議狀態(tài)
構(gòu)建啟動頁之前,在LauncherPage的生命周期onPageShow方法處,添加一個(gè)命名為“myStore”的首選項(xiàng)表,并在“myStore”首選項(xiàng)表讀取一個(gè)名為“isPrivacy”的字段,獲取隱私協(xié)議狀態(tài)。
// LauncherPage.ets
onPageShow() {
...
// 獲取保存數(shù)據(jù)操作類
this.getDataPreferences(this).then((preferences: preferences.Preferences) = > {
preferences.get(CommonConstants.PREFERENCES_KEY_PRIVACY, true).then((value: preferences.ValueType) = > {
Logger.info(CommonConstants.LAUNCHER_PAGE_TAG, 'onPageShow value: ' + value);
if (value) {
// let isJumpPrivacy: boolean = globalThis.isJumpPrivacy ?? false;
let isJumpPrivacy: boolean = (GlobalContext.getContext().getObject('isJumpPrivacy') as boolean) ?? false;
if (!isJumpPrivacy) {
// 自定義協(xié)議彈窗
this.dialogController.open();
}
} else {
// 跳至廣告頁
this.jumpToAdvertisingPage();
}
});
});
}
// 獲取數(shù)據(jù)首選項(xiàng)操作
getDataPreferences(common: Object) : Promise< preferences.Preferences >{
return preferences.getPreferences(getContext(common), CommonConstants.PREFERENCES_FILE_NAME);
}
保存隱私協(xié)議狀態(tài)
當(dāng)用戶點(diǎn)擊隱私協(xié)議彈窗同意按鈕時(shí),回調(diào)onConfirm方法,調(diào)用saveIsPrivacy保存隱私協(xié)議狀態(tài)。
// LauncherPage.ets
onConfirm(): void {
// 保存隱私協(xié)議狀態(tài)
this.saveIsPrivacy();
...
}
saveIsPrivacy(): void {
let preferences: Promise< preferences.Preferences > = this.getDataPreferences(this);
preferences.then((result: preferences.Preferences) = > {
let privacyPut = result.put(CommonConstants.PREFERENCES_KEY_PRIVACY, false);
result.flush();
...
});
}
頁面跳轉(zhuǎn)
用戶在啟動頁LauncherPage,點(diǎn)擊隱私協(xié)議彈窗同意按鈕onConfirm,在onConfirm方法內(nèi)開啟3秒倒計(jì)時(shí),倒計(jì)時(shí)結(jié)束后跳到廣告頁,當(dāng)啟動頁不可見時(shí),清除定時(shí)器和啟動頁,效果如圖所示:

// LauncherPage.ets
private isJumpToAdvertising: boolean = false;
onConfirm() :void{
...
// 跳轉(zhuǎn)到廣告頁
this.jumpToAdvertisingPage();
}
jumpToAdvertisingPage() :void{
this.timerId = setTimeout(() = > {
// 設(shè)置跳轉(zhuǎn)標(biāo)識
this.isJumpToAdvertising = true;
router.pushUrl({
url: CommonConstants.ADVERTISING_PAGE_URL
}).catch((error: Error) = > {
Logger.error(CommonConstants.LAUNCHER_PAGE_TAG, 'LauncherPage pushUrl error ' + JSON.stringify(error));
});
}, CommonConstants.LAUNCHER_DELAY_TIME);
}
onPageHide(): void {
if (this.isJumpToAdvertising) {
// 清除頁面
router.clear();
}
GlobalContext.getContext().setObject('isJumpPrivacy', true);
// 清除定時(shí)器
clearTimeout(this.timerId);
}
打開廣告頁AdvertisingPage后,進(jìn)行2秒倒計(jì)時(shí)(用戶可手動點(diǎn)擊跳過),倒計(jì)時(shí)結(jié)束跳轉(zhuǎn)到首頁AppHomePage,當(dāng)廣告頁不可見時(shí),清除定時(shí)器和廣告頁,效果如圖所示:

// AdvertisingPage.ets
@State countDownSeconds: number = CommonConstants.ADVERTISING_COUNT_DOWN_SECONDS;
private timeId: number = 0;
onPageShow() {
// 開啟2秒倒計(jì)時(shí)
this.timeId = setInterval(() = > {
if (this.countDownSeconds == 0) {
// 跳轉(zhuǎn)到首頁
this.jumpToAppHomePage();
} else {
this.countDownSeconds--;
}
}, CommonConstants.ADVERTISING_INTERVAL_TIME);
}
onPageHide() {
// 清除頁面
router.clear();
// 清除定時(shí)器
clearInterval(this.timeId);
}
build() {
Stack({ alignContent: Alignment.Top }) {
Image($r('app.media.ic_advertising_background'))
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
Text($r('app.string.advertising_text_title', this.countDownSeconds))
...
.onClick(() = > {
this.jumpToAppHomePage();
})
...
}
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
}
jumpToAppHomePage(): void {
router.pushUrl({
url: CommonConstants.APP_HOME_PAGE_URL
}).catch((error) = > {
Logger.error(CommonConstants.ADVERTISING_PAGE_TAG, 'AdvertisingPage pushUrl error ' + JSON.stringify(error));
});
}
審核編輯 黃宇
-
存儲
+關(guān)注
關(guān)注
13文章
4889瀏覽量
90284 -
鴻蒙
+關(guān)注
關(guān)注
60文章
3018瀏覽量
46175 -
HarmonyOS
+關(guān)注
關(guān)注
80文章
2157瀏覽量
36294
發(fā)布評論請先 登錄
3562-物聯(lián)網(wǎng)模塊開發(fā)案例
HarmonyOS開發(fā)案例:【購物車app】
HarmonyOS IoT 硬件開發(fā)案例分享
【HarmonyOS】開發(fā)跨設(shè)備的鴻蒙(HarmonyOS) App
【HarmonyOS】開發(fā)跨設(shè)備的鴻蒙(HarmonyOS)App
如何優(yōu)雅地開發(fā)HarmonyOS APP應(yīng)用
【潤和直播課預(yù)告@華為開發(fā)者學(xué)院】HarmonyOS設(shè)備開發(fā)基礎(chǔ)課程|HiSpark WiFi-IoT 智能小車套件開發(fā)案例
harmonyOS開發(fā)的APP如何訪問Webservice?
HarmonyOS APP打包運(yùn)行和調(diào)試應(yīng)用開發(fā)步驟
App開發(fā)案例教程PDF電子書免費(fèi)下載
許思維老師HarmonyOS IoT硬件開發(fā)案例分享
華為開發(fā)者分論壇HarmonyOS學(xué)生公開課-OpenHarmony Codelabs開發(fā)案例
淘寶與華為合作將基于HarmonyOS NEXT啟動鴻蒙原生應(yīng)用開發(fā)
HarmonyOS 代碼工坊的指尖開發(fā),讓 APP 開發(fā)所見即所得
HarmonyOS開發(fā)案例:【app初始啟動】
評論