鸿蒙NEXT开发案例:九宫格随机

【引言】

在鸿蒙NEXT开发中,九宫格抽奖是一个常见且有趣的应用场景。通过九宫格抽奖,用户可以随机获得不同奖品,增加互动性和趣味性。本文将介绍如何使用鸿蒙开发框架实现九宫格抽奖功能,并通过代码解析展示实现细节。

【环境准备】

• 操作系统:Windows 10

• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

• 目标设备:华为Mate60 Pro

• 开发语言:ArkTS

• 框架:ArkUI

• API版本:API 12

【思路】

本案例中的“九宫格随机”应用旨在模拟一个简单的抽奖场景,用户点击抽奖按钮后,程序会从预先定义好的九个奖品中随机选择一个作为最终奖品。整个应用采用了响应式编程模式,结合鸿蒙NEXT提供的组件化开发方式,实现了交互流畅、视觉效果良好的用户体验。

1. Prize类设计 应用首先定义了一个Prize类,用于表示奖品信息。该类使用了@ObservedV2装饰器,使得奖品属性(如标题、颜色、描述)的变化可以被自动追踪,从而实现UI的实时更新。构造函数允许创建具有特定属性值的奖品实例,便于后续管理。

2. MyPrizeUpdate结构组件 为了提供奖品信息的编辑功能,我们创建了MyPrizeUpdate结构组件。它通过接收外部传入的数据(当前选中的奖品索引、抽奖顺序数组及所有奖品的数组),构建了一个包含文本输入框的界面,用户可以在其中修改奖品的标题、描述和颜色。任何对这些属性的更改都会即时反映到对应的奖品对象上,并触发UI的相应更新。

3. LotteryPage入口组件LotteryPage是整个抽奖应用的核心组件,负责组织页面布局和处理用户交互逻辑。它初始化了一系列必要的状态变量,比如保存所有奖品的数组prizeArray、定义抽奖顺序的selectionOrder以及控制动画状态的isAnimating等。此外,该组件实现了抽奖过程的关键方法——startLottery(开始抽奖)、runAtConstantSpeed(匀速运行)和slowDown(减速),它们共同协作以模拟真实的抽奖体验。当用户点击抽奖按钮时,这些方法按照预定的速度模式依次调用,直到最终确定一个奖品为止。最后,通过弹出对话框的方式向用户展示抽奖结果。

4. UI布局与样式 在构建UI方面,应用充分利用了鸿蒙NEXT提供的布局容器(如Column、Row、Flex)和样式属性(如宽度、高度、边距、背景色、圆角、阴影),精心设计了每个奖品项的外观。特别地,对于抽奖按钮,不仅设置了独特的背景颜色,还在点击事件中添加了动画效果,增强了用户的参与感。同时,考虑到不同设备屏幕尺寸的差异,所有布局元素均采用相对单位进行设置,确保了应用在各种终端上的良好适配性。

5. 动画与交互优化 为了让抽奖过程看起来更加生动有趣,应用引入了加速、匀速、减速三个阶段的动画效果,使选中的奖品项能够以逐渐加快然后缓慢停止的方式出现在用户面前。这种变化不仅增加了悬念感,也提升了整体的娱乐性。此外,通过对点击事件的监听和处理,确保了即使是在动画过程中,用户的交互也不会受到影响,保证了良好的用户体验。

【完整代码】

