【鸿蒙HarmonyOS.4】健身APP项目 从0开始 第一天(借鉴b站某厂程序员)
目录
制作欢迎页面
用户协议弹窗制作
首选项存储欢迎页面完结
制作首页
遇到的问题
本项目开发了一款健身app,有进入app界面、首页界面、任务项界面、成就界面、个人界面,可以自由选择任务项界面中存在的运动项目并添加到今日的日程当中,并根据添加的运动项目计算当日的运动量(卡路里),累计达成目标天数获得成就。
制作欢迎页面
在pages中创建SplashIndex.ets作为欢迎界面
用户协议弹窗制作
在dialog中创建UserPrivacyDialog.ets作为用户协议弹窗
首选项存储欢迎页面完结
制作首页
在pages中创建MainIndex.ets作为首页界面
遇到的问题
在SplashIndex类欢迎界面中定义两个常量存储首选项中的键时,将string写成大写S开头的String,导致在写定义首选项
let preferences = data_preferences.getPreferences(this.context, H_STORE)
和记录用户数据到首选项
res.put(IS_PRIVACY, true).then(() => {
res.flush();
Logger.debug('SplashIndex', 'isPrivacy记录成功')
}).catch((err: Error) => {
Logger.error('SplashIndex', 'isPrivacy记录失败,原因: '+ err)
})
时,H_STORE 和 IS_PRIVACY报错 Argument of type 'String' is not assignable to parameter of type 'string'. 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible. <tsCheck>
原因:
string 是一个原始数据类型,而 String 是一个包装对象。原始数据类型 string 用于表示文本数据,而 String 对象提供了一些方法来操作这些文本数据。TypeScript 的类型检查器会区分这两者,并在类型不匹配时给出错误或警告。
错误信息 "Argument of type 'String' is not assignable to parameter of type 'string'" 意味着尝试将一个 String 对象实例传递给一个期望 string 类型参数的函数或方法。为了解决这个问题,应该确保传递的是原始的 string 类型,而不是 String 对象。
import UserPrivacyDialog from '../dialog/UserPrivacyDialog'
import common from '@ohos.app.ability.common'
import data_preferences from '@ohos.data.preferences'
import Logger from '../utils/Logger'
import router from '@ohos.router'
const H_STORE: string = 'BaiZhanKeepStore'
const IS_PRIVACY: string = 'isPrivacy'
@Entry
@Component
struct SplashIndex {
context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
dialogController: CustomDialogController = new CustomDialogController({
builder: UserPrivacyDialog({
cancel: () => {this.exitApp()},
confirm: () => {this.onConfirm()}
})
})
onConfirm() {
let preferences = data_preferences.getPreferences(this.context, H_STORE)
preferences.then((res) => {
res.put(IS_PRIVACY, true).then(() => {
res.flush();
Logger.debug('SplashIndex', 'isPrivacy记录成功')
}).catch((err: Error) => {
Logger.error('SplashIndex', 'isPrivacy记录失败,原因: '+ err)
})
})
}
exitApp() {
this.context.terminateSelf()
}
aboutToAppear() {
let preferences = data_preferences.getPreferences(this.context, H_STORE)
preferences.then((res) => {
res.get(IS_PRIVACY, false).then((isPrivate) => {
if(isPrivate === true) {
this.jumpToMain()
}else {
this.dialogController.open()
}
})
})
}
jumpToMain() {
setTimeout(() => {
router.replaceUrl({url: ''})
}, 2000)
}
aboutToDisappear() {
clearTimeout()
}
build() {
Column() {
Image($r('app.media.logo'))
.width(100)
.margin({top: 120})
Text('欢迎进入百战健身')
.fontSize(25)
.fontColor('#FFFFFF')
.fontWeight(800)
.letterSpacing(0.8)
.opacity(0.7)
.margin({top: 20, bottom: 140})
Image($r('app.media.titlePhoto'))
.width('80%')
}
.width('100%')
.height('100%')
.backgroundImage($r('app.media.welcomeBg'))
.backgroundImageSize({width: '100%', height: '100%'})
.backgroundImagePosition({x: 0, y: 0})
}
}
MainIndex类:
@Entry
@Component
struct MainIndex {
@State selectIndex: number = 0
@Builder TabBarBuilder(index: number, normalIcon: ResourceStr, selIcon: ResourceStr, text: string) {
Column() {
Image(this.selectIndex === index ? selIcon : normalIcon)
.width(20)
Text(text)
.fontSize(10)
.fontColor(this.selectIndex === index ? $r('app.color.tab_bar_sel') : $r('app.color.tab_bar_normal'))
}
}
build() {
Tabs({
barPosition: BarPosition.End,
index: this.selectIndex
}) {
TabContent()
.tabBar(this.TabBarBuilder(
0,
$r('app.media.ic_tabs_home_normal'),
$r('app.media.ic_tabs_home_sel'),
"主页"
))
TabContent()
.tabBar(this.TabBarBuilder(
1,
$r('app.media.ic_tabs_achievement_normal'),
$r('app.media.ic_tabs_achievement_sel'),
"成就"
))
TabContent()
.tabBar(this.TabBarBuilder(
2,
$r('app.media.ic_tabs_mine_normal'),
$r('app.media.ic_tabs_mine_sel'),
"个人"
))
}
.onChange((index: number) => {
this.selectIndex = index
})
}
}
UserPrivacyDialog类:
@Preview
@CustomDialog
export default struct UserPrivacyDialog {
controller: CustomDialogController = new CustomDialogController({builder: ''})
cancel: Function = () => {}
confirm: Function = () => {}
build() {
Column({space: 10}) {
Text($r('app.string.welcome_title'))
.fontSize(20)
.fontWeight(FontWeight.Bolder)
.margin({top: 8, bottom: 5})
Text() {
Span($r('app.string.welcome_span_one'))
}
Text() {
Span($r('app.string.welcome_span_two'))
Span($r('app.string.personal_privacy_protocol'))
.fontColor($r('app.color.privacy_color'))
Span($r('app.string.welcome_span_three'))
Span($r('app.string.user_protocol'))
.fontColor($r('app.string.welcome_span_four'))
Span($r('app.string.welcome_span_four'))
}
Text() {
Span($r('app.string.welcome_span_end'))
}
Button('同意')
.fontColor(Color.White)
.backgroundColor("#ff06ae27")
.width(150)
.onClick(() => {
this.confirm()
this.controller.close()
})
Button('不同意')
.fontColor("#d09d9d9d")
.backgroundColor("#412ef550")
.width(150)
.onClick(() => {
this.cancel()
this.controller.close()
})
}
.width('80%')
.height('75%')
}
}
网址:【鸿蒙HarmonyOS.4】健身APP项目 从0开始 第一天(借鉴b站某厂程序员) https://www.yuejiaxmz.com/news/view/80178
相关内容
鸿蒙智联生态产品《接入智慧生活App开发指导》(官方更新版)Harmony鸿蒙实战开发项目
基于 HarmonyOS Next 和 ArkUI 开发一款 健康生活APP
鸿蒙生态,便捷生活:华为智能门锁 Plus解锁有娃家庭智慧新体验
【HarmonyOS第一课:运动健康实战】我的运动生活
2023 总结:我在上海做程序员的第八年大家好,我是拭心。 这篇文章我将从生活、赚钱、专业技术、健康几方面总结我的 20
创新体验 + 超多福利,升级 HarmonyOS NEXT 数字生活更给力
一个美好的家庭,这些小故事的例子值得大家借鉴
从容生活,从爬一次山开始
科技快报