介紹
本篇Codelab基于自定義彈框、首選項和頁面路由實現一個模擬應用首次啟動的案例。需要完成以下功能:
- 實現四個頁面,啟動頁、隱私協議頁、廣告頁、應用首頁。
- 頁面之間的跳轉。
- 實現自定義隱私協議彈窗,點擊協議可查看隱私協議具體內容。
- 隱私協議狀態持久化存儲,再次啟動時,如果沒有保存狀態會再次彈出,否則不彈出。
效果如圖所示:
相關概念
- [首選項] :首選項為應用提供Key-Value鍵值型的數據處理能力,支持應用持久化輕量級數據,并對其修改和查詢。數據存儲形式為鍵值對,鍵的類型為字符串型,值的存儲數據類型包括數字型、字符型、布爾型以及這3種類型的數組類型。
- [自定義彈窗]: 通過CustomDialogController類顯示自定義彈窗。
- [頁面路由]:提供通過不同的url訪問不同的頁面,包括跳轉到應用內的指定頁面、用應用內的某個頁面替換當前頁面、返回上一頁面或指定的頁面等。
環境搭建
軟件要求
- [DevEco Studio] 版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 開發板類型:[潤和RK3568開發板]。
- OpenHarmony系統:3.2 Release。
環境搭建
完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:
- [獲取OpenHarmony系統版本] :標準系統解決方案(二進制)。以3.2 Release版本為例:
- 搭建燒錄環境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開發板的燒錄]
- 鴻蒙開發指導文檔:[
qr23.cn/AKFP8k
]
- 搭建開發環境。
- 開始前請參考[工具準備] ,完成DevEco Studio的安裝和開發環境配置。
- 開發環境配置完成后,創建工程(模板選擇“Empty Ability”)。
- 工程創建完成后,選擇使用[真機進行調測] 。
代碼結構解讀
本篇Codelab只對核心代碼進行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區
│ ├──common
│ │ ├──constants
│ │ │ └──CommonConstants.ets // 常量類
│ │ └──utils
│ │ ├──GlobalContext.ets // 項目工具類
│ │ └──Logger.ets // 日志打印工具類
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口類
│ ├──pages
│ │ ├──AdvertisingPage.ets // 廣告頁
│ │ ├──AppHomePage.ets // 應用首頁
│ │ ├──LauncherPage.ets // 應用啟動頁
│ │ └──PrivacyPage.ets // 隱私協議頁
│ └──view
│ └──CustomDialogComponent.ets // 自定義彈窗組件
└──entry/src/main/resources // 資源文件目錄
應用啟動頁實現
打開應用時進入EntryAbility頁面,通過windowStage.loadContent方法加載啟動頁LauncherPage,然后在LauncherPage的build里面構建啟動頁組件,效果如圖所示:
// 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)
}
隱私彈窗實現
啟動頁的隱私協議內容需要用到自定義彈窗,效果如圖所示:
// CustomDialogComponent.ets
// 自定義彈窗
@CustomDialog
export default struct CustomDialogComponent {
controller: CustomDialogController = new CustomDialogController({'builder': ''});
// 不同意按鈕回調
cancel: Function = () = > {}
// 同意按鈕回調
confirm: Function = () = > {}
build() {
Column() {
// 彈窗標題
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')
})
// 彈窗內容
Text($r('app.string.dialog_text_privacy_content'))
.fontSize($r('app.float.dialog_common_text_size'))
.width(CommonConstants.DIALOG_COMPONENT_WIDTH_PERCENT)
// 協議鏈接
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));
});
})
// 協議聲明
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)
}
獲取隱私協議狀態
構建啟動頁之前,在LauncherPage的生命周期onPageShow方法處,添加一個命名為“myStore”的首選項表,并在“myStore”首選項表讀取一個名為“isPrivacy”的字段,獲取隱私協議狀態。
// LauncherPage.ets
onPageShow() {
...
// 獲取保存數據操作類
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) {
// 自定義協議彈窗
this.dialogController.open();
}
} else {
// 跳至廣告頁
this.jumpToAdvertisingPage();
}
});
});
}
// 獲取數據首選項操作
getDataPreferences(common: Object) : Promise< preferences.Preferences >{
return preferences.getPreferences(getContext(common), CommonConstants.PREFERENCES_FILE_NAME);
}
保存隱私協議狀態
當用戶點擊隱私協議彈窗同意按鈕時,回調onConfirm方法,調用saveIsPrivacy保存隱私協議狀態。
// LauncherPage.ets
onConfirm(): void {
// 保存隱私協議狀態
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();
...
});
}
頁面跳轉
用戶在啟動頁LauncherPage,點擊隱私協議彈窗同意按鈕onConfirm,在onConfirm方法內開啟3秒倒計時,倒計時結束后跳到廣告頁,當啟動頁不可見時,清除定時器和啟動頁,效果如圖所示:
// LauncherPage.ets
private isJumpToAdvertising: boolean = false;
onConfirm() :void{
...
// 跳轉到廣告頁
this.jumpToAdvertisingPage();
}
jumpToAdvertisingPage() :void{
this.timerId = setTimeout(() = > {
// 設置跳轉標識
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);
// 清除定時器
clearTimeout(this.timerId);
}
打開廣告頁AdvertisingPage后,進行2秒倒計時(用戶可手動點擊跳過),倒計時結束跳轉到首頁AppHomePage,當廣告頁不可見時,清除定時器和廣告頁,效果如圖所示:
// AdvertisingPage.ets
@State countDownSeconds: number = CommonConstants.ADVERTISING_COUNT_DOWN_SECONDS;
private timeId: number = 0;
onPageShow() {
// 開啟2秒倒計時
this.timeId = setInterval(() = > {
if (this.countDownSeconds == 0) {
// 跳轉到首頁
this.jumpToAppHomePage();
} else {
this.countDownSeconds--;
}
}, CommonConstants.ADVERTISING_INTERVAL_TIME);
}
onPageHide() {
// 清除頁面
router.clear();
// 清除定時器
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));
});
}
審核編輯 黃宇
-
存儲
+關注
關注
13文章
4320瀏覽量
85912 -
鴻蒙
+關注
關注
57文章
2363瀏覽量
42888 -
HarmonyOS
+關注
關注
79文章
1977瀏覽量
30264
發布評論請先 登錄
相關推薦
評論