鸿蒙期末个人项目-黑马健康——项目阶段八:发现页面和我的页面UI界面以及
目录项目介绍:
页面布局:
分析:
发现页面UI设计:
我的页面UI设计:
登录页面UI设计:
健康信息页面UI设计:
页面实现效果:
出现的问题与办理:
阶段项目代码:
发现页面代码:
我的页面代码:
登录页面代码:
健康信息页面代码:
项目介绍:
黑马健康软件是一款基于全民健康的软件,重要有三个页面构成,分别是欢迎页面,统计记录页面,食物列表页面。
页面布局:
分析:
发现页面UI设计:
[*]总体是一个列式布局,第一行是一有两个文本组件构成,第二行是由list组件构成的一个水平滑动样式,第三行是有两个文本构成,最后是由list组件渲染的列式布局样式
我的页面UI设计:
[*]总体是列式布局,第一行是有两个Image组件构成,此中一个是之前在食物列表页面用到的消息的渲染效果,另一个是一个设置按钮,点击按钮之后,会弹出一个panel弹窗,在这里可以点击换字体大小,实现全局变化字体大小的效果,并实现用户持久化;第二行是一个有Image组件和Text组件渲染的用户登录的样式,点击后,可以跳转到用户登录注册的界面(这里只实现了用户的登录),输入信息后,点击“登录”按钮,即可跳转回顾页,而且输入的账号等登录乐成的信息也会传递返来,而且重新进行登录注册组件的渲染。第三行是一个关于健康数据的组件,由Image组件和Text组件构成,点击后可以跳转到健康数据页面。最后一行是由List组件循环渲染的应用功能的组件。
登录页面UI设计:
[*]登录页面是一个列式布局,第一行是由Image组件构成的登录标识,第二行是一个文本组件,第三行和四行分别是输入的用户名和密码,最后一行是登录和注册的按钮;
健康信息页面UI设计:
[*]总体是列式布局,首部是有两个Image组件构成,此中一个是退出此页面,返回主页面的退回图片,下面的部分是由一个网格Grid组件构成的,用ForEach循环渲染健康信息。
页面实现效果:
https://i-blog.csdnimg.cn/blog_migrate/db18a0b4f9832281b23526e87765decb.png
https://i-blog.csdnimg.cn/blog_migrate/4bc711c2522aaa99eb7ff726920d33ff.png
https://i-blog.csdnimg.cn/blog_migrate/eabfdb6aa0a76e5b2cc314df35aad2d0.png
https://i-blog.csdnimg.cn/blog_migrate/b85692ea3eca52bcf5cffedf5cf3f451.png
https://i-blog.csdnimg.cn/blog_migrate/ce3cc1a51b035d06387eac78eee7dd94.png
出现的问题与办理:
[*]当不给这一行设定宽度的时间,Blank()组件是不起作用的
https://i-blog.csdnimg.cn/blog_migrate/9d1a71ba23127879f0bbeb06bac2c656.png
分配宽度之后:
https://i-blog.csdnimg.cn/blog_migrate/c989ee5770fb17bd36efb20e5546627d.png
https://i-blog.csdnimg.cn/blog_migrate/720ecd1f0a4309b18923aee567d93d59.png
[*]调用子组件时一直报错,但是不妨碍功能的利用,图片能正常加载
https://i-blog.csdnimg.cn/blog_migrate/eaf216646c2c30de0b0136aaf87b2237.png
https://i-blog.csdnimg.cn/blog_migrate/e2d0a64e22154cfe731a950dc40265d7.png
实行了很多遍,官方论坛里看还是没有办理
办理方式就是关闭编译器重新打开,不报错了
[*]发现页面的主题推荐,加载不出图片和文字资源。查抄之后,发现是构造函数的赋值错误
https://i-blog.csdnimg.cn/blog_migrate/fe83a985bfee71e95a4ec7f4c24e8f78.png
改动之后:图片资源和文字资源精确加载
https://i-blog.csdnimg.cn/blog_migrate/f2966de10e53b3ec2b9f5f3b15d7a986.png
[*]如果利用@Consume和@Provide来传递数据,只能在父子组件之间进行传递,不能在同一品级之间传递
[*]出现了运行时异常,在main_pages.json配置的必须是一个页面,带有@entry装饰器
https://i-blog.csdnimg.cn/blog_migrate/93d0640fd42e65b0bea23dd52b2ed966.png
[*] 这里click利用的装饰器是@link,就不能利用 this. 去传递参数,应该利用$传递参数
https://i-blog.csdnimg.cn/blog_migrate/394d013b618a2b4f76b2b4d513d08def.png
[*]当未登录是不能获取到页面跳转所传递过来的值,加上条件判断,等点击登录按钮,而且传递过来当界说的@State修饰的状态变量仍是false的时间才获取数据否则不会获取数据,而且将这两个变量实现持久化。 出现的问题仍旧如下:
https://i-blog.csdnimg.cn/blog_migrate/68f91183a7fd9c0bf610de795cb4150d.png
但是经过console.log后发现数据都传递过来了,
https://i-blog.csdnimg.cn/blog_migrate/63197455e62460e9c3f9d791d375c809.png但是在用户登录的界面偶尔渲染不上,(那种感觉似乎是页面渲染和数据的传递在竞速)而且出现了一些bug,就是当实现登录后,点击退出,再次进入该应用时,就会发生一些运行时异常,直接卡退。
经过重新的梳理分析,发如今页面跳转获取数据时有逻辑上的问题,很可能没有执行登录,就去获取登录页面穿过来的值,这样就会导致卡退。办理办法就是利用一些状态参数来控制传值,当点击登录而且登录乐成时,才会去获取数据,进行数据传递和页面的渲染,在登录乐成之后,就会将背面页面渲染所要用到的数据实现持久化处理,而且状态参数也会实现持久化处理。
阶段项目代码:
发现页面代码:
import { CommonConstants } from '../../common/constants/CommonConstants'
import FunctionList from './FunctionList'
import RecommendTheme from './RecommendTheme'
import ThemeInfo from './ThemeInfo'
/**
* 发现页面
*/
@Component
export default struct FindPage {
@Consume fontSize:number
build() {
Column({ space: CommonConstants.SPACE_8 }) {
// 1.推荐主题
Row() {
Text('推荐主题')
.fontWeight(CommonConstants.FONT_WEIGHT_700)
.fontSize(this.fontSize+4)
Blank()
Text('更多')
}
.width(CommonConstants.THOUSANDTH_940)
.margin({ top: 10, bottom: 10 })
// 2.主题展示
Row({space:CommonConstants.SPACE_4}){
RecommendTheme()
}
.backgroundColor(Color.White)
.width(CommonConstants.THOUSANDTH_940)
.height(210)
.borderRadius(CommonConstants.DEFAULT_18)
.justifyContent(FlexAlign.SpaceEvenly)
.margin({ bottom: 10 })
// 3.功能管理
Row() {
Text('功能管理')
.fontWeight(CommonConstants.FONT_WEIGHT_700)
.fontSize(this.fontSize+4)
Blank()
Image($r('app.media.sort'))
.width(18)
}
.width(CommonConstants.THOUSANDTH_940)
.margin({ top: 10, bottom: 10 })
// 4.功能列表
FunctionList()
.layoutWeight(1)
.margin({left:5})
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.index_page_background'))
}
}
import { CommonConstants } from '../../common/constants/CommonConstants'
import ThemeInfo from './ThemeInfo'
@Component
export default struct RecommendTheme {
themeList: Array<ThemeInfo> = [
new ThemeInfo('绿泡泡', $r('app.media.background_green')),
new ThemeInfo('粉色回忆', $r('app.media.background_pink')),
new ThemeInfo('色彩碰撞', $r('app.media.background_color')),
new ThemeInfo('清凉一夏', $r('app.media.bacground_color2')),
new ThemeInfo('黑夜骑士', $r('app.media.background_color3')),
new ThemeInfo('甜美西瓜', $r('app.media.background_color4')),
new ThemeInfo('璀璨星河', $r('app.media.background_color5')),
]
build() {
List(){
ForEach(this.themeList,(item:ThemeInfo)=>{
ListItem(){
Column({space:CommonConstants.SPACE_4}){
Image(item.images)
.width(120)
.aspectRatio(0.7)
.borderRadius(CommonConstants.DEFAULT_18)
.shadow({radius: 6, color:'#000000',offsetX:4,offsetY:4})
Text(item.name)
.fontWeight(20)
}
}.margin({left:7,right:5,top:10})
})
}.listDirection(Axis.Horizontal)//图片水平摆放
}
}
import { CommonConstants } from '../../common/constants/CommonConstants'
import ThemeInfo from './ThemeInfo'
@Component
export default structFunctionList{
@Consume fontSize:number
themeList: Array<ThemeInfo> = [
new ThemeInfo('消息通知', $r('app.media.fun_1')),
new ThemeInfo('闹钟', $r('app.media.fun_2')),
new ThemeInfo('名片', $r('app.media.fun_3')),
new ThemeInfo('查找设备', $r('app.media.fun_4')),
new ThemeInfo('遥控拍照', $r('app.media.fun_5')),
new ThemeInfo('天气推送', $r('app.media.fun_6')),
new ThemeInfo('音乐', $r('app.media.fun_7')),
new ThemeInfo('常用联系人', $r('app.media.fun_8')),
new ThemeInfo('健康提醒', $r('app.media.fun_9')),
new ThemeInfo('其他功能', $r('app.media.fun_10')),
]
build() {
List(){
ForEach(this.themeList,(item:ThemeInfo)=>{
ListItem(){
Row({space:CommonConstants.SPACE_8}){
Image(item.images)
.width(35)
.height(35)
.margin({left:7,right:15})
.borderRadius(CommonConstants.DEFAULT_18)
// .shadow({radius: 6, color:'#000000',offsetX:4,offsetY:4})
Text(item.name)
.fontWeight(26)
.fontSize(this.fontSize-2)
}
.padding(8)
.backgroundColor(Color.White)
.borderRadius(CommonConstants.DEFAULT_18)
.width(CommonConstants.THOUSANDTH_940)
.height(50)
}.margin({left:12,right:5,top:2,bottom:8})
})
}
}
} 我的页面代码:
import router from '@ohos.router'
import preferences from '@ohos.data.preferences'
import { CommonConstants } from '../../common/constants/CommonConstants'
import ChangePanel from '../../viewmodel/ChangePanel'
import AppSetting from './AppSetting'
import MyPageHeader from './MyPageHeader'
import preferencesUtil from '../../common/utils/preferencesUtil'
/**
* 我的页面
*/
@Component
export default struct MyPage {
days:number = 1
@Consume showPanel:number
@Consume fontSize:number
@Prop username:string
@Prop hasLogin:boolean
@Link clickLogin:boolean
@State user_name:string = '用户请登录'
@State welcome_use:string = '请注册/登录使用~'
build() {
Column({space:CommonConstants.SPACE_8}){
// 1.我的页面首部
MyPageHeader()
// 2.用户的登录注册
Row(){
if(!this.hasLogin){
Image($r('app.media.entry'))
.width(70)
.fillColor(Color.Red)
.margin({right:10})
}else{
Image($r('app.media.user_img'))
.width(70)
.margin({right:10})
}
Column(){
if(this.hasLogin){
Text('ID:'+this.username)
.fontWeight(CommonConstants.FONT_WEIGHT_600)
.fontColor(Color.Red)
.fontSize(this.fontSize+4)
Text('欢迎使用黑马健康!')
.fontColor($r('app.color.light_gray'))
.fontSize(this.fontSize-2)
}else{
Text(this.user_name)
.fontWeight(CommonConstants.FONT_WEIGHT_600)
.fontColor(Color.Red)
.fontSize(this.fontSize+4)
Text(this.welcome_use)
.fontColor($r('app.color.light_gray'))
.fontSize(this.fontSize-2)
}
}
}
.padding(10)
.height('100')
.width(CommonConstants.THOUSANDTH_940)
.justifyContent(FlexAlign.Start)
.margin({bottom:13,top:6})
.backgroundColor($r('app.color.White_Color'))
.borderRadius(CommonConstants.DEFAULT_10)
.onClick(()=>{
//当点击登录时,首先将this.clickLogin ,this.hasLogin的状态写进首选项
console.log('成功点击登录'+'testTag')
this.clickLogin = true
preferencesUtil.putPreferenceValue('UserLoginInfo','clickVictoryInfo',this.clickLogin)
this.hasLogin = false
preferencesUtil.putPreferenceValue('HasLogin','HasLoginInfo',this.hasLogin)
router.pushUrl({
url:'pages/LoginPage'
})
})
// 3.健康使用
// 覆盖的功能
Row({space:CommonConstants.SPACE_8}){
Column({space:CommonConstants.SPACE_8}){
//您已健康使用多少天?点击查看健康数据
Text(`您已健康使用 ${this.days} 天`)
.fontSize(this.fontSize+4)
.fontWeight(CommonConstants.FONT_WEIGHT_600)
.fontColor(Color.White)
Text('点击查看您的健康信息')
.fontSize(this.fontSize-2)
.fontColor(Color.White)
}
Blank()
Image($r('app.media.healthInfo'))
.width(60)
}
.padding(10)
.width(CommonConstants.THOUSANDTH_940)
.height(80)
.backgroundColor($r('app.color.primary_color'))
.borderRadius(CommonConstants.DEFAULT_18)
.shadow({radius: 6, color:'#000000',offsetX:7,offsetY:10})
.onClick(()=>{
router.pushUrl({
url:'pages/HealthStatisticPage'
})
})
//VIP设置
Row({space:CommonConstants.SPACE_8}){
Column({space:CommonConstants.SPACE_8}){
Text('升级VIP享更多专属权限')
.fontSize(this.fontSize+2)
.fontWeight(CommonConstants.FONT_WEIGHT_600)
.fontColor(Color.White)
Text('升级VIP享更多专属权限')
.fontSize(this.fontSize-2)
.fontColor(Color.White)
}
Blank()
Button('去升级')
.type(ButtonType.Capsule)
.fontColor($r('app.color.primary_color'))
.backgroundColor(Color.White)
}
.padding(10)
.width(CommonConstants.THOUSANDTH_940)
.height(80)
.backgroundColor($r('app.color.primary_color'))
.borderRadius(CommonConstants.DEFAULT_18)
.shadow({radius: 6, color:'#000000',offsetX:7,offsetY:10})
// 4.应用的设置等
AppSetting()
.layoutWeight(1)
if(this.showPanel===1){
ChangePanel()
.transition({
translate: { y: 115 }
})
.layoutWeight(1)
}
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.index_page_background'))
}
} import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct MyPageHeader {
@Consume showPanel:number
build() {
Column(){
// 1.设置按钮和信息
Row({space:CommonConstants.SPACE_10}){
Blank()
Image($r('app.media.setting')).width(28).margin({right:10})
.onClick(()=>{
this.showPanel = -this.showPanel
console.log("弹窗显示成功",'testTag')
})
Badge({count:1,position:BadgePosition.RightTop,style:{fontSize:12}}){
Image($r('app.media.ic_public_email'))
.width(28)
}
}
.width(350)
.margin({top:7})
.height(30)
}
}
} 登录页面代码:
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import { CommonConstants } from '../common/constants/CommonConstants'
import preferencesUtil from '../common/utils/preferencesUtil'
@Entry
@Component
struct LoginPage {
@State username:string = ''
@State password:string = ''
@State hasLogin:boolean = false
build() {
Image($r('app.media.login_img'))
.width(60)
.margin({top:160,bottom:10})
Text('欢迎登录')
.fontWeight(CommonConstants.FONT_WEIGHT_600)
.fontSize(30)
Row(){
Text('用户名:').fontWeight(CommonConstants.FONT_WEIGHT_600).fontSize(18)
TextInput({placeholder:'请输入用户名:'})
.margin({top:20,bottom:15})
.width(250)
.height(40)
.fontColor(Color.Blue)
.onChange((value:string)=>{
this.username = value
})
}.width(300)
Row(){
Text('密 码:').fontWeight(CommonConstants.FONT_WEIGHT_600).fontSize(18)
TextInput({placeholder:'请输入密码:'})
.type(InputType.Password)
.width(250)
.height(40)
.fontColor(Color.Blue)
.onChange((value:string)=>{
this.password = value
})
}.width(300)
Row({space:CommonConstants.SPACE_12}){
Button('登录')
.type(ButtonType.Capsule)
.fontSize(18)
.backgroundColor($r('app.color.primary_color'))
.onClick(()=>{
// router.back()
//如果输入的用户名或者密码为空,则提示
if(this.username==='' || this.password ===''){
//登录失败
prompt.showToast({
message:"账号和密码均不可以为空!"
})
}else{
//登录成功
this.hasLogin = true
console.log('hasLogin:'+this.hasLogin.toString()+'testTag')
console.log('username:'+this.username.toString()+'testTag')
//将已经登录成功的信息写入首选项
preferencesUtil.putPreferenceValue('HasLogin','HasLoginInfo',this.hasLogin)
router.replaceUrl({
url:'pages/Index',
params:{
username:this.username,
}
})
}
})
Button('注册')
.type(ButtonType.Capsule)
.fontSize(18)
.backgroundColor($r('app.color.light_gray'))
}.margin({top:30})
}
.backgroundColor($r('app.color.index_page_background'))
.height('100%')
.width('100%')
}
} 健康信息页面代码:
import router from '@ohos.router'
import { CommonConstants } from '../common/constants/CommonConstants'
import preferencesUtil from '../common/utils/preferencesUtil'
import HealthComponent from '../view/health/HealthComponent'
@Entry
@Component
struct HealthStatisticPage {
@State hasLogin:boolean = false
async aboutToAppear(){
//将登录成功的值从用户首选项中取出来
this.hasLogin = await preferencesUtil.getPreferenceValue('HasLogin','HasLoginInfo',false) as boolean
}
build() {
Column({space:CommonConstants.SPACE_10}){
Row({space:CommonConstants.SPACE_10}){
Image($r('app.media.ic_public_back')).width(40)
.onClick(()=>{
router.back()
})
Text('健康').fontSize(20)
Blank()
if(this.hasLogin){
Image($r('app.media.user_img')).width(40)
}else{
Image($r('app.media.entry')).width(40)
}
}
.width(CommonConstants.THOUSANDTH_940)
.margin({top:10})
//网格记录项,祥康组件
HealthComponent()
.layoutWeight(1)
}.width('100%')
.height('100%')
.backgroundColor($r('app.color.index_page_background'))
}
}
参考黑马课堂老师的讲解,欢迎大家的批评和指正。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]