【鸿蒙HarmonyOS.4】健身APP项目 第三天(借鉴b站某厂程序员)

目录

主页bottom部分的下半部分

实现主页添加按钮

添加任务页面

制作添加任务弹窗

 遇到的问题


  • 主页bottom部分的下半部分

  • 有任务状态

  • 无任务状态 

  • 该部分现阶段HomeContent.ets代码
//主页

import DateDialog from '../../dialog/DateDialog'
import DateUtil from '../../utils/DateUtil'

@Preview
@Component
export default struct HomeContent {

  @StorageProp('date')      //从全局获取,DateDialog中保存到全局中的日期
  date: number = DateUtil.beginTimeOfDay(new Date()) //定义一个变量,使用beginTimeOfDay获取到当天的一个日期

  //创建一个数组,直接使用的是死数据,没有经过数据库,直接展示的内容
  @State arr: any[] = [
    {
      name: '跳绳',
      icon: $r('app.media.skip'),
      consume: 60,//消耗
      num: 10,    //已经完成的数量
      target: 10, //目标数量
      pre: '分钟'  //单位
    },
    {
      name: '游泳',
      icon: $r('app.media.swim'),
      consume: 400,
      num: 1,
      target: 2,
      pre: '小时'
    },
    {
      name: '卧推',
      icon: $r('app.media.push'),
      consume: 30,
      num: 5,
      target: 10,
      pre: '个'
    },
  ]

  //将DateDialog弹窗打开
  controller: CustomDialogController = new CustomDialogController({
    builder: DateDialog({ date: new Date(this.date)})
  })

  build() {
    Column() {
      Column() {
        Text('百战健身')
          .fontSize(25)
          .fontWeight(600)
          .margin({ top: 10, bottom: 100, left: 20})
        Row() {                                   //日期选择
          Text(DateUtil.formatDate(this.date))//把获取到的data转换成年月日
            .fontSize(15)
            .fontWeight(500)
          Image($r('app.media.arrow_down'))
            .width(20)
        }
        .width('90%')
        .height(50)
        .backgroundColor(Color.White)
        .margin({ left: 19, top: 90})
        .borderRadius(20)//圆角
        .justifyContent(FlexAlign.Center)//两个字组件居中显示
        .onClick(() => {    //点击整个Row容间都可以打开DateDialog日期选择弹窗
          this.controller.open()
        })
      }
      .backgroundImage($r('app.media.home_bg'))
      .backgroundImageSize({ width: '100%', height: '100%'})
      .width('100%')
      .height('40%')
      .alignItems(HorizontalAlign.Start)//交叉轴方向的对齐方式,左对齐
      .borderRadius({ bottomLeft: 20, bottomRight: 20})

      //堆叠容器,使主页的下半部分同时拥有任务列表和添加按钮
      Stack() {
        Column() {
          Text('任务列表')
            .fontSize(13)
            .fontWeight(700)
            .margin({ left: 20, top: 20, bottom: 10})

          if(this.arr.length !== 0) {       //有任务的状态
            //展示任务
            Column() {
              List({space: 10}) {
                ForEach(this.arr, (item) => {
                  ListItem() {
                    Row() {
                      Image(item.icon)
                        .width(50)
                        .height(50)
                      Text(item.name)
                        .fontSize(13)
                        .fontWeight(600)
                        .opacity(0.8)

                      //任务列表内容空白中间部分处理
                      Blank()

                      //任务列表框内容处理
                      if(item.num === item.target) { //完成的数量等于目标任务量
                        Text('消耗' + item.consume * item.num + '卡路里')
                          .fontSize(13)
                          .fontWeight(600)
                          .margin({ right: 10})
                          .fontColor($r('app.color.task_color'))
                      }else {
                        Text(item.num + ':' + item.target + '/' + item.pre)
                          .fontSize(13)
                          .fontWeight(600)
                          .margin({ right: 10})
                      }
                    }
                    .width('100%')
                    .backgroundColor(Color.White)
                    .borderRadius(15)//圆角
                  }
                  .width('90%')
                })
              }
              .width('100%')
              .alignListItem(ListItemAlign.Center)//list的每个子组件都居中展示
            }
            .width('100%')
          }else {                           //没有任务的状态
            Column({space: 8}) {
              Image($r('app.media.ic_no_data'))
                .width(350)
                .height(220)
              Text('暂无任务,请添加任务')
                .fontSize(20)
                .opacity(0.4)
            }
            .margin({ top: 68, left: 25})
          }
        }
        .width('100%')
        .height('100%')
        .alignItems(HorizontalAlign.Start)  //使任务列表这四个字等都展示在左侧
      }
      .width('100%')
      .height('100%')
    }
    .backgroundColor($r('app.color.light_gray')) //任务项背景图片,白框
  }
}

  • 实现主页添加按钮

  • 在view文件夹中的home文件夹下创建AddBtn.ets添加任务按钮按键

  • 该部分现阶段AddBtn.ets代码