// 定义一个可观察的Prize类,用于表示奖品信息。
@ObservedV2
class Prize {@Trace title: string // 奖品标题属性,使用@Trace进行追踪以便响应式更新UI@Trace color: string // 奖品颜色属性@Trace description: string // 奖品描述属性// 构造函数,用来初始化新的奖品实例constructor(title: string, color: string, description: string = "") {this.title = title // 设置奖品标题this.color = color // 设置奖品颜色this.description = description // 设置奖品描述,默认为空字符串}
}// 定义MyPrizeUpdate结构组件,用于显示和编辑选中的奖品信息
@Component
struct MyPrizeUpdate {@Consume selectedIndex: number // 当前选中的奖品索引@Consume private selectionOrder: number[] // 保存抽奖顺序的数组@Consume private prizeArray: Prize[] // 保存所有奖品的数组build() {Column({ space: 20 }) { // 创建列布局容器,设置子元素之间的间距为20pxRow() { // 创建行布局容器Text('标题:') // 显示“标题”文本TextInput({ text: this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].title }).width('300lpx') // 设置输入框宽度.onChange((value) => { // 监听输入框内容变化this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].title = value // 更新奖品标题})}Row() {Text('描述:')TextInput({text: `${this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].description}`}).width('300lpx').onChange((value) => { // 同上,但针对奖品描述this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].description = value})}Row() {Text('颜色:')TextInput({text: `${this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].color}`}).width('300lpx').onChange((value) => { // 同上,但针对奖品颜色this.prizeArray[this.selectionOrder[this.selectedIndex%this.selectionOrder.length]].color = value})}}.justifyContent(FlexAlign.Start) // 设置内容左对齐.padding(40) // 设置内边距.width('100%') // 设置宽度为100%.backgroundColor(Color.White) // 设置背景颜色为白色}
}// 定义抽奖页面入口组件
@Entry
@Component
struct LotteryPage {@Provide private selectedIndex: number = 0 // 提供当前选中的索引,初始值为0private isAnimating: boolean = false // 标记是否正在进行动画,初始值为false@Provide private selectionOrder: number[] = [0, 1, 2, 5, 8, 7, 6, 3] // 定义抽奖顺序private cellWidth: number = 200 // 单元格宽度private baseMargin: number = 10 // 单元格边距@Provide private prizeArray: Prize[] = [new Prize("红包", "#ff9675", "10元"), // 初始化奖品数组,创建各种奖品对象new Prize("话费", "#ff9f2e", "5元"),new Prize("红包", "#8e7fff", "50元"),new Prize("红包", "#48d1ea", "30元"),new Prize("开始抽奖", "#fffdfd"), // 抽奖按钮,没有具体奖品描述new Prize("谢谢参与", "#5f5f5f"),new Prize("谢谢参与", "#5f5f5f"),new Prize("超市红包", "#5f5f5f", "100元"),new Prize("鲜花", "#75b0fe"),]private intervalID: number = 0 // 定时器ID,用于控制抽奖速度@State isSheetVisible: boolean = false // 控制底部弹出表单的可见性// 开始抽奖逻辑startLottery(speed: number = 500) {setTimeout(() => { // 设置延时执行if (speed > 50) { // 如果速度大于50,则递归调用startLottery以逐渐加速speed -= 50this.startLottery(speed)} else {this.runAtConstantSpeed() // 达到最高速度后进入匀速阶段return}this.selectedIndex++ // 每次调用时更新选中索引}, speed)}// 以恒定速度运行抽奖runAtConstantSpeed() {let speed = 40 + Math.floor(Math.random() * this.selectionOrder.length) // 随机生成一个速度值clearInterval(this.intervalID) // 清除之前的定时器this.intervalID = setInterval(() => { // 设置新的定时器来更新选中索引if (this.selectedIndex >= speed) { // 如果选中索引达到速度值,停止并进入减速阶段clearInterval(this.intervalID)this.slowDown()return}this.selectedIndex++}, 50)}// 减速逻辑slowDown(speed = 50) {setTimeout(() => { // 设置延时执行if (speed < 500) { // 如果速度小于500,则递归调用slowDown以逐渐减速speed += 50this.slowDown(speed)} else {this.selectedIndex %= this.selectionOrder.length // 确保索引在有效范围内let index = this.selectionOrder[this.selectedIndex] // 获取最终选中的奖品索引this.isAnimating = false // 动画结束this.getUIContext().showAlertDialog({ // 显示结果对话框title: '结果',message: `${this.prizeArray[index].title}${this.prizeArray[index].description}`, // 显示奖品信息confirm: {defaultFocus: true,value: '我知道了', // 确认按钮文本action: () => {} // 点击确认后的操作},alignment: DialogAlignment.Center,});return}this.selectedIndex++}, speed)}// 构建UI方法build() {Column() { // 使用Column布局容器Flex({ wrap: FlexWrap.Wrap }) { // 使用弹性布局,允许换行ForEach(this.prizeArray, (item: Prize, index: number) => { // 遍历奖品数组,创建每个奖品的UIColumn() { // 使用Column布局容器为每个奖品项Text(`${item.title}`) // 显示奖品标题.fontColor(index == 4 ? Color.White : item.color) // 设置字体颜色,对于抽奖按钮特殊处理.fontSize(16)Text(`${item.description}`) // 显示奖品描述.fontColor(index == 4 ? Color.White : item.color) // 设置字体颜色.fontSize(20)}.clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 添加点击效果.onClick(() => { // 处理点击事件if (this.isAnimating) { // 如果正在动画中,忽略点击return}if (index == 4) { // 如果点击的是抽奖按钮,开始抽奖this.isAnimating = truethis.startLottery()} else {for (let i = 0; i < this.selectionOrder.length; i++) {if (this.selectionOrder[i] == index) {this.selectedIndex = i // 更新选中索引到对应位置}}}}).alignItems(HorizontalAlign.Center) // 设置水平居中对齐.justifyContent(FlexAlign.Center) // 设置垂直居中对齐.width(`${this.cellWidth}lpx`) // 设置单元格宽度.height(`${this.cellWidth}lpx`) // 设置单元格高度.margin(`${this.baseMargin}lpx`) // 设置单元格边距.backgroundColor(index == 4 ? "#ff5444" : // 抽奖按钮背景颜色特殊处理(this.selectionOrder[this.selectedIndex % this.selectionOrder.length] == index ? Color.Gray : Color.White)).borderRadius(10) // 设置圆角.shadow({ // 设置阴影效果radius: 10,color: "#f98732",offsetX: 0,offsetY: 20})})}.width(`${this.cellWidth * 3 + this.baseMargin * 6}lpx`) // 设置整体宽度.margin({ top: 30 }) // 设置顶部边距MyPrizeUpdate().margin({top:20}) // 插入MyPrizeUpdate组件,并设置其上边距}.height('100%') // 设置高度为100%.width('100%') // 设置宽度为100%.backgroundColor("#ffb350") // 设置页面背景颜色}
}

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

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

相关文章

金融信息分析基础(1)

1.金融数据 金融数据分为&#xff1a;交易数据&#xff08;低频数据&#xff0c;高频数据&#xff0c;超高频数据&#xff09;&#xff0c;报表数据&#xff08;财务报表&#xff0c;研报&#xff09;&#xff0c;金融社交媒体数据 低频数据&#xff1a; 以日、周、月、季、年…

.NET 技术系列 | 通过CreatePipe函数创建管道

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

docker安装、升级、以及sudo dockerd --debug查看启动失败的问题

1、docker安装包tar下载地址 Index of linux/static/stable/x86_64/ 2、下载tgz文件并解压 tar -zxvf docker-24.0.8.tgz 解压后docker文件夹下位docker相关文件 3、将老版本docker相关文件&#xff0c;备份 将 /usr/bin/docker下docker相关的文件&#xff0c;mv到备份目录…

uniapp——H5中使用富文本编辑器,如何使用。

一、插件市场 去插件市场找到这个插件https://ext.dcloud.net.cn/plugin?id14726 二、引入 找到自己项目引入 项目里面多了很多文件 三、使用 找到A页面&#xff0c;在里面引入组件 <view class"editBox"><sp-editor exportHtml"handleExpor…

arXiv-2024 | VLM-GroNav: 基于物理对齐映射视觉语言模型的户外环境机器人导航

作者&#xff1a; Mohamed Elnoor, Kasun Weerakoon, Gershom Seneviratne, Ruiqi Xian, Tianrui Guan, Mohamed Khalid M Jaffar, Vignesh Rajagopal, and Dinesh Manocha单位&#xff1a;马里兰大学学院公园分校原文链接&#xff1a;VLM-GroNav: Robot Navigation Using Phys…

音频客观测评方法PESQ

一、简介 语音质量感知评估&#xff08;Perceptual Evaluation of Speech Quality&#xff09;是一系列的标准&#xff0c;包括一种用于自动评估电话系统用户所体验到的语音质量的测试方法。该标准于2001年被确定为ITU-T P.862建议书[1]。PESQ被电话制造商、网络设备供应商和电…

Gitlab服务管理和仓库项目权限管理

Gitlab服务管理 gitlab-ctl start # 启动所有 gitlab 组件&#xff1b; gitlab-ctl stop # 停止所有 gitlab 组件&#xff1b; gitlab-ctl restart # 重启所有 gitlab 组件&#xff1b; gitlab-ctl status …

浏览器插件开发实战

浏览器插件开发实战 [1] 入门DEMO一、创建项目二、创建manifest.json三、加载插件四、配置 service-worker.js五、以书签管理器插件为例manifest.jsonpopup.htmlpopup.js查看效果 [2] Vue项目改造成插件一、复习Vue项目的结构二、删除、添加个别文件三、重写build [3] 高级开发…

SpringBoot集成JWT和Redis实现鉴权登录功能

目前市面上有许多鉴权框架&#xff0c;鉴权原理大同小异&#xff0c;本文简单介绍下利用JWT和Redis实现鉴权功能&#xff0c;算是抛砖引玉吧。 主要原理就是“令牌主动失效机制”&#xff0c;主要包括以下4个步骤&#xff1a; (1)利用拦截器LoginInterceptor实现所有接口登录拦…

在IDE中使用Git

我们在开发的时候肯定是经常使用IDE进行开发的&#xff0c;所以在IDE中使用Git也是非常常用的&#xff0c;接下来以IDEA为例&#xff0c;其他的VS code &#xff0c;Pycharm等IDE都是一样的。 在IDEA中配置Git 1.打开IDEA 2.点击setting 3.直接搜索git 如果已经安装了会自…

Python鼠标轨迹算法(游戏防检测)

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

【2025最新版】Stable diffusion汉化版安装教程(附SD安装包),一键激活,永久免费!

如何安装并学习使用Stable Diffusion呢&#xff1f; 其实&#xff0c;安装SD的过程并不复杂&#xff0c;只需按照简单的步骤操作&#xff0c;几分钟内就能完成安装&#xff0c;不论是Windows系统还是Mac系统&#xff0c;都能轻松应对。

Python学习(二)—— 基础语法(上)

目录 一&#xff0c;表达式和常量和变量 1.1 表达式 1.2 变量 1.3 动态类型特性 1.4 输入 二&#xff0c;运算符 2.1 算术运算符 2.2 关系运算符 2.3 逻辑运算符 2.4 赋值运算符 2.5 练习 三&#xff0c;语句 3.1 条件语句 3.2 while循环 3.3 for循环 四&#…

如何用状态图进行设计06

独立的控制线程 扩展状态图也提供了获取无序的输入事件的方法。这意味着一个状态开始时&#xff0c;它可能位于一个或多个控制线程的交叉点。控制行为的每个独立线程都类似一个状态机&#xff0c;独自运行&#xff0c;互不干扰。因此&#xff0c;这些控制线程可能会同时发生状…

嵌入式学习(18)-stm32F407串口接收空闲中断+DMA

一、概述 在一些一次性接收大批量数据的引用场合&#xff0c;如果使用接收中断会频繁的进入接收中断影响代码的运行效率。为了解决这个问题可以使用串口的空闲中断DMA实现。 二、应用 在网上招了一些例程在STM32F407的平台上都没有跑通会出现各种异常&#xff0c;主要原因还…

多线程的知识总结(8):用 thread 类 或全局 async (...) 函数,创建新线程时,谁才是在新线程里第一个被执行的函数

&#xff08;40&#xff09;用 thread 类 或全局 async (…) 函数&#xff0c;创建新线程时&#xff0c;谁才是在新线程里第一个被执行的函数&#xff1f; 弄清楚这个问题&#xff0c;有利于推测和理解线程中代码的执行流程。根据 thread 类 和 async &#xff08;…&#xff0…

UOB大华银行|校招网申综合能力SHL测评题库英语版本真题分析

大华银行有限公司&#xff08;大华银行&#xff09;是亚洲银行业的翘楚&#xff0c;大华银行总部位于新加坡&#xff0c;并在中国、印度尼西亚、马来西亚、泰国及越南设立了全资法人银行&#xff0c;在全球拥有约500 间分行及办事处&#xff0c;分布在亚太、欧洲与北美的19 个国…

WebSpoon9.0(KETTLE的WEB版本)编译 + tomcatdocker部署 + 远程调试教程

前言 Kettle简介 Kettle是一款国外开源的ETL工具&#xff0c;纯Java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装&#xff0c;数据抽取高效稳定 WebSpoon是Kettle的Web版本&#xff0c;由Kettle社区维护&#xff0c;不受Pentaho支持&#xff0c;…

用人话讲计算机:Python篇!(十二)正则运算+re模块

目录 一、正则表达式 &#xff08;1&#xff09;什么是正则表达式 &#xff08;2&#xff09;它的结构及使用 示例&#xff1a; 1.字符 . &#xff08;←这里有个小点哦&#xff09; 2.字符 | 3.字符 [ ] 4.字符^ 5.字符\d &#xff08;3&#xff09;补充&#xff…

Service Discovery in Microservices 客户端/服务端服务发现

原文链接 Client Side Service Discovery in Microservices - GeeksforGeeks 原文链接 Server Side Service Discovery in Microservices - GeeksforGeeks 目录 服务发现介绍 Server-Side 服务发现 实例&#xff1a; Client-Side 服务发现 实例&#xff1a; 服务发现介绍…