当前位置: 首页 > news >正文

鸿蒙 OS 开发单词打卡 APP 项目实战 20240922 笔记和源码分享

配套有完整的录播课, 需要的私信.
在这里插入图片描述

零基础入门级别, 有点前端基础都能学会.

效果截图:
在这里插入图片描述

代码截图:
在这里插入图片描述

页面完整代码:

import { AnswerStatus } from '../enums/AnswerStatus'
import { PracticeStatus } from '../enums/PracticeStatus'
import { getRandomQuestions, Question } from '../model/Question'
import { promptAction } from '@kit.ArkUI'
import { OptionButton } from '../components/OptionButton'
import { StatItem } from '../components/StatItem'
import { ResultDialog } from '../components/ResultDialog'
import { trustedAppService } from '@kit.DeviceSecurityKit'@Entry
@Component
struct PracticePage {// 练习状态@State status: PracticeStatus = PracticeStatus.STOPPED// 题目个数@State totalQuestion: number = 3// 题目数组@State questions: Question[] = getRandomQuestions(this.totalQuestion)// 当前题目的索引@State currentIndex: number = 0// 用户选中的选项@State selectedOption: string = ""// 作答状态@State answerStatus: AnswerStatus = AnswerStatus.Answering// 已作答个数@State answeredCount: number = 0// 答对的个数@State rightCount: number = 0// 控制定时器timerController = new TextTimerController()// 总用时时间@State totalTime: number = 0// 自定义的弹窗组件控制器dialogController: CustomDialogController = new CustomDialogController({builder: ResultDialog({answeredCount: this.answeredCount,rightCount: this.rightCount,totalTime: this.totalTime,onStartFunc: () => {this.status = PracticeStatus.RUNNINGthis.timerController.start()},onCloseFunc: () => {this.questions = getRandomQuestions(this.totalQuestion)this.currentIndex = 0this.answeredCount = 0this.rightCount = 0this.totalTime = 0this.timerController.reset()this.answerStatus = AnswerStatus.Answeringthis.status = PracticeStatus.STOPPED},}),customStyle: true, // 使用自定义样式, 否则那个 x 出不来autoCancel: false, // 点击空白区域不会被自动关闭})// 统计准确率getRightPercent() {if (this.rightCount === 0) {return "0%"}return `${((this.rightCount / this.answeredCount) * 100).toFixed()}%`}// 停止练习stopPractice() {this.status = PracticeStatus.STOPPEDthis.timerController.pause()this.dialogController.open()}build() {Column() {// 统计面板Column() {// 准确率StatItem({icon: $r("app.media.ic_accuracy"),name: "准确率",fontColor: Color.Black,}) {Text(this.getRightPercent()).width(100).textAlign(TextAlign.Center)}// 进度StatItem({icon: $r("app.media.ic_progress"),name: "进度",fontColor: Color.Black,}) {Progress({ value: this.answeredCount, total: this.totalQuestion }).width(100)}// 题目个数StatItem({icon: $r("app.media.ic_count"),name: "个数",fontColor: Color.Black,}) {Button(this.totalQuestion.toString()).width(100).height(25).backgroundColor("#EBEBEB").enabled(this.status === PracticeStatus.STOPPED).onClick(() => {TextPickerDialog.show({range: ["5", "10", "20", "50", "100"],value: this.totalQuestion.toString(), // 默认值onAccept: (result) => {this.totalQuestion = parseInt(result.value.toString())this.questions = getRandomQuestions(this.totalQuestion)}})})}// 计时StatItem({icon: $r("app.media.ic_timer"),name: "用时",fontColor: Color.Black,}) {Row() {TextTimer({ controller: this.timerController }).onTimer((utc, elapsedTime) => {this.totalTime = elapsedTime})}.width(100).justifyContent(FlexAlign.Center)}}.statBgStyle()// 题目Column() {Text(this.questions[this.currentIndex].word).wordStyle()Text(this.questions[this.currentIndex].sentence).sentenceStyle()}// 选项Column({ space: 15 }) {ForEach(this.questions[this.currentIndex].options,(item: string) => {OptionButton({option: item,answer: this.questions[this.currentIndex].answer,selectedOption: this.selectedOption,answerStatus: this.answerStatus,}).enabled(this.answerStatus === AnswerStatus.Answering).onClick(() => {// 判断练习状态if (this.status !== PracticeStatus.RUNNING) {promptAction.showToast({ message: "请先点击开始测试按钮" })return}// 先将答题状态改为已作答this.answerStatus = AnswerStatus.Answered// 判断答案是否正确this.selectedOption = itemthis.answeredCount++if (this.questions[this.currentIndex].answer === this.selectedOption) {this.rightCount++}// 判断题目状态if (this.currentIndex < this.questions.length - 1) {setTimeout(() => {this.currentIndex++this.answerStatus = AnswerStatus.Answering}, 500)} else {// 停止测试this.stopPractice()}})},(item: string) => this.questions[this.currentIndex].word + "_" + item,)}// 控制按钮Row({ space: 20 }) {Button("停止测试").controlButtonStyle(Color.Transparent,this.status === PracticeStatus.STOPPED ? Color.Gray : Color.Black,this.status === PracticeStatus.STOPPED ? Color.Gray : Color.Black,).enabled(this.status !== PracticeStatus.STOPPED).onClick(() => this.stopPractice())Button(this.status === PracticeStatus.RUNNING ? "暂停测试" : "开始测试").controlButtonStyle(this.status === PracticeStatus.RUNNING ? "#666666" : Color.Black,this.status === PracticeStatus.RUNNING ? "#666666" : Color.Black,Color.White,).stateEffect(false).onClick(() => {if (this.status === PracticeStatus.RUNNING) {// 暂停测试this.status = PracticeStatus.PAUSEDthis.timerController.pause()} else {// 开始测试this.status = PracticeStatus.RUNNINGthis.timerController.start()}})}}.practiceBgStyle()}
}// 页面背景
@Extend(Column)
function practiceBgStyle() {.width("100%").height("100%").backgroundImage($r("app.media.img_practice_bg")).backgroundImageSize({ width: "100%", height: "100%" }).justifyContent(FlexAlign.SpaceEvenly)
}// 统计面板背景
@Styles
function statBgStyle() {.backgroundColor(Color.White).width("90%").borderRadius(10).padding(20)
}// 单词样式
@Extend(Text)
function wordStyle() {.fontSize(50).fontWeight(FontWeight.Bold)
}// 例句样式
@Extend(Text)
function sentenceStyle() {.height(40).fontSize(16).fontColor("#9BA1A5").fontWeight(FontWeight.Medium).width("80%").textAlign(TextAlign.Center)
}// 控制按钮样式
@Extend(Button)
function controlButtonStyle(bgColor: ResourceColor,borderColor: ResourceColor,fontColor: ResourceColor,
) {.fontSize(16).borderWidth(1).backgroundColor(bgColor).borderColor(borderColor).fontColor(fontColor)
}

