一、项目名称:黑马健康
黑马健康app是一款通过记录饮食,食物营养成分,以及提供运动可消耗热量的app,用户可以查看饮食记录帮助用户清晰的得知自己的个人身体热量与营养的摄入与消耗以及还可摄入多少热量
二、运行过程
1.欢迎页面UI实现
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()
})
})
async aboutToAppear(){
//加载首选项
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({
url:'pages/Index'
})
},1000)
}
//如果选择同意
onConfirm(){
//1.保存首选项
PreferenceUtil.putPreferenceValue(PREF_KEY,true)
//2.跳转到首页
this.jumpToIndex()
}
exitApp(){
//退出App
this.context.terminateSelf()
}
build() {
//字的间距太小,用space改变
Column({space:10}) {
//1.中央slogan
//如何让中央的字占据剩下的全部空间?用布局权重来解决1.先单独设一个行,给这个行加一个布局权重
Row(){
Image($r('app.media.home_slogan')).width(260)
}
.layoutWeight(1)
//2.logo
Image($r('app.media.home_logo')).width(150)
//3.文字描述
Row(){
Text('黑马健康支持').opacitywhiteText(0.8,12)
Text('IPv6')
.opacitywhiteText(0.8)
//边框:border
.border({style:BorderStyle.Solid,width:1,color:Color.White,radius:'15%'})//style 样式(虚线或实线)BorderStyle.Solid 枚举,实线 width:边框宽度 color:Color.White边框颜色为白色 radius:'15%'边框弧度
.padding({left:5,right:5})//边距,左右都为5
Text('网络').opacitywhiteText(0.8,12)
}
Text(`'减更多'指黑马健康APP希望通过软件工具的形式,帮助更多用户实现身材管理`)
.opacitywhiteText(0.6)
Text('浙ICP备00000000号-36D')
.opacitywhiteText(0.4)
//如果最下面一行字太贴底,就给最下面的文字加一个外边距
.margin({bottom:35})
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.welcome_page_background'))
}
}
import { CommonConstants } from '../../common/constants/CommonConstants'
@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)
}
}
2.Tabs组件
import { CommonConstants } from '../common/constants/CommonConstants'
import RecordIndex from '../view/record/RecordIndex'
@Entry
@Component
struct Index {
@State currentIndex: number = 0
@Builder TabBarBuilder(title:ResourceStr,image:ResourceStr,index:number){
Column({space:CommonConstants.SPACE_8}){
Image(image)
.width(22)
.fillColor(this.selectColor(index))
Text(title)
.fontSize(14)
.fontColor(this.selectColor(index))
}
}
selectColor(index:number){
return this.currentIndex==index ?$r('app.color.primary_color'):$r('app.color.gray')
}
build() {
Tabs({barPosition:BarPosition.End}) {
TabContent(){
RecordIndex()
}
.tabBar(this.TabBarBuilder($r('app.string.tab_record'),$r('app.media.ic_calendar'),0))
TabContent(){
Text('发现页面')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_discover'),$r('app.media.discover'),1))
TabContent(){
Text('我的主页')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_user'),$r('app.media.ic_user_portrait'),2))
}
.width('100%')
.height('100%')
.onChange(index=>this.currentIndex=index)
}
}
总结
1.欢迎页面
引入了自定义工具类PreferenceUtil
用于处理本地偏好设置,以及UserPrivacyDialog
组件用于展示用户隐私协议对话框。
定义了一个名为opacityWhiteText
的装饰器函数,用于快速设置文本的不透明度、字体大小和颜色,提高代码复用性和可读性。
PREF_KEY
:用于存储用户隐私政策同意状态的键名。
初始化了UI上下文context
和一个自定义对话框控制器controller
,用于管理用户隐私协议对话框的显示与交互。
定义了生命周期方法aboutToAppear
,在页面即将出现时检查用户是否已同意隐私政策。根据检查结果决定是跳转至首页还是显示隐私对话框。
实现了跳转首页的方法jumpToIndex
,并带有1秒延迟,可能是为了展示动画效果。
onConfirm
方法处理用户点击同意隐私政策后的逻辑,包括保存同意状态至本地,并跳转至首页。
exitApp
方法用于直接终止应用程序
2.对话框
-
从
CommonConstants
导入了常用的空间间隔和字体权重等常量,以便保持UI设计的一致性。cancel
: 用户拒绝隐私政策时调用的回调函数。confirm
: 用户同意隐私政策时调用的回调函数。controller
: 用于控制对话框的显示与关闭。
- 使用结构体(struct)定义了
UserPrivacyDialog
组件,并通过@CustomDialog
装饰器表明它是一个自定义对话框。 -
构建UI界面:
build
方法内使用了声明式语法来构建对话框的布局,包含: - 按钮: 包含“同意”和“拒绝”两个按钮。
- “拒绝”按钮:同样设置了宽度、背景色(较浅)、字体颜色,并在点击时调用
cancel
回调及关闭对话框。 - “同意”按钮:设置了宽度、背景色,并绑定了点击事件,当用户点击时会调用
confirm
回调并关闭对话框。 - 内容: 展示详细的隐私政策内容。
- 标题: 通过
Text
组件展示隐私政策的标题,设置了字体大小和加粗样式。
- “拒绝”按钮:同样设置了宽度、背景色(较浅)、字体颜色,并在点击时调用
-
样式与布局:
- 对话框主体使用
Column
布局,各部分之间有预定义的间距。 - 整个对话框宽度为100%,并添加了内边距,以适应不同屏幕尺寸并保持良好的视觉效果。
- 对话框主体使用