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

news2024/11/24 7:56:49

文章目录

    • 一、目标
    • 二、基础搭建
      • 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布局
  • 题目切换处理
  • 做题标记及高亮展示

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Laravel框架使用图片处理简单教程

PHP图片处理扩展包使用 文中使用的是Laravel框架&#xff0c;更多框架扩展包请点击传送门-》更多框架集成 Intervention Image 是一个开源的 PHP 图像处理和操作 库。它提供了一个更简单也更优雅的方式来创建/编辑/组合图像,并且支持最常见的两个图像处理库 GD Library 和 Im…

经验之谈——正确选择矿用旋转式孔板流量计

说到孔板流量计大家除了想到矿用旋转式孔板流量计是不是还会想到价格&#xff1f;我们举个例子&#xff1a; 10块钱的停车费你觉得贵 于是抱着侥幸心理停路边 突然一张200的罚单贴车上 你才悔不当初 早知道给100停车费也愿意 当你真正需要质量和保障的时候 多高的价格你都不嫌…

软件FMEA的时机:架构设计、详设阶段——FMEA软件

免费试用FMEA软件-免费版-SunFMEA 软件FMEA&#xff08;故障模式与影响分析&#xff09;是一种预防性的质量工具&#xff0c;旨在识别软件中可能存在的故障模式&#xff0c;并分析其对系统性能、安全性和可靠性的影响。在软件开发生命周期中&#xff0c;选择适当的时机进行FME…

【C语言】动态分配内存

内存的五大分区 1、堆区&#xff08;heap&#xff09;——由程序员分配和释放&#xff0c; 若程序员不释放&#xff0c;程序结束时一般由操作系统回收。注意它与数据结构中的堆是两回事 2、栈区&#xff08;stack&#xff09;——由编译器自动分配释放 &#xff0c;存放函数的…

CST电磁仿真软件远场源的导出调用和提取结果【小白必看】

远场源的导出&调用(1) 提取Hybrid仿真所需的远场源&#xff01; Post-Processing > Tools > Result Templates Tools >Farfield and Antenna Properties > Export Farfields As Source 混合求解(Hybrid Simulation)是对安装在舰船等大型平台上的天线进行仿真…

【docker】常用的Docker编排和调度平台

常用的Docker编排和调度平台 Kubernetes (K8s): Kubernetes是目前市场上最流行和功能最全面的容器编排和调度平台。它由Google开发并开源&#xff0c;现由CNCF&#xff08;云原生计算基金会&#xff09;维护。Kubernetes设计用于自动化容器部署、扩展和管理&#xff0c;支持跨…

EPSON的温补晶振TG7050SKN

EPSON公司推出的温补品振(TCXO)TG7050SKN&#xff0c;尺寸大小为7.0x5.0x1.5 mm&#xff0c;具有高稳定性(105℃℃高温)等特点&#xff0c;可输出10MHz~54MHz的频率可应用在网络同步&#xff0c;BTS&#xff0c;微波&#xff0c;以及需要符合Stratum3、SyncE和IEEE1588等规范的…

张大哥笔记:商标也可以赚大钱

一大早看群聊&#xff0c;发现群里几个小伙伴在讨论商标转让的事情&#xff0c;我一时兴起&#xff0c;就想知道怎么通过商标来赚钱呢&#xff1f;不查不知道&#xff0c;原来还可以这样用商标赚大钱&#xff01; 下面我给大家掰扯一下&#xff0c;首先我们来了解一下什么是商标…

LeetCode面试298,二叉树最长连续序列(Python)

开始想着dfs&#xff0c;两种情况 1.以root为根 2.不以root为根 但是这样需要两个dfs分别进行&#xff0c;那么时间复杂度就上去了。 class Solution:def longestConsecutive(self, root: Optional[TreeNode]) -> int:def dfs(root):# 以root为根节点&#xff0c;可以延…

递归与递推---题目练习