//添加任务按钮,并且点击按钮会跳转到任务页面

@Component
export default struct AddBtn {
  clickAction: Function = () => {}
  build() {
    Button({type: ButtonType.Circle, stateEffect: false}) {
      Image($r('app.media.ic_home_add'))
        .borderRadius('50%')
        .width('100%')
        .height('100%')
    }
    .zIndex(2)
    .position({ x: '78%', y: '48%'})//偏移量
    .width(48)
    .height(48)
    .onClick(() => this.clickAction())  //在运行该项目测试添加任务按钮是否能够跳转界面时,并未发生跳转,原因是在clickAction后面未加(),
    // 不能执行该函数的内容
  }
}
  • 在主页中添加添加任务按钮(目前跳转后仅是空白页面)

  • 该部分现阶段HomeContent.ets代码
//主页

import DateDialog from '../../dialog/DateDialog'
import DateUtil from '../../utils/DateUtil'
import AddBtn from './AddBtn'
import router from '@ohos.router'
import Logger from '../../utils/Logger'

@Preview
@Component
export default struct HomeContent {

  @StorageProp('date')      //从全局获取,DateDialog中保存到全局中的日期
  date: number = DateUtil.beginTimeOfDay(new Date()) //定义一个变量,使用beginTimeOfDay获取到当天的一个日期

  //创建一个数组,直接使用的是死数据,没有经过数据库,直接展示的内容
  @State arr: any[] = [
    {
      name: '跳绳',
      icon: $r('app.media.skip'),
      consume: 60,//消耗
      num: 10,    //已经完成的数量
      target: 10, //目标数量
      pre: '分钟'  //单位
    },
    {
      name: '游泳',
      icon: $r('app.media.swim'),
      consume: 400,
      num: 1,
      target: 2,
      pre: '小时'
    },
    {
      name: '卧推',
      icon: $r('app.media.push'),
      consume: 30,
      num: 5,
      target: 10,
      pre: '个'
    },
  ]

  //重新定义一个点击事件
  addTask() {
    router.pushUrl({url: "pages/AddTaskPage"})
    Logger.debug('跳转到添加任务页面')
  }

  //将DateDialog弹窗打开
  controller: CustomDialogController = new CustomDialogController({
    builder: DateDialog({ date: new Date(this.date)})
  })