选项按钮组件完整代码:

import { AnswerStatus } from '../enums/AnswerStatus'
import { OptionStatus } from '../enums/OptionStatus'@Component
export struct OptionButton {// 选项内容option: string = ""// 答案answer: string = ""// 选项状态@State optionStatus: OptionStatus = OptionStatus.DEFAULT// 用户选中的选项@Prop selectedOption: string = ""// 属性@Prop @Watch("onAnswerStatusChange") answerStatus: AnswerStatus = AnswerStatus.Answering// 监听器方法onAnswerStatusChange() {if (this.option === this.answer) {// 答案正确this.optionStatus = OptionStatus.RIGHT} else {if (this.option === this.selectedOption) {// 如果当前选项按钮是被选中但错误的按钮this.optionStatus = OptionStatus.ERROR} else {this.optionStatus = OptionStatus.DEFAULT}}}// 获取背景颜色getBgColor() {switch (this.optionStatus) {case OptionStatus.RIGHT:return "#1DBF7B"case OptionStatus.ERROR:return "#FA635F"default:return Color.White}}build() {Stack() {Button(this.option).optionButtonStyle(this.getBgColor(), // 动态获取背景颜色this.optionStatus === OptionStatus.DEFAULT ? Color.Black : Color.White,)// 根据状态设置不同的图标if (this.optionStatus === OptionStatus.RIGHT) {Image($r("app.media.ic_right")).width(22).height(22).offset({ x: 10 })} else if (this.optionStatus === OptionStatus.ERROR) {Image($r("app.media.ic_wrong")).width(22).height(22).offset({ x: 10 })}}.alignContent(Alignment.Start)}
}// 选项按钮样式
@Extend(Button)
function optionButtonStyle(bgColor: ResourceColor, fontColor: ResourceColor) {.width(240).height(48).fontSize(16).type(ButtonType.Normal).fontWeight(FontWeight.Medium).borderRadius(8).backgroundColor(bgColor).fontColor(fontColor)
}

弹窗组件完整代码:

import { millisecondsToTimeStr } from '../utils/DateUtil'
import { StatItem } from './StatItem'@CustomDialog
export struct ResultDialog {answeredCount: number = 0 // 已答题个数rightCount: number = 0 // 正确个数totalTime: number = 0 // 总计耗时// 再来一局开始执行的函数onStartFunc: () => void = () => {}// 在关闭弹窗时触发方法onCloseFunc: () => void = () => {}// 弹窗控制器controller: CustomDialogController = new CustomDialogController({builder: ResultDialog()})// 统计准确率getRightPercent() {if (this.rightCount === 0) {return "0%"}return `${((this.rightCount / this.answeredCount) * 100).toFixed()}%`}build() {Column({ space: 10 }) {// 右上角有个 X 的按钮Image($r("app.media.ic_close")).width(25).height(25).alignSelf(ItemAlign.End).onClick(() => {this.controller.close() // 关闭弹窗this.onCloseFunc() // 触发关闭的函数})// 主体内容Column({ space: 10 }) {// 图片Image($r("app.media.img_post")).width("100%").borderRadius(10)// 用时StatItem({icon: $r("app.media.ic_timer"),name: "用时",fontColor: Color.Black}) {Text(millisecondsToTimeStr(this.totalTime))}// 准确率StatItem({icon: $r("app.media.ic_accuracy"),name: "准确率",fontColor: Color.Black}) {Text(this.getRightPercent())}// 个数StatItem({icon: $r("app.media.ic_count"),name: "个数",fontColor: Color.Black}) {Text(this.answeredCount.toString())}// 分割线Divider()// 控制按钮Row({ space: 30 }) {Button("再来一局").controlButtonStyle(Color.Transparent,Color.Black,Color.Black,).onClick(() => {this.controller.close()this.onCloseFunc() // 先关闭this.onStartFunc() // 再启动})Button("登录打卡").controlButtonStyle(Color.Black,Color.Black,Color.White,).onClick(() => {this.controller.close()this.onCloseFunc() // 先关闭// TODO: 登录并打卡})}}.backgroundColor(Color.White).width("100%").padding(20).borderRadius(10)}.backgroundColor(Color.Transparent).width("80%")}
}// 控制按钮样式
@Extend(Button)
function controlButtonStyle(bgColor: ResourceColor,borderColor: ResourceColor,fontColor: ResourceColor,
) {.fontSize(16).borderWidth(1).backgroundColor(bgColor).borderColor(borderColor).fontColor(fontColor)
}

代码比较多, 需要整套完整代码的可以私信我获取.

相关文章:

鸿蒙 OS 开发单词打卡 APP 项目实战 20240922 笔记和源码分享

配套有完整的录播课, 需要的私信. 零基础入门级别, 有点前端基础都能学会. 效果截图: 代码截图: 页面完整代码: import { AnswerStatus } from ../enums/AnswerStatus import { PracticeStatus } from ../enums/PracticeStatus import { getRandomQuestions, Question …...

力扣P1706全排列问题 很好的引入暴力 递归 回溯 dfs

代码思路是受一个洛谷题解里面大佬的启发。应该算是一个dfs和回溯的入门题目&#xff0c;很好的入门题目了下面我会先给我原题解思路我想可以很快了解这个思路。下面是我自己根据力扣大佬写的。 我会进行详细讲解并配上图辅助理解大家请往下看 #include<iostream> #inc…...

使用Python Pandas导入数据库和文件数据

大家好&#xff0c;在数据分析过程中&#xff0c;数据的导入是第一步&#xff0c;也是最重要的一步。Python的Pandas提供了强大的数据读取功能&#xff0c;支持从多种数据源导入数据&#xff0c;包括CSV、Excel、JSON、SQL数据库、网页等。Pandas库不仅能够处理常见的文件格式&…...

lef 中antenna解释

这些规则主要涉及集成电路设计中的天线效应(Antenna Effect)和通孔(Via)设计规则。 ANTENNAAREADIFFREDUCEPWL 这条规则指定了一个分段线性函数,用于根据连接到切割层的扩散区面积来计算cut_area的缩减因子。扩散区面积值应从0开始单调增加。如果没有定义此规则,PAR(mi)方程中的…...

初试Bootstrap前端框架

文章目录 一、Bootstrap概述二、Bootstrap实例1、创建网页2、编写代码3、代码说明4、浏览网页&#xff0c;查看结果5、登录按钮事件处理6、浏览网页&#xff0c;查看结果 三、实战小结 一、Bootstrap概述 大家好&#xff0c;今天我们将一起学习一个非常流行的前端框架——Boot…...

mysql数据库:超键、候选键、主键与外键

mysql数据库&#xff1a;超键、候选键、主键与外键 1、超键&#xff08;Superkey&#xff09;2、候选键&#xff08;Candidate Key&#xff09;3、主键&#xff08;Primary Key&#xff09;4、外键&#xff08;Foreign Key&#xff09; &#x1f496;The Begin&#x1f496;点点…...

音频转MP3格式困难?如何轻松实现wav转mp3?

格式多样化为我们带来了灵活性和创意的无限可能&#xff0c;但同时&#xff0c;不同格式间的转换也成为了不少用户面临的难题。尤其是当你手握珍贵的WAV音频文件&#xff0c;却希望它们能在更多设备上流畅播放或节省存储空间时&#xff0c;wav转mp3的需求便应运而生。WAV以其无…...

基于vue框架的大连盐业有限公司生产管理系统的设计与实现3hk5y(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;计划员,工艺员,生产建模,生产计划,生产信息,生产监视,工艺质量,盐政信息 开题报告内容 一、引言 随着信息技术的飞速发展和市场竞争的日益激烈&#xff0c;传统盐业企业如大连盐业有限公司正面临着转型升级的迫切需求。传统管理模式下…...

《深入理解JAVA虚拟机(第2版)》- 第13章 - 学习笔记【终章】

第13章 线程安全与锁优化 13.1 概述 面向过程的编程思想 将数据和过程独立分开&#xff0c;数据是问题空间中的客体&#xff0c;程序代码是用来处理数据的&#xff0c;这种站在计算机角度来抽象和解决问题的思维方式&#xff0c;称为面向对象的编程思想。 面向对象的编程思想…...

网络工程师学习笔记——网络互连与互联网(三)

TCP三次握手 建立TCP连接是通过三次握手实现的&#xff0c;采用三报文握手主要是为了防止已失效的连接请求报文突然又传送到了&#xff0c;因而产生错误 主动发起TCP连接建立的称为客户端 被动等待的为TCP服务器&#xff0c;二者之间需要交换三个TCP报文段 首先是客户端主动…...

【Tomcat】常见面试题整理 共34题

文章目录 1. 简述什么是Tomcat&#xff1f;2. Tomcat的缺省端口是多少&#xff0c;怎么修改&#xff1f;3. 简述Tomcat 目录结构及作用4. 简述Tomcat有几种部署方式&#xff1f;5. 简述Tomcat容器是如何创建servlet类实例&#xff1f;6. Tomcat有哪几种Connector运行模式&#…...

到时间没回家又不接电话?如何迅速确定孩子的位置?

当孩子未按时回家且无法通过电话联系时&#xff0c;家长往往会感到焦虑。此时&#xff0c;如何迅速确定孩子的位置成为许多家长迫切需要解决的问题。 利用智能手机定位技术是最常见的方法之一。大多数智能手机都内置GPS定位功能&#xff0c;通过“查找设备”应用&#xff0c;家…...

接口自动化--commons内容详解-02

上篇文章主要讲解了接口自动化主要架构框架&#xff0c;这篇文庄主要讲解commons中的内容 1. requests_utils.py 首先讲解这个工具类&#xff0c;主要是因为在接口自动化中&#xff0c;基本都有的接口都是发送请求&#xff0c;获取响应结果&#xff0c;唯一不同的是&#xff0…...

WanFangAi论文写作研究生论文写作神器在线生成真实数据,标注参考文献位置,表格公式代码流程图查重20以内,研究生论文写作技巧

WanFangAi是一个专业的学术论文辅助平台&#xff0c;它提供了一系列工具来帮助用户提升论文写作的效率和质量。以下是WanFangAi的一些核心功能:1.主题探索与文献搜索:用户可以输入关键词和研究领域&#xff0c;WanFangAi会迅速推荐合适的论文主题并提供相关的文献搜索服务。系统…...

cv2.waitkey(30) 按键盘无效

cv2.imshow("detection", color_image) # 窗口显示&#xff0c;显示名为 Capture_Videok cv2.waitKey(100) & 0xFF # 每帧数据延时 1ms&#xff0c;延时不能为 0&#xff0c;否则读取的结果会是静态帧 if k ord(s): # 键盘按一下s, 保存当前照片和机械臂位姿…...

【洛谷】P10417 [蓝桥杯 2023 国 A] 第 K 小的和 的题解

【洛谷】P10417 [蓝桥杯 2023 国 A] 第 K 小的和 的题解 题目传送门 题解 CSP-S1 补全程序&#xff0c;致敬全 A 的答案&#xff0c;和神奇的预言家。 写一下这篇的题解说不定能加 CSP 2024 的 RP 首先看到 k k k 这么大的一个常数&#xff0c;就想到了二分。然后写一个判…...

Ubuntu24.04 安装ssh开启22端口及允许root用户远程登录

1、安装openssh-server插件开启22端口访问 # 安装ssh会默认启动服务并开启22端口 apt update apt install openssh-server 2、开启root用户远程访问 激活root用户&#xff0c;设置root用户登录密码 hunterlocalhost:/$ sudo passwd root New password: Retype new password…...

STM32基础学习笔记-DHT11单总线协议面试基础题7

第七章、DHT11: 单总线协!议 常见问题 1、DHT11是什么 &#xff1f;有什么特性 &#xff1f; 2、单总线协议是什么 &#xff1f;原理 &#xff1f;DHT11的单总线协议的组成 &#xff1f; ## 1、DHT11定义 单总线协议是一种用于在多个设备之间进行通信的协议&#xff0c;所有…...

Redisson分布式锁的概念和使用

Redisson分布式锁的概念和使用 一 简介1.1 什么是分布式锁&#xff1f;1.2 Redisson分布式锁的原理1.3 Redisson分布式锁的优势1.4 Redisson分布式锁的应用场景 二 案例2.1 锁竞争案例2.2 看门狗案例2.3 参考文章 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff…...

uniapp小程序持续获取用户位置信息,后台位置获取

做一个小程序持续获取用户位置信息的功能&#xff0c;即使小程序切换到后台也能继续获取&#xff0c;getLocation这个api只有小程序在前台才能获取位置&#xff0c;所以不用这个 先申请一个腾讯地图key 在uniapp项目配置源码视图里加上这个代码 先获取权限&#xff0c;再开启…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合

无论是python&#xff0c;或者java 的大型项目中&#xff0c;都会涉及到 自身平台微服务之间的相互调用&#xff0c;以及和第三发平台的 接口对接&#xff0c;那在python 中是怎么实现的呢&#xff1f; 在 Python Web 开发中&#xff0c;FastAPI 和 Django 是两个重要但定位不…...