news 2026/6/26 3:03:30

Flutter for OpenHarmony 实战_随机抽签应用设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter for OpenHarmony 实战_随机抽签应用设计与实现

Flutter for OpenHarmony 实战:随机抽签应用设计与实现

欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区

文章目录

  • Flutter for OpenHarmony 实战:随机抽签应用设计与实现
    • 前言
    • 一、抽签算法实现
      • 1.1 基础随机选择
      • 1.2 多次抽签
      • 1.3 权重抽签
    • 二、候选人管理
      • 2.1 添加候选人
      • 2.2 批量导入
      • 2.3 删除候选人
    • 三、抽签动画
      • 3.1 滚动动画
      • 3.2 结果对话框
    • 四、UI界面设计
      • 4.1 主界面布局
      • 4.2 候选人列表
      • 4.3 控制按钮
    • 五、历史记录
      • 5.1 记录存储
      • 5.2 历史显示
    • 六、设置功能
      • 6.1 动画时长
      • 6.2 音效开关
    • 七、数据持久化
      • 7.1 保存数据
      • 7.2 加载数据
    • 总结

前言

随机抽签应用是一个实用的工具类应用,广泛应用于抽奖、分组、决策等场景。本文将详细介绍随机抽签算法、候选人管理、动画效果实现、结果历史记录以及UI交互设计。

一、抽签算法实现

1.1 基础随机选择

classLotterySystem{List<String>candidates=[];StringdrawWinner(){if(candidates.isEmpty){return'';}finalrandom=Random();finalindex=random.nextInt(candidates.length);returncandidates[index];}}

使用Random().nextInt()生成随机索引,从候选人列表中选择一个。

1.2 多次抽签

List<String>drawMultiple(int count){if(count>candidates.length){throwException('抽签数量超过候选人数量');}finalselected=<String>[];finalavailable=List<String>.from(candidates);for(int i=0;i<count;i++){finalrandom=Random();finalindex=random.nextInt(available.length);selected.add(available[index]);available.removeAt(index);}returnselected;}

支持一次抽取多个不重复的候选人。

1.3 权重抽签

classWeightedCandidate{finalStringname;finalint weight;WeightedCandidate({requiredthis.name,requiredthis.weight});}StringdrawWeighted(List<WeightedCandidate>candidates){finaltotalWeight=candidates.fold(0,(sum,c)=>sum+c.weight);finalrandom=Random();finalrandomValue=random.nextInt(totalWeight);int currentWeight=0;for(varcandidateincandidates){currentWeight+=candidate.weight;if(randomValue<currentWeight){returncandidate.name;}}returncandidates.last.name;}

根据权重进行抽签,权重越高被抽中的概率越大。

二、候选人管理

2.1 添加候选人


voidaddCandidate(Stringname){if(name.trim().isEmpty){return;}if(candidates.contains(name)){ScaffoldMessenger.of(context).showSnackBar(constSnackBar(content:Text('该候选人已存在')),);return;}setState((){candidates.add(name);});}

添加候选人时检查重复和空名称。

2.2 批量导入

voidimportCandidates(Stringtext){finallines=text.split('\n');int added=0;for(varlineinlines){finalname=line.trim();if(name.isNotEmpty&&!candidates.contains(name)){candidates.add(name);added++;}}ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text('成功导入$added个候选人')),);}

支持从文本批量导入候选人,每行一个。

2.3 删除候选人

voidremoveCandidate(Stringname){setState((){candidates.remove(name);});}voidclearAll(){showDialog(context:context,builder:(context)=>AlertDialog(title:constText('清空候选人'),content:constText('确定要清空所有候选人吗?'),actions:[TextButton(onPressed:()=>Navigator.pop(context),child:constText('取消'),),TextButton(onPressed:(){setState((){candidates.clear();});Navigator.pop(context);},child:constText('确定'),),],),);}

提供单个删除和清空全部功能。

三、抽签动画

3.1 滚动动画

StringcurrentDisplay='';bool isAnimating=false;List<String>history=[];voidstartDrawing()async{if(candidates.isEmpty||isAnimating){return;}isAnimating=true;finalduration=constDuration(milliseconds:2000);finalstart=DateTime.now();while(DateTime.now().difference(start)<duration){finalrandom=Random();currentDisplay=candidates[random.nextInt(candidates.length)];setState((){});awaitFuture.delayed(constDuration(milliseconds:50));}// 最终结果finalwinner=drawWinner();currentDisplay=winner;history.add(winner);isAnimating=false;setState((){});showResultDialog(winner);}

2秒内快速滚动显示候选人名称,制造悬念。

3.2 结果对话框

voidshowResultDialog(Stringwinner){showDialog(context:context,builder:(context)=>AlertDialog(title:constText('抽签结果'),content:Column(mainAxisSize:MainAxisSize.min,children:[constIcon(Icons.celebration,size:64,color:Colors.amber),constSizedBox(height:16),Text(winner,style:constTextStyle(fontSize:32,fontWeight:FontWeight.bold),),],),actions:[TextButton(onPressed:()=>Navigator.pop(context),child:constText('确定'),),],),);}

使用对话框展示最终结果,带有庆祝图标。

四、UI界面设计

4.1 主界面布局

@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText('随机抽签'),actions:[IconButton(icon:constIcon(Icons.history),onPressed:showHistory),IconButton(icon:constIcon(Icons.settings),onPressed:showSettings),],),body:Column(children:[Expanded(child:Center(child:Text(currentDisplay,style:Theme.of(context).textTheme.displayLarge,),),),_buildCandidateList(),_buildControlButtons(),],),);}

中心显示当前抽签结果,下方是候选人列表和控制按钮。

4.2 候选人列表

Widget_buildCandidateList(){returnContainer(height:200,padding:constEdgeInsets.all(16),child:ListView.builder(itemCount:candidates.length,itemBuilder:(context,index){returnListTile(title:Text(candidates[index]),trailing:IconButton(icon:constIcon(Icons.remove_circle),onPressed:()=>removeCandidate(candidates[index]),),);},),);}

可滚动的候选人列表,每个项带删除按钮。

4.3 控制按钮

Widget_buildControlButtons(){returnPadding(padding:constEdgeInsets.all(16),child:Row(mainAxisAlignment:MainAxisAlignment.spaceEvenly,children:[ElevatedButton.icon(onPressed:isAnimating?null:startDrawing,icon:constIcon(Icons.play_arrow),label:constText('开始抽签'),),ElevatedButton.icon(onPressed:()=>addCandidateDialog(),icon:constIcon(Icons.add),label:constText('添加候选人'),),],),);}

开始抽签和添加候选人两个主要按钮。

五、历史记录

5.1 记录存储

List<String>history=[];List<DateTime>timestamps=[];voidaddToHistory(Stringwinner){history.add(winner);timestamps.add(DateTime.now());}

记录抽签结果和时间戳。

5.2 历史显示

voidshowHistory(){showDialog(context:context,builder:(context)=>AlertDialog(title:constText('抽签历史'),content:SizedBox(width:double.maxFinite,height:400,child:ListView.builder(itemCount:history.length,itemBuilder:(context,index){finalreversedIndex=history.length-1-index;returnListTile(title:Text(history[reversedIndex]),subtitle:Text(_formatTime(timestamps[reversedIndex])),leading:Text('${reversedIndex+1}'),);},),),actions:[TextButton(onPressed:()=>Navigator.pop(context),child:constText('关闭'),),TextButton(onPressed:(){setState((){history.clear();timestamps.clear();});Navigator.pop(context);},child:constText('清空历史'),),],),);}

显示所有历史记录,最新记录在前。

六、设置功能

6.1 动画时长

int animationDuration=2000;// 毫秒voidupdateDuration(int duration){setState((){animationDuration=duration;});}

允许用户调整抽签动画时长。

6.2 音效开关

bool soundEnabled=true;voidtoggleSound(){setState((){soundEnabled=!soundEnabled;});}

控制抽签时是否播放音效。

七、数据持久化

7.1 保存数据

Future<void>saveData()async{finalprefs=awaitSharedPreferences.getInstance();awaitprefs.setStringList('candidates',candidates);awaitprefs.setStringList('history',history);}

使用SharedPreferences保存候选人和历史记录。

7.2 加载数据

Future<void>loadData()async{finalprefs=awaitSharedPreferences.getInstance();finalsavedCandidates=prefs.getStringList('candidates');finalsavedHistory=prefs.getStringList('history');if(savedCandidates!=null){setState((){candidates=savedCandidates;});}if(savedHistory!=null){history=savedHistory;}}

应用启动时自动加载数据。

总结

本文详细介绍了随机抽签应用的设计与实现。从随机算法到候选人管理,从动画效果到UI设计,每个技术点都直接影响应用的功能性和用户体验。通过这些技术的综合应用,实现了功能完整且实用的随机抽签应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 0:23:17

Pr怎么给视频添加字幕?2种方法对比,第2种效率提升10倍!

做视频剪辑&#xff0c;最枯燥的环节莫过于加字幕。是用PR自带的文字工具一个个手打&#xff0c;还是用Pr插件一键识别&#xff1f;本文深度对比2种PR添加字幕的方法&#xff1a;传统手动添加与千鹿Pr助手自动识别。 实测发现&#xff0c;使用千鹿Pr助手插件&#xff0c;无需打…

作者头像 李华
网站建设 2026/6/9 3:55:27

构建镜像docker命令

1、有网的机器编写DockerFile文件 FROM python:3.9-slimRUN apt-get update && apt-get install -y \libgl1 \libglib2.0-0 \&& rm -rf /var/lib/apt/lists/*# 设置工作目录 WORKDIR /app# 设置环境变量 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=…

作者头像 李华
网站建设 2026/6/14 2:23:51

惊爆!提示工程架构师揭秘Agentic AI技术生态与未来走向

惊爆&#xff01;提示工程架构师揭秘Agentic AI技术生态与未来走向 引言&#xff1a;从“工具AI”到“伙伴AI”&#xff0c;我们需要的是能主动解决问题的AI 凌晨三点&#xff0c;我盯着电脑屏幕上的ChatGPT对话框发呆——为了写一篇关于Agentic AI的深度文章&#xff0c;我已经…

作者头像 李华
网站建设 2026/6/22 17:34:37

【开题答辩全过程】以 河市富达购物微信小程序为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

作者头像 李华
网站建设 2026/6/25 8:33:52

Cursor+Claude AI编程 - Cursor简介

大家好&#xff0c;我是小锋老师&#xff0c;最近更新《2027版 CursorClaude AI编程 1天快速上手》专辑&#xff0c;感谢大家支持。 本课程主要讲解Cursor简介&#xff0c;Cursor下载安装&#xff0c;Cursor生成helloWorld网页&#xff0c;Cursor会话里的Cursor会话里的Agent,…

作者头像 李华