一、案例概述
本项目是一个基于HarmonyOS 6开发的随机数生成器应用。你将构建一个工具应用,允许用户输入一个数字范围的最小值与最大值。点击按钮后,程序会在这个区间内生成并显示一个随机整数。旨在让你快速掌握ArkTS组件和状态管理的核心用法,是新手上手的理想实践。
二、核心知识点
2.1 Math.random()
Math.random()是一个十分便捷的接口。每次执行都返回一个大于等于0且小于1的双精度浮点数,即数学区间 [0, 1) 。
这个函数内部采用伪随机数生成算法。对于抽奖、游戏道具掉落、演示数据生成这类对随机性质量要求不高的场景,它完全够用。在HarmonyOS 6应用开发中,你可以在任何需要随机性的地方直接调用它,例如在 onClick 事件处理函数中生成一个随机数,或用于初始化一些模拟数据。
2.2 范围计算
随机数生成的本质,是将 Math.random() 产生的 [0, 1) 区间均匀分布的随机小数 r ,线性变换到目标区间 [min, max] 。
生成随机整数的公式是核心:
TypeScript
let randomInteger = Math.floor(Math.random() * (max - min + 1)) + min;
拆解这个公式:
- Math.random() 产生 r ∈ [0, 1) 。
- (max - min + 1) 计算目标区间内整数的总数量。例如区间 [1, 10] 共有10个整数。
- r * (max - min + 1) 将 r 放大,得到 ∈ [0, max-min+1) 的浮点数。
- Math.floor() 对这个浮点数向下取整,得到 ∈ {0, 1, ..., max-min} 的整数。
-
- min 将整数集合平移,最终得到 ∈ {min, min+1, ..., max} 的目标随机整数。
如果需要生成随机小数(浮点数),公式更为直接,且无需取整:
TypeScript
let randomFloat = Math.random() * (max - min) + min;
这里 (max - min) 是区间跨度, r * (max - min) 得到 ∈ [0, max-min) 的浮点数,再加上 min 即完成平移。
2.3 输入验证
用户输入是不可预测的。两个 TextInput 接收的 min 和 max 值,必须经过严格校验。
验证逻辑需包含以下关键检查:
- 非数字输入:使用 isNaN() 判断输入是否能被转换为有效数字。
- 逻辑边界:确保最小值 min 不大于最大值 max 。
- 整数区间处理:如果目标是生成整数,需确认 min 和 max 本身是整数,或对其进行取整处理,并再次校验取整后的逻辑关系。
一个健壮的 validateInputs() 函数应在检测到任何无效输入时,立即中断生成流程,并通过 AlertDialog 或 Text 提示向用户反馈明确错误信息,例如"最小值不能大于最大值"或"请输入有效数字"。
2.4 UI响应式更新
界面动态展示的核心是 @State 装饰器。我们定义一个 @State randomResult: string = '' 状态变量。
当用户点击生成按钮时, onClick 事件触发 handleGenerateRandom() 函数。此函数内部:
- 调用 validateInputs() 通过校验。
- 执行上述范围计算公式,得到随机数。
- 将计算结果赋值给 this.randomResult 。
关键在于第三步:一旦 this.randomResult 的值被修改,所有在UI中绑定了此变量的组件,ArkUI框架会自动检测到状态变化并触发重新渲染。因此,显示结果的 Text 组件内容会即时更新。
三、开发步骤
3.1 基础UI设计
输入区域采用横向并排布局,通过 Row 容器排列两个 TextInput 组件,清晰对应"最小值"与"最大值"的输入职责。两个输入框保持相同样式,并通过 placeholder 属性提示用户,例如"最小整数"和"最大整数"。它们的角色是捕获用户的自定义区间意图,并将输入的字符串传递给后台逻辑进行解析和验证。
触发核心是一个 Button 组件,放置于输入区域下方。它的文本标签为"生成随机数",功能角色单一明确:响应用户点击,驱动应用执行从输入验证、随机数计算到结果更新的完整逻辑链条。
展示区域是一个用于结果输出的 Text 组件,通常放置在按钮下方或作为视觉中心。它使用较大的字体和醒目的样式,初始状态可显示提示文字如"等待生成..."。其核心角色是实时、直观地反馈每次生成的随机数结果。该区域通过绑定一个 @State 变量实现动态响应------当后台计算产生新数值并更新该变量时,文本内容会立即自动刷新。
为了实现上述清晰的视觉层次和操作性,界面布局采用了 Flex 纵向容器与内部 Row 横向容器的简洁组合。
TypeScript
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
// 输入区域:横向排列
Row({ space: 10 }) {
TextInput({ placeholder: '最小值' })
.width('40%')
.onChange((value: string) => { /* 更新minValue状态 */ })
TextInput({ placeholder: '最大值' })
.width('40%')
.onChange((value: string) => { /* 更新maxValue状态 */ })
}
.margin({ bottom: 20 })
// 触发按钮
Button('生成随机数')
.width('50%')
.margin({ bottom: 20 })
.onClick(() => { /* 触发生成逻辑 */ })
// 结果显示区域
Text(this.randomResult)
.fontSize(36)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('100%')
}
3.2 核心逻辑代码
TypeScript
@Entry
@Component
struct RandomGenerator {
// 步骤1:定义响应式状态变量
// 绑定到TextInput,存储用户输入的范围值
@State minValue: string = ''
@State maxValue: string = ''
// 存储并驱动显示生成的随机结果
@State randomResult: string = '准备就绪,请设定范围并点击生成。'
// 用于临时提示输入错误等信息
@State tipMessage: string = ''
// 步骤2:核心生成函数
// 该函数在生成按钮点击时被触发
private handleGenerateRandom(): void {
// 首先进行输入验证
if (!this.validateInputs()) {
return // 验证失败则终止流程
}
// 将字符串输入转换为数字
const minNum: number = Number(this.minValue)
const maxNum: number = Number(this.maxValue)
// 核心算法:将[0,1)的随机数映射到[min, max]的整数区间
// 公式:Math.floor(Math.random() * (max - min + 1)) + min
const randomInteger: number =
Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum
// 更新结果状态,触发UI重绘
this.randomResult = `随机数:${randomInteger}`
this.tipMessage = `已生成范围 [${minNum}, ${maxNum}] 内的整数。`
}
// 步骤3:输入验证函数
// 确保用户输入的数字有效且逻辑正确
private validateInputs(): boolean {
const minStr: string = this.minValue.trim()
const maxStr: string = this.maxValue.trim()
// 检查是否为空
if (minStr === '' || maxStr === '') {
this.tipMessage = '请输入最小值和最大值。'
this.randomResult = '输入不完整'
return false
}
// 检查是否为有效数字
const minNum: number = Number(minStr)
const maxNum: number = Number(maxStr)
if (isNaN(minNum) || isNaN(maxNum)) {
this.tipMessage = '请输入有效的数字。'
this.randomResult = '输入无效'
return false
}
// 检查是否为整数
if (!Number.isInteger(minNum) || !Number.isInteger(maxNum)) {
this.tipMessage = '请输入整数以获得准确的整数随机数。'
}
// 核心逻辑检查:最小值不能大于最大值
if (minNum > maxNum) {
this.tipMessage = '最小值不能大于最大值。'
this.randomResult = '范围设定错误'
return false
}
// 所有检查通过
this.tipMessage = '输入有效,可以生成。'
return true
}
// 步骤4:构建UI布局与事件绑定
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly }) {
// 标题区域
Text('随机数生成器')
.fontSize(26)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 30 })
// 范围输入区域 - 采用Row横向排列
Row({ space: 15 }) {
Column({ space: 5 }) {
Text('最小值')
.fontSize(14)
.fontColor(Color.Gray)
TextInput({ placeholder: '例如: 1', text: this.minValue })
.width('100%')
.height(40)
.type(InputType.Number)
.borderRadius(10)
.backgroundColor(Color.White)
.padding({ left: 10, right: 10 })
.onChange((value: string) => {
// 实时更新状态变量
this.minValue = value
})
}
.width('40%')
Column({ space: 5 }) {
Text('最大值')
.fontSize(14)
.fontColor(Color.Gray)
TextInput({ placeholder: '例如: 100', text: this.maxValue })
.width('100%')
.height(40)
.type(InputType.Number)
.borderRadius(10)
.backgroundColor(Color.White)
.padding({ left: 10, right: 10 })
.onChange((value: string) => {
this.maxValue = value
})
}
.width('40%')
}
.width('90%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 20 })
// 状态提示信息
Text(this.tipMessage)
.fontSize(12)
.fontColor(this.tipMessage.includes('错误') || this.tipMessage.includes('无效') ? '#ff4d4f' : '#1890ff')
.margin({ bottom: 10 })
.height(20)
// 生成按钮
Button('生成随机数', { type: ButtonType.Capsule })
.width(200)
.height(45)
.backgroundColor('#1890ff')
.fontColor(Color.White)
.fontSize(16)
.margin({ bottom: 30 })
.onClick(() => {
this.handleGenerateRandom()
})
// 结果展示区域 - 视觉焦点
Column({ space: 10 }) {
Text('生成结果')
.fontSize(18)
.fontColor(Color.Gray)
Text(this.randomResult)
.fontSize(42)
.fontWeight(FontWeight.Bold)
.fontColor('#262626')
.height(80)
.textAlign(TextAlign.Center)
.backgroundColor(Color.White)
.padding({ left: 30, right: 30 })
.borderRadius(16)
.shadow({ radius: 10, color: '#1890ff20', offsetX: 0, offsetY: 5 })
}
.margin({ top: 10 })
// 底部公式提示
Text(`公式:Math.floor(Math.random() * (max - min + 1)) + min`)
.fontSize(12)
.fontColor('#8c8c8c')
.margin({ top: 30 })
.width('90%')
.textAlign(TextAlign.Center)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
}
.width('100%')
.height('100%')
.backgroundColor('#f5f5f5')
.padding(20)
}
}
这段代码构建了一个完整、可交互的随机数生成器。其核心流程是:用户在 TextInput 中设定范围,点击按钮触发 handleGenerateRandom 函数。该函数内部调用 validateInputs 进行严格校验,通过后执行核心映射算法,最后将结果赋值给 randomResult 状态变量,驱动界面自动更新。
四、实现效果