目录 1、递归实现指数型枚举 2、递归实现排列型枚举 3、递归实现组合型枚举 4、带分数 方法一 方法二 5、翻硬币 6、飞行员兄弟 7、费解的开关 递归是指在函数的定义中使用函数自身的方法。它通过不断地将问题分解为更小的子问题&#xff0c;直到达到基本情况&#xf…

【Gaea+UE5】创建基本的大型世界场景

目录 效果 步骤 一、在Gaea中生成地形 二、确定导出的地形规模 三、在UE中创建地形 四、验证UE创建的地形规模是否正确 五、使用M4自动地形材质 效果 步骤 一、在Gaea中生成地形 1. 打开Gaea官网下载软件 2. 打开Gaea软件&#xff0c;我们可以选择一个预设的山体 创…

机器学习——4.案例: 简单线性回归求解

案例目的 寻找一个良好的函数表达式,该函数表达式能够很好的描述上面数据点的分布&#xff0c;即对上面数据点进行拟合。 求解逻辑步骤 使用Sklearn生成数据集定义线性模型定义损失函数定义优化器定义模型训练方法&#xff08;正向传播、计算损失、反向传播、梯度清空&#…

Implicit Diffusion Models for Continuous Super-Resolution

CVPR2023https://github.com/Ree1s/IDM问题引入&#xff1a; – LIIF方法可以实现任意分辨率的输出&#xff0c;但是因为是regression-based方法&#xff0c;所以得到的结果缺少细节&#xff0c;而生成的方法(gan-based,flow-based&#xff0c;diffusion-based等)可以生成细节&…

JavaScript中的RegExp和Cookie

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f506;RegExp &#x1f3b2; 1 什么是正则表达式 &#x1f3b2;2 创建…

从招标到合作:如何筛选与企业需求匹配的6sigma咨询公司

在市场竞争激烈的环境中&#xff0c;领军企业需要不断改进和创新才能在行业中保持竞争优势。为了解决产品质量、生产流程和客户满意度等方面的挑战&#xff0c;许多企业选择与6sigma咨询公司合作&#xff0c;推动企业的全面变革和持续发展。下面是企业在选择合作伙伴时通常会经…

一、Redis五种常用数据类型

Redis优势&#xff1a; 1、性能高—基于内存实现数据的存储 2、丰富的数据类型 5种常用&#xff0c;3种高级 3、原子—redis的所有单个操作都是原子性&#xff0c;即要么成功&#xff0c;要么失败。其多个操作也支持采用事务的方式实现原子性。 Redis特点&#xff1a; 1、支持…

Golang日志实战教程:掌握log与syslog库的高效使用

Golang日志实战教程&#xff1a;掌握log与syslog库的高效使用 简介理解 Golang 的 log 库基本概念创建日志记录器自定义日志记录器日志级别 深入 syslogsyslog 的基础配置和使用 syslog高级应用 日志格式化与管理日志格式化日志文件管理 日志的高级应用集成第三方日志框架使用 …

Python程序中温度更新出现振荡问题的分析和解决方案

在处理温度更新出现振荡问题时&#xff0c;可以考虑以下分析和解决方案&#xff1a;检查温度更新算法是否正确&#xff0c;可能存在错误导致振荡。检查温度更新的步长&#xff08;时间步长&#xff09;是否合适&#xff0c;步长过大可能导致振荡。检查系统动力学模型是否准确&a…

场外个股期权和场内个股期权的优缺点是什么?

场外个股期权和场内个股期权的优缺点 场外个股期权是指在沪深交易所之外交易的个股期权&#xff0c;其本质是一种金融衍生品&#xff0c;允许投资者在股票交易场所外以特定价格买进或卖出证券。场内个股期权是以单只股票作为标的资产的期权合约&#xff0c;其内在价值是基于标…

如何用Kimi,5秒1步生成流程图

引言 在当前快节奏的工作环境中&#xff0c;拥有快速、专业且高效的工具不可或缺。 Kimi不仅能在5秒内生成专业的流程图&#xff08;kimi&#xff09;&#xff0c;还允许实时编辑和预览&#xff0c;大幅简化了传统流程图的制作过程。 这种迅速的生成能力和高度的可定制性使得…