news 2026/5/13 7:43:22

Flutter 不只是写 App —— 用代码打造一个“会说话”的桌面宠物

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter 不只是写 App —— 用代码打造一个“会说话”的桌面宠物

Flutter 不只是写 App —— 用代码打造一个“会说话”的桌面宠物**

当我们谈论 Flutter,大多数人想到的是“跨平台 App 开发”、“Material Design”或“高性能 UI”。但今天,我们不走寻常路 —— 我要用Flutter 构建一个运行在桌面端的“会说话的小狐狸”宠物应用,它能随机弹出气泡对话、眨眼卖萌,还能随着鼠标靠近做出反应。

这不是又一篇“计数器教程”,而是一次对 Flutter 能力边界的探索:

谁说 Flutter 只能做传统界面?它也能成为创意表达的画布。


🌟 项目亮点

  • 使用 Flutter 构建无边框透明窗口桌面应用
  • 实现动画角色 + 气泡对话
  • 利用dart:mathTimer做行为逻辑
  • 支持鼠标互动(接近时转头)
  • 完全自定义绘制与布局

这不仅是一个玩具,更是展示 Flutter 在非传统 UI 场景下的创造力


✅ 环境准备

确保你已安装:

flutter desktopenable-dwindows,macos,linux

创建项目并启用桌面支持后,我们直接进入核心编码。


🦊 第一步:设计我们的小狐狸

我们将使用一张 PNG 图片作为小狐狸形象(你可以替换成任何你喜欢的角色)。假设图片名为fox.png,放在assets/images/fox.png

pubspec.yaml 配置资源
flutter:assets:-assets/images/fox.png

💬 第二步:写一个浮动对话气泡

我们来做一个从头顶飘出的对话框,带圆角和箭头。

// widgets/speech_bubble.dartimport'package:flutter/material.dart';classSpeechBubbleextendsStatelessWidget{finalStringmessage;finalDurationduration;constSpeechBubble({super.key,requiredthis.message,this.duration=constDuration(seconds:3)});@overrideWidgetbuild(BuildContextcontext){returnAnimatedOpacity(opacity:1.0,duration:constDuration(milliseconds:300),child:Container(padding:constEdgeInsets.symmetric(horizontal:12,vertical:8),decoration:BoxDecoration(color:Colors.black.withOpacity(0.7),borderRadius:BorderRadius.circular(16),boxShadow:[BoxShadow(color:Colors.black.withOpacity(0.3),blurRadius:6,)],),child:Text(message,style:constTextStyle(color:Colors.white,fontSize:14),),),);}}

🖼️ 第三步:主界面 —— 透明无边框 + 角色显示

我们要让窗口没有标题栏,并且背景透明。

修改 main.dart
// main.dartimport'package:flutter/material.dart';import'package:window_manager/window_manager.dart';voidmain()async{WidgetsFlutterBinding.ensureInitialized();awaitwindowManager.ensureInitialized();// 设置窗口配置(仅桌面有效)WindowOptionswindowOptions=constWindowOptions(size:Size(200,200),center:true,skipTaskbar:true,// 不显示在任务栏transparent:true,// 透明背景frameless:true,// 无边框);windowManager.waitUntilReadyToShow(windowOptions,()async{awaitwindowManager.show();awaitwindowManager.focus();});runApp(constPetApp());}

⚠️ 注意:需要添加依赖window_manager: ^0.4.0来控制原生窗口行为。


🧠 第四步:小狐狸大脑 —— 行为逻辑

我们现在写一个状态类,让它每隔几秒“说点什么”。

// screens/pet_screen.dartimport'dart:async';import'dart:math';import'package:flutter/material.dart';import'../widgets/speech_bubble.dart';classPetScreenextendsStatefulWidget{constPetScreen({super.key});@overrideState<PetScreen>createState()=>_PetScreenState();}class_PetScreenStateextendsState<PetScreen>withSingleTickerProviderStateMixin{lateAnimationController_blinkController;double mouseX=0,mouseY=0;bool isLookingAtMouse=false;String?currentMessage;Timer?_messageTimer;finalList<String>messages=['今天天气真好~','你瞅啥?','摸摸头会变强哦','我饿了,有吃的吗?','别靠太近!害羞了啦','呼噜呼噜…睡着了',];@overridevoidinitState(){super.initState();// 眨眼动画(眼睛开合)_blinkController=AnimationController(vsync:this,duration:constDuration(milliseconds:150),);// 定时说话_startRandomMessaging();// 监听鼠标移动(通过全局事件)windowManager.addListener(_onMouseMove);}void_startRandomMessaging(){Timer.periodic(Duration(seconds:Random().nextInt(8)+5),(timer){if(!mounted)return;_showMessage(messages[Random().nextInt(messages.length)]);});}void_showMessage(Stringmsg){setState((){currentMessage=msg;});// 3秒后消失_messageTimer?.cancel();_messageTimer=Timer(constDuration(seconds:3),(){if(!mounted)return;setState((){currentMessage=null;});});// 触发眨眼_blinkController.forward().then((_)=>_blinkController.reverse());}void_onMouseMove(PointerEventevent){finalwindowSize=windowManager.getSize();finalwindowPos=windowManager.getPosition();// 计算窗口中心finalcenterX=windowPos.x+windowSize.width/2;finalcenterY=windowPos.y+windowSize.height/2;// 判断鼠标是否靠近(距离小于 200px)finaldx=event.screenX-centerX;finaldy=event.screenY-centerY;finaldistance=sqrt(dx*dx+dy*dy);if(distance<200&&!isLookingAtMouse){setState((){isLookingAtMouse=true;});}elseif(distance>=200&&isLookingAtMouse){setState((){isLookingAtMouse=false;});}}@overridevoiddispose(){_blinkController.dispose();_messageTimer?.cancel();windowManager.removeListener(_onMouseMove);super.dispose();}@overrideWidgetbuild(BuildContextcontext){returnScaffold(backgroundColor:Colors.transparent,body:Stack(children:[// 小狐狸本体(可缩放+倾斜看向鼠标)Positioned.fill(child:Transform.scale(scale:1.3,child:Transform.rotate(angle:isLookingAtMouse?-0.2:0,child:Image.asset('assets/images/fox.png',fit:BoxFit.contain),),),),// 眼睛区域(用于模拟眨眼)Positioned(top:60,left:80,right:80,child:Row(mainAxisAlignment:MainAxisAlignment.spaceEvenly,children:[_buildEye(),_buildEye(),],),),// 对话气泡(顶部显示)if(currentMessage!=null)Align(alignment:Alignment.topCenter,child:Padding(padding:constEdgeInsets.only(top:16),child:SpeechBubble(message:currentMessage!),),),],),);}Widget_buildEye(){returnAnimatedBuilder(animation:_blinkController,builder:(context,child){finalheight=lerpDouble(20,5,_blinkController.value)!;returnContainer(width:18,height:height,decoration:BoxDecoration(color:Colors.black,borderRadius:BorderRadius.vertical(top:Radius.elliptical(9,height/2),bottom:Radius.elliptical(9,height/2),),),);},);}}

🎉 最终效果说明

运行flutter run -d macos或 Windows 后,你会看到:

  • 一个半透明窗口中站着一只小狐狸
  • 每隔几秒冒出一句随机对话(持续 3 秒)
  • 眨眼动画自然流畅
  • 当你把鼠标靠近时,它会“害羞地”歪头看你
  • 不占用任务栏,像真正的桌面宠物一样安静陪伴

🔧 技术深挖:Flutter 的隐藏能力

特性用途
transparent: true+frameless实现无边框悬浮窗
window_manager插件控制原生窗口位置、大小、层级
PointerEvent全局监听获取鼠标全局坐标
Transform.rotate+ 动画实现拟人化交互
AnimatedOpacity/AnimationController细粒度控制视觉反馈

这些能力表明:Flutter 不仅适合做 App,也可以用来开发工具类、创意类甚至游戏化桌面程序


🚀 扩展想法(你可以继续做的)

  • 加入语音合成:“说”出来而不是只显示文字
  • 添加拖拽功能:允许用户移动宠物
  • 多角色切换:按快捷键换猫、狗、熊猫
  • “心情系统”:根据时间或用户活动改变行为
  • 打包成独立.exe.app分享给朋友

结语:Flutter 是画笔,不是模板

大多数文章教你“怎么做登录页”、“怎么调接口”,但我们忘了:

技术的本质是创造。

这个“会说话的小狐狸”或许没用,但它有趣、有温度、有生命力 —— 正如 Flutter 给开发者带来的自由感。

下次当你打开编辑器,请记住:

Flutter 不是用来复制别人 App 的工具,
而是你心中奇思妙想落地的桥梁。


📦 依赖清单(pubspec.yaml)

dependencies:flutter:sdk:flutterwindow_manager:^0.4.0

GitHub 示例资源建议包含:

  • fox.png(透明背景 PNG)
  • 完整项目结构截图
  • 编译后的桌面版演示视频(GIF)

“有用的工具千篇一律,有趣的灵魂万里挑一。”
—— 愿你的代码,永远带着一点顽皮。

现在,去让你的应用学会微笑吧 😸欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

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

计算广告:智能时代的营销科学与实践(二十一)

目录 11.2 担保式投送系统 11.2.1 流量预测 11.2.2 频次控制 11.3 在线分配 11.3.1 在线分配问题 11.3.2 在线分配问题举例 11.3.3 极限性能研究 11.3.4 实用优化算法 总结 11.2 担保式投送系统 担保式投送&#xff08;Guaranteed Delivery&#xff0c; GD&#xff09…

作者头像 李华
网站建设 2026/5/11 0:24:03

计算广告:智能时代的营销科学与实践(二十三)

目录 第13章 竞价广告核心技术 13.1 竞价广告计价算法 1. 从密封竞价到广义第二价格&#xff1a;市场的进化 2. VCG拍卖&#xff1a;理论上的完美与现实的差距 3. 计价算法的工程实现与考量 4. 计价的演进&#xff1a;从CPC到oCPX 13.2 搜索广告系统 13.2.1 查询扩展 1…

作者头像 李华
网站建设 2026/5/12 7:10:21

【完整源码+数据集+部署教程】食品物品检测系统源码分享[一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

一、背景意义 随着全球经济的快速发展和生活水平的不断提高&#xff0c;食品消费市场日益繁荣&#xff0c;食品安全问题也随之凸显。食品物品的检测与识别不仅是保障消费者权益的重要环节&#xff0c;也是提升食品产业链效率的关键因素。传统的食品检测方法多依赖人工检查&…

作者头像 李华
网站建设 2026/5/11 8:07:06

Java小白求职互联网大厂:面试官的技术挑战与业务思考

文章简述 在这篇文章中&#xff0c;我们将模拟一个互联网大厂Java小白求职者的面试场景。面试官通过一系列技术问题&#xff0c;考察求职者的Java核心技术、微服务架构、缓存技术、日志处理等能力&#xff0c;并引导其思考实际业务场景中的应用。本文将详细解析每个问题的答案&…

作者头像 李华
网站建设 2026/5/12 8:14:42

函数模板.

闲谈&#xff1a;上一篇初识模板我也只是初略了解&#xff0c;这一次我在整理一下。模板模板是C支持泛型程序设计的工具&#xff0c;通过它可以实现参数化多态性。参数化多态性&#xff1a;就是将程序所处理的对象的类型参数化&#xff0c;使得一段程序可以处理多种不同类型的对…

作者头像 李华
网站建设 2026/5/3 19:46:40

还在卷 AI 编码?别傻了,拖垮你效率的根本不是写代码

提升研发效率的关键&#xff0c;也许不是AI&#xff0c;而是开发者体验最近&#xff0c;整个技术圈都在为 AI 疯狂。我们讨论 AIGC&#xff0c;讨论 AI Agent 如何重塑工作流&#xff0c;但这可能只说对了一半。我们用 AI 加速了“写代码”&#xff0c;但我发现&#xff0c;自己…

作者头像 李华