HarmonyOS NEXT星河版之在线考试功能实战

文章目录

    • 一、目标
    • 二、基础搭建
      • 2.1 定义数据
      • 2.2 mock数据
      • 2.3 主页面布局
        • 2.3.1 布局规划
        • 2.3.2 标题栏
        • 2.3.3 进度条
        • 2.3.4 答题模块
        • 2.3.5 底部按钮
      • 2.4 主页面逻辑
        • 2.4.1 加载数据及定义变量
        • 2.4.2 上一题、下一题
    • 三、选项点击及高亮
      • 3.1 声明对象及变量
      • 3.2 给选项注册点击事件
      • 3.3 处理背景和文本颜色
    • 四、小结

一、目标

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、基础搭建

2.1 定义数据

// 题目
export interface ExamItem {
  id: number
  title: string
  options: OptionItem[]
}
// 答案
export interface OptionItem {
  letter: string
  content: string
}

2.2 mock数据

export const mockExamDataList: ExamItem[] = [
  {
    id: 1,
    title: 'Android系统的构建系统叫什么名字?',
    options: [
      { letter: 'A', content: 'Gradle' },
      { letter: 'B', content: 'Maven' },
      { letter: 'C', content: 'Ant' },
      { letter: 'D', content: 'Make' },
    ],
  },
  {
    id: 2,
    title: '以下哪个组件不是Android架构的一部分?',
    options: [
      { letter: 'A', content: 'Activity(活动)' },
      { letter: 'B', content: 'Service(服务)' },
      { letter: 'C', content: 'Content Provider(内容提供者)' },
      { letter: 'D', content: 'Fragment(片段)' },
    ],
  },
  {
    id: 3,
    title: 'Android中的RecyclerView控件有什么用途?',
    options: [
      { letter: 'A', content: '显示一个可滚动的元素列表' },
      { letter: 'B', content: '在不同活动之间导航' },
      { letter: 'C', content: '播放视频内容' },
      { letter: 'D', content: '绘制自定义的形状和路径' },
    ],
  },
];

2.3 主页面布局

2.3.1 布局规划

将主页面布局抽取,封装对应如下:
在这里插入图片描述

2.3.2 标题栏
@Builder
getTitleBar() {
  Stack({ alignContent: Alignment.Start }) {
    Image($r('app.media.ic_left_arrow'))
      .width(24)
    Text('在线考试')
      .width('100%')
      .textAlign(TextAlign.Center)
  }
  .padding({ left: 12, right: 12 })
  .width('100%')
  .height(52)
  .backgroundColor(Color.White)
  .borderWidth({
    bottom: 0.5
  })
  .borderColor('#e5e5e5')
}
2.3.3 进度条
@Builder
getProgressView() {
  Row() {
    Progress({ value: this.currentIndex + 1, total: this.questionList.length })
      .padding({ left: 12, right: 12 })
    Text() {
      Span(`${this.currentIndex + 1}`)
        .fontColor(Color.Black)
      Span('/' + this.questionList.length)
        .fontColor(Color.Gray)
    }
    .layoutWeight(1)
  }
  .width('100%')
}
2.3.4 答题模块
Column() {
  Column({ space: 5 }) {
    Text(this.currentQuestion.title)
      .margin({ bottom: 6, top: 12 })
    ForEach(this.currentQuestion.options, (item: OptionItem) => {
      Row() {
        Text(item.letter + '. ')
        Text(item.content)
      }
      .width('100%')
      .height(40)
      .padding({ left: 12 })
      .backgroundColor('#F9F9F9')
    })
  }
  .alignItems(HorizontalAlign.Start)
  .width('100%')
  .padding({ left: 15, right: 15 })

}.layoutWeight(1)
2.3.5 底部按钮
@Builder
getBottomView() {
  Row() {
    Row({ space: 3 }) {
      Image($r('app.media.ic_arrow_left'))
        .width(15)
        .fillColor(this.getPreEnable() ? Color.Black : '#BABABA')
      Text('上一题')
        .fontColor(this.getPreEnable() ? Color.Black : '#BABABA')
    }
    .onClick(() => {
      this.onPreClick()
    })

    Row({ space: 3 }) {
      Text('下一题')
        .fontColor(this.getNextEnable() ? Color.Black : '#BABABA')
      Image($r('app.media.ic_arrow_right'))
        .width(15)
        .fillColor(this.getNextEnable() ? Color.Black : '#BABABA')
    }
    .onClick(() => {
      this.onNextClick()
    })
  }
  .width('100%')
  .justifyContent(FlexAlign.SpaceBetween)
  .backgroundColor(Color.White)
  .height(50)
  .padding({
    left: 12, right: 12
  })
  .border({
    color: '#e5e5e5',
    width: { top: 1 }
  })
}

2.4 主页面逻辑