  build() {
    Column() {
      Column() {
        Text('百战健身')
          .fontSize(25)
          .fontWeight(600)
          .margin({ top: 10, bottom: 100, left: 20})
        Row() {                                   //日期选择
          Text(DateUtil.formatDate(this.date))//把获取到的data转换成年月日
            .fontSize(15)
            .fontWeight(500)
          Image($r('app.media.arrow_down'))
            .width(20)
        }
        .width('90%')
        .height(50)
        .backgroundColor(Color.White)
        .margin({ left: 19, top: 90})
        .borderRadius(20)//圆角
        .justifyContent(FlexAlign.Center)//两个字组件居中显示
        .onClick(() => {    //点击整个Row容间都可以打开DateDialog日期选择弹窗
          this.controller.open()
        })
      }
      .backgroundImage($r('app.media.home_bg'))
      .backgroundImageSize({ width: '100%', height: '100%'})
      .width('100%')
      .height('40%')
      .alignItems(HorizontalAlign.Start)//交叉轴方向的对齐方式,左对齐
      .borderRadius({ bottomLeft: 20, bottomRight: 20})

      //堆叠容器,使主页的下半部分同时拥有任务列表和添加按钮
      Stack() {
        Column() {
          Text('任务列表')
            .fontSize(13)
            .fontWeight(700)
            .margin({ left: 20, top: 20, bottom: 10})

          if(this.arr.length !== 0) {       //有任务的状态
            //展示任务
            Column() {
              List({space: 10}) {
                ForEach(this.arr, (item) => {
                  ListItem() {
                    Row() {
                      Image(item.icon)
                        .width(50)
                        .height(50)
                      Text(item.name)
                        .fontSize(13)
                        .fontWeight(600)
                        .opacity(0.8)

                      //任务列表内容空白中间部分处理
                      Blank()

                      //任务列表框内容处理
                      if(item.num === item.target) { //完成的数量等于目标任务量
                        Text('消耗' + item.consume * item.num + '卡路里')
                          .fontSize(13)
                          .fontWeight(600)
                          .margin({ right: 10})
                          .fontColor($r('app.color.task_color'))
                      }else {
                        Text(item.num + ':' + item.target + '/' + item.pre)
                          .fontSize(13)
                          .fontWeight(600)
                          .margin({ right: 10})
                      }
                    }
                    .width('100%')
                    .backgroundColor(Color.White)
                    .borderRadius(15)//圆角
                  }
                  .width('90%')
                })
              }
              .width('100%')
              .alignListItem(ListItemAlign.Center)//list的每个子组件都居中展示
            }
            .width('100%')
          }else {                           //没有任务的状态
            Column({space: 8}) {
              Image($r('app.media.ic_no_data'))
                .width(350)
                .height(220)
              Text('暂无任务,请添加任务')
                .fontSize(20)
                .opacity(0.4)
            }
            .margin({ top: 68, left: 25})
          }
        }
        .width('100%')
        .height('100%')
        .alignItems(HorizontalAlign.Start)  //使任务列表这四个字等都展示在左侧

        AddBtn({ clickAction: () => this.addTask()})
      }
      .width('100%')
      .height('100%')
    }
    .backgroundColor($r('app.color.light_gray')) //任务项背景图片,白框
  }
}

  • 添加任务页面

  • 在pages文件夹中创建AddTaskPage.ets添加任务按钮跳转页面(目前点击添加按钮后不能添加该任务)

  • 该部分现阶段AddTaskPage.ets代码
//添加任务按钮跳转页面

import router from '@ohos.router'

@Entry
@Component
struct AddTaskPage {

  //任务数组
  arr: any[] = [
    {
      name: '跳绳',
      icon: $r('app.media.skip'),
      consume: 600,
      pre: '小时'
    },
    {
      name: '游泳',
      icon: $r('app.media.swim'),
      consume: 400,
      pre: '小时'
    },
    {
      name: '卧推',
      icon: $r('app.media.push'),
      consume: 50,
      pre: '个'
    },
    {
      name: '慢跑',
      icon: $r('app.media.jog'),
      consume: 600,
      pre: '小时'
    },

  ]

  build() {
    Column() {
      //返回按钮
      Row() {
        Image($r('app.media.back'))
          .width(25)
      }
      .margin({ top: 10, left: 10, bottom: 10})
      .onClick(() => { //返回上一页
        router.back()
      })

      //遍历数组展示
      List({ space: 10}) {
        //遍历
        ForEach(this.arr, (item) => {
          ListItem() {
            Row() {
              Image(item.icon)
                .width(60)
                .height(60)
                .margin({ right: 15})
              Column() {
                Text(item.name)
                  .fontSize(15)
                  .fontWeight(500)
                Text(item.consume + '卡路里/' + item.pre)
                  .fontSize(10)
                  .fontWeight(600)
                  .opacity(0.7)
              }
              .alignItems(HorizontalAlign.Start) //交叉轴方向左对齐
              Blank()
              Button() {
                Image($r('app.media.add_norm_filled'))
                  .width(20)
              }
              .backgroundColor(Color.Transparent)  //透明背景
              .onClick(() => {

              })
            }
            .width('100%')
            .justifyContent(FlexAlign.SpaceBetween) //主轴方向对齐方式
          }
          .width('95%')
          .backgroundColor(Color.White)
          .padding(5)
        })
      }
      .width('100%')
      .alignListItem(ListItemAlign.Center)
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.light_gray'))
    .alignItems(HorizontalAlign.Start)
  }
}

  • 制作添加任务弹窗

  • 在dialog文件夹中创建TaskAddDialog.ets添加任务弹窗
     

  • 该部分现阶段TaskAddDialog.ets代码
//添加任务弹窗

import DateUtil from '../utils/DateUtil'

//封装,设置专属GridItem样式
@Extend(GridItem) function btnStyle() {
  .backgroundColor(Color.White)
  .opacity(0.7)
  .height(50)
  .borderRadius(15)
}

@Preview
@CustomDialog
export default struct TaskAddDialog {

  //从全局内取出日期
  @StorageProp('date') date: number = DateUtil.beginTimeOfDay(new Date())

  //弹窗弹出时小键盘就会存在
  @State show: boolean = true

  //创建一个字符串类型数组填入小键盘
  numberArr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']

  controller: CustomDialogController

  //创建一个自定义组件
  @Builder
  saveBtn(text: string, color: ResourceStr, onClick: () => void) {
    Button() {
      Text(text)
        .fontSize(20)
        .fontWeight(800)
        .opacity(0.9)
    }
    .width(80)
    .height(50)
    .type(ButtonType.Normal)
    .backgroundColor(color)
    .borderRadius(5)
    .padding({ left: 3, right: 3 })
    .onClick(onClick)
  }

  build() {
    Column() {
      Row() {
        //左上角日期
        Text(DateUtil.formatDate(this.date)) //从全局内取日期
          .fontSize(15)
          .fontWeight(600)
        Blank(10)
        //右上角按钮
        Button() {
          Text('x')
            .fontSize(15)
            .fontColor(Color.White)
            .fontWeight(800)
        }
        .width(20)
        .height(20)
        .backgroundColor(Color.Red)
        .padding({ bottom: 5 })
        .onClick(() => {
          this.controller.close()
        })
      }
      .width('95%')
      .justifyContent(FlexAlign.End)

      //运动任务图标
      Column({ space: 10 }) {
        Image($r('app.media.swim'))
          .width(90)
          .height(90)
        Text('游泳')
          .fontSize(20)
          .fontWeight(700)
          .backgroundColor($r('app.color.light_gray'))

        //目标任务量输入
        Row() {
          TextInput()
            .width('35%')
            .fontSize(35)
            .fontColor($r('app.color.task_color'))
            .caretColor(Color.Transparent)
            .textAlign(TextAlign.Center)
            .copyOption(CopyOptions.None)
          Text('/小时')
            .fontSize(35)
            .opacity(0.7)
            .fontWeight(800)
        }

        //Panel组件展示小键盘
        Panel(this.show) {
          Column() {
            //格栅容器Grid
            Grid() {
              //遍历小键盘数组
              ForEach(this.numberArr, (item) => {
                GridItem() {
                  Text(item)
                    .fontSize(20)
                    .fontWeight(500)
                }
                .btnStyle()     //专属GridItem样式
                .onClick(() => {

                })
              })
              GridItem() {
                Text('删除')
                  .fontSize(20)
                  .fontWeight(500)
              }
              .btnStyle()
              .onClick(() => {

              })

              GridItem() {
                this.saveBtn('确定', $r('app.color.btn_color'), () => this.show = false) //改变show的状态,可以使Panel组件消失掉
              }
              .columnStart(1)  //开始在第一行
              .columnEnd(3)    //结束在第三行
              .btnStyle()
            }
            .columnsTemplate('1fr 1fr 1fr')  //三列,每一列占据一样的宽度
            .columnsGap(5)
            .rowsGap(8)
            .width('95%')
            .padding({ top: 15 })
          }
        }
        .mode(PanelMode.Half) //展示占据一半
        .halfHeight(1050)
        .type(PanelType.Temporary)
        .dragBar(false)
        .width('100%')
      }
    }
    .width('95%')
    .height('95%')
    .alignItems(HorizontalAlign.Center)
  }
}

  •  遇到的问题

在运行该项目测试添加任务按钮是否能够跳转界面时,并未发生跳转,原因是在

.onClick(() => this.clickAction())

clickAction后面未加(),不能执行该函数的内容。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值