鸿蒙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.rhkb.cn/news/489874.html

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

相关文章

redis集群安装部署 redis三主三从集群

redis集群安装部署 redis三主三从集群 1、下载redis2、安装redis集群 三主三从3、配置redis开机自启动3.1、建立启动脚本3.2、复制多份redis启动脚本给集群使用3.3、添加可执行权限3.4、配置开机自启动 1、下载redis 本次redis安装部署选择当前最新的稳定版本7.4.1 下载链接: …

链表的回文结构

链表的回文结构。OJ链接 import java.util.*;/* public class ListNode {int val;ListNode next null;ListNode(int val) {this.val val;} }*/ public class PalindromeList {public boolean chkPalindrome(ListNode head) {// write code hereListNode slowhead;ListNode …

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题 这篇文章是接我cocos专栏的上一篇文章继续写的&#xff0c;我上一篇文章写的是 cocos 开发触摸屏项目&#xff0c;需要嵌入一个网页用来展示&#xff0c;最后通过 electron 打包成 exe 程序&#xff0c;而且网页里面…

计算机组成原理与系统结构——多核计算机

笔记内容及图片整理自XJTUSE “计算机组成原理与系统结构” 课程ppt&#xff0c;仅供学习交流使用&#xff0c;谢谢。 多核处理器也称为芯片多处理器&#xff0c;将两个及以上处理器单元组合在一个芯片上。通常&#xff0c;每个内核都由独立处理器的全部组件构成&#xff0c;例…

JAVA学习(三)

方法内部类 匿名内部类 如下使用匿名内部类去实现&#xff1a;&#xff08;对内存的损耗&#xff0c;对系统性能的影响相对较小&#xff09; 总结

IIS服务器部署C# WebApi程序,客户端PUT,DELETE请求无法执行

这两天在自己Windows10电脑上搭建IIS服务器&#xff0c;把自己写的WebApi代码部署上做个本地服务器&#xff0c;结果客户端的PUT和DELETE请求无法执行&#xff0c;GET、POST这些都正常&#xff0c;研究后发现要删除IIS中的“模块”中的"webdavmodule"才能解决。

微服务-01

1.认识微服务 1.1 单体架构 单体架构&#xff08;monolithic structure&#xff09;&#xff1a;顾名思义&#xff0c;整个项目中所有功能模块都在一个工程中开发&#xff1b;项目部署时需要对所有模块一起编译、打包&#xff1b;项目的架构设计、开发模式都非常简单。 当项目…

Vue2 基础

Vue 2 是 Vue.js 的第二个主要版本&#xff0c;于 2016 年发布。它是一个渐进式的 JavaScript 框架&#xff0c;以其简单、灵活、易用性高而广受欢迎。Vue 2 主要专注于构建用户界面&#xff08;UI&#xff09;&#xff0c;并且非常适合用于构建单页应用&#xff08;SPA&#x…

LSTM详解

1. LSTM设计 LSTM(长短期记忆网络)详解 长短期记忆网络(LSTM, Long Short-Term Memory) 是一种特殊的循环神经网络(RNN),特别适合处理和预测序列数据中的长时间依赖关系。LSTM 通过引入“门机制”(如输入门、遗忘门、输出门)来解决标准 RNN 在长时间序列任务中梯度消…

【从零开始入门unity游戏开发之——C#篇05】转义字符、@处理多行文本或者不使用转义字符、随机数

文章目录 一、转义字符1、什么是转义字符&#xff1f;2、常见的转义字符3、总结 二、使用处理多行文本或者不使用转义字符1、多行字符串2、不使用转义字符 三、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSin…

3D 生成重建034-NerfDiff借助扩散模型直接生成nerf

3D 生成重建034-NerfDiff借助扩散模型直接生成nerf 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 感觉这个论文可能能shapE差不多同时期工作&#xff0c;但是shapE是生成任意种类。 本文提出了一种新颖的单图像视图合成方法NerfDiff&#xff0c;该方法利用神经辐射场 …

3D一览通在线协同设计,助力汽车钣金件设计与制造数字化升级

汽车行业已迎来智能化的汹涌浪潮&#xff0c;在此背景下&#xff0c;零部件制造商唯有积极应对&#xff0c;以智能制造为核心驱动力&#xff0c;方能跟上行业发展步调&#xff0c;在激烈的市场竞争中抢占先机。作为整车制造不可或缺的核心组件之一&#xff0c;汽车钣金件亦需紧…

从资产流动分析WIF市场潜力X.game深究其他未知因素

近日&#xff0c;两则关于WIF最新消息引起了投资者们的注意。据报道&#xff0c;11月28日Vintermute在过去13小时内累计从Binance交易所提取了价值533万美元的WIF&#xff0c;此举不仅彰显了其强大的资金实力&#xff0c;更在某种程度上推动了WIF币价的反弹&#xff1b;另一方面…

如何使用IoT_CLOUD连接百度云平台?一篇实现高效的物联网开发

随着物联网技术的飞速发展&#xff0c;云平台在物联网项目中的重要性日益凸显。然而&#xff0c;市面上众多云平台各自为政&#xff0c;拥有不同的接入协议和开发文档&#xff0c;使得工程师们在开发过程中面临巨大的挑战。本文将以Air780ELuatOS作为示例&#xff0c;教你使用I…

CentOS7 Apache安装踩坑

Gnome桌面右键弹出终端。 [rootlocalhost ~]# yum repolist 已加载插件&#xff1a;fastestmirror, langpacks /var/run/yum.pid 已被锁定&#xff0c;PID 为 2611 的另一个程序正在运行。 Another app is currently holding the yum lock; waiting for it to exit... [root…

31.攻防世界php_rce

进入场景 不是&#xff0c;这是个啥啊 index.php?sindex/think\app/invokefunction&functioncall_user_func_array&vars[0]system&vars[1][]whoami index.php?sindex/think\app/invokefunction&functioncall_user_func_array&vars[0]system&vars[1]…

C 进阶 — 指针的使用

C 进阶 — 指针的使用 主要内容 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 6、函数指针数组 7、指向函数指针数组的指针 8、 回调函数 9、指针和数组练习题 前节回顾 1、指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一…

【ChatGPT出现降智无法画图和联网解决方法】

【ChatGPT出现降智无法画图和联网解决方法】 打开浏览器进入到ChatGPT界面 快捷键F12开发者调试工具 切换到Network&#xff0c;勾选Disable cache 切换到Application 选择Local storage(1)&#xff0c;然后点击Clear All(2)&#xff0c;再点击Refresh(3) 选择Session …

API接口示例:电商商品评论数据

当然&#xff0c;以下是一个简化的电商商品评论数据API接口的示例。请注意&#xff0c;这只是一个示例&#xff0c;实际的API接口可能会更加复杂&#xff0c;并且会包含更多的验证、错误处理和安全措施。 API接口示例&#xff1a;电商商品评论数据 基础信息 API名称&#xf…

操作系统(7)处理机调度

前言 操作系统中的处理机调度是一个核心概念&#xff0c;它涉及如何从就绪队列中选择进程并将处理机分配给它以运行&#xff0c;从而实现进程的并发执行。 一、调度的层次 高级调度&#xff08;作业调度&#xff09;&#xff1a; 调度对象&#xff1a;作业&#xff08;包含程序…