2.4.1 加载数据及定义变量
// 题目列表
  @State questionList: ExamItem[] = []
  // 当前显示第N题
  @State currentIndex: number = 0
  // 当前题目
  @State currentQuestion: ExamItem = {} as ExamItem

  aboutToAppear(): void {
    this.loadData()
  }

  async loadData() {
    // 模拟网络获取数据
    this.questionList = await new Promise<ExamItem[]>((resolve, reject) => {
      setTimeout(() => {
        resolve(mockExamDataList)
      }, 500)
    });
    // 默认展示第一条
    this.currentQuestion = this.questionList[this.currentIndex]
  }
2.4.2 上一题、下一题
onPreClick() {
  if (this.getPreEnable()) {
    this.currentIndex--
    this.currentQuestion = this.questionList[this.currentIndex]
  }
}

onNextClick() {
  if (this.getNextEnable()) {
    this.currentIndex++
    this.currentQuestion = this.questionList[this.currentIndex]
  }
}

getPreEnable() {
  return this.currentIndex > 0
}

getNextEnable() {
  return this.currentIndex < this.questionList.length - 1
}

三、选项点击及高亮

3.1 声明对象及变量

export interface UserAnswer {
  questionId: number // 问题ID
  userAnswer: string // 用户选择项
}

在主页面中,定义变量,存储用户做题数据,如下:

// 存储题目和用户答案
@State userAnswerList: Record<number, UserAnswer> = {}

3.2 给选项注册点击事件

ForEach(this.currentQuestion.options, (item: OptionItem) => {
   Row() {
     Text(item.letter + '. ')
     Text(item.content)
   }
   .width('100%')
   .height(40)
   .padding({ left: 12 })
   .onClick(() => {
     this.onUserAnswerClick(item)
   })
 })

处理点击事件:

onUserAnswerClick(option: OptionItem) {
   this.userAnswerList[this.currentQuestion.id] = {
     questionId: this.currentQuestion.id,
     userAnswer: option.letter
   }
 }

3.3 处理背景和文本颜色

Row() {
  Text(item.letter + '. ')
    .fontColor(this.getOptionColor(item, 'font'))
  Text(item.content)
    .fontColor(this.getOptionColor(item, 'font'))
}
...
.backgroundColor(this.getOptionColor(item))
/**
   * 获取选择项背景或文本颜色
   * @param option 当前选择项
   * @param type 类型
   * @returns
   */
getOptionColor(option: OptionItem, type: 'back' | 'font' = 'back') {
  if (this.currentQuestion) {
    const userAnswer = this.userAnswerList[this.currentQuestion.id]
    if (userAnswer?.userAnswer === option.letter) {
      return type === 'back' ? Color.Pink : Color.White
    }
  }
  return type === 'back' ? '#e5e5e5' : Color.Black
}

四、小结

  • UI布局
  • 题目切换处理
  • 做题标记及高亮展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/597659.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI图书推荐:Zapier和AI融合来自动化业务流程

这本书《Zapier和AI融合来自动化业务流程》&#xff08;Automate It with Zapier and Generative AI&#xff09;由Kelly Goss撰写&#xff0c;这本书是为想要使用Zapier和AI集成功能来自动化重复性任务、提高生产力的微型、小型或中型企业的业务所有者、运营经理和团队准备的。…

C++入门基础(四)

目录 auto关键字(C11)类型别名思考auto的使用细则auto与指针和引用结合起来使用在同一行定义多个变量 auto不能推导的场景auto不能作为函数的参数auto不能直接用来声明数组 复杂场景下的auto 基于范围的for循环(C11)范围for的语法范围for的使用条件 指针空值---nullptr(C11)C98…

电商核心技术揭秘四十九:智能广告投放与效果评估

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…

饥荒服务器搭建centos

服务器环境需要64位32位不可用 uname -r 查看服务器版本 更新yum sudo yum update 安装依赖环境 sudo yum -y install glibc.i686 libstdc.i686 libcurl4-gnutls-dev.i686 libcurl.i686 screen 安装steam cd /home && mkdir steamcmd && cd steamcmd 国…

【typescript测试 - Jest 配置与使用】

安装 npm install --save-dev types/jestnpm install --save-dev ts-jest配置 tsconfig.json {"compilerOptions": {"types": ["jest"]} }jest.config.js module.exports {preset: ts-jest,testEnvironment: node, };使用 // add.js funct…

越权漏洞!

越权漏洞是指在一个系统或应用程序中存在某种不当的访问权限&#xff0c;使得攻击者可以获得比其应该拥有的权限更高的权限。这种漏洞可能允许攻击者执行未经授权的操作&#xff0c;例如访问他人的敏感数据、修改系统设置、执行恶意代码等。越权漏洞通常是由于设计或实现上的错…

HarmonyOS NEXT星河版之模拟图片选择器(下)---使用bindSheet展示图片选择器

文章目录 一、目标二、开撸2.1 bindSheet参数2.2 使用Builder修饰组件2.3 调用bindSheet 三、小结 一、目标 使用bindSheet属性实现图片选择器&#xff0c;如图&#xff1a; 二、开撸 2.1 bindSheet参数 bindSheet接收三个参数&#xff0c;如下&#xff1a; bindSheet(is…

精准读取CSV/Excel数据 - 灵活指定行列范围的 Python 解决方案

文章目录 源代码项目简介导入相关库__file_exists 装饰器函数的签名和注释主要功能的实现运行演示读取 Excel 文件 源代码 https://github.com/ma0513207162/PyPrecip。pyprecip\reading\read_api.py 路径下。 项目简介 PyPrecip 是一个专注于气候数据处理的 Python 库&#xf…

【C++ 关键字】const 关键字详解

文章目录 1. const 概念2.常量指针 和 指针常量 的区别2.1 常量指针&#xff08;底层 const&#xff09;2.2 指针常量 (顶层 const) 3.const 关键字的作用4.const 和 define 的区别5.const 总结 1. const 概念 const 是一个关键字&#xff0c;被修饰的值不能改变&#xff0c;是…

请求转发和响应重定向

文章目录 一、 概述二、 请求转发三、响应重定向参考资料 一、 概述 什么是请求转发和响应重定向 请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段 请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现…

大模型模型简化机器人训练;简单易用的 3D 工具Project Neo;特斯拉放出了擎天柱机器人最新训练视频

✨ 1: DrEureka 利用大语言模型自动化将机器人仿真环境训练结果转移到真实世界 DrEureka是一种利用大型语言模型&#xff08;LLMs&#xff09;自动化和加速从仿真&#xff08;sim&#xff09;到现实世界&#xff08;real&#xff09;转移的技术。在机器人技能学习领域&#x…

Gradle基础学习(六) 认识任务Task

理解Gradle中的任务 Gradle的构建过程基于任务&#xff08;Task&#xff09;的概念&#xff0c;而每个任务都可以包含一个或多个动作&#xff08;Action&#xff09;。 任务是构建中执行的一些独立的工作单元&#xff0c;例如编译类、创建JAR、生成Javadoc或将存档发布到仓库…

62-USB转JTAG or SPI电路设计

视频链接 USB转JTAG or SPI电路设计01_哔哩哔哩_bilibili USB 转 JTAG or SPI电路设计 第07课---USB转串口电路设计第 34&#xff5e;40课---USB硬件电路设计 第22课---SPI Flash电路设计 第31课---JTAG电路设计&#xff08;JLINK&XILINX&ALTERA&#xff09; 第…

代码随想录-算法训练营day31【贪心算法01:理论基础、分发饼干、摆动序列、最大子序和】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第八章 贪心算法 part01● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和 贪心算法其实就是没有什么规律可言&#xff0c;所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其…

5.Git

Git是一个分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码文件&#xff08;Java类、xml文件、html文件等&#xff09;。通过Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种 本地仓库&#xff1a;开发人员自己电脑上的Git仓库远程仓库&#xff1a;远程…

360手机去除广告 360手机关闭弹窗广告 360手机刷机

360手机去除广告 360手机关闭弹窗广告 360手机刷机 360手机去广告 360手机刷机 360手机弹窗广告 永久去除360手机的各种广告教程 360手机禁止更新 360手机关闭广告 360手机去除内部广告 360手机资源网 360手机刷机资源下载链接&#xff1a;360rom.github.io 参考&#xff1a;…

如何高效封装App?小猪APP分发平台一站式解决方案

在移动应用开发领域&#xff0c;App封装&#xff08;App Packaging&#xff09;是一个至关重要的环节&#xff0c;它不仅关乎应用的安全性&#xff0c;还直接影响到最终用户体验和市场推广策略。本文旨在通过实战指南&#xff0c;揭示如何高效完成App封装&#xff0c;并介绍如何…

【图书推荐】《图神经网络基础、模型与应用实战》

本书目的 详解PyTorch 图神经网络基础理论、模型与十多个应用案例&#xff0c;带领读者掌握图神经网络在自然语言处理、计算机视觉、推荐系统、社交网络4个领域的应用开发方法&#xff0c;丰富读者利用深度学习算法解决实际问题的能力。 本书案例 图卷积网络实现图注意力网络…

Python量化炒股的统计数据图

Python量化炒股的统计数据图 单只股票的收益统计图 查看单只股票的收盘价信息 单击聚宽JoinQuant量化炒股平台中的“策略研究/研究环境”命令&#xff0c;进入Jupyter Notebook的研究平台。然后单击“新建”按钮&#xff0c;创建Python3文件&#xff0c;输入如下代码如下&am…

知到java笔记(4.1--继承的用法以及this和super的用法)

格式&#xff1a; 例子&#xff1a; get set获取父类的私有变量 private属性 this和super区别&#xff1a; this用法 super用法 例子