发文时间:2022年04月18日 10:36:07 编辑:Aaron 标签:Flutter异步(Async) 图文详解系列 1283
结合streamBuilder一个键盘小游戏,通过小键盘发出的触摸时间做出对应的响应等,以及StreamTransformer的使用详解。
期间有写到关于StreamTransformer(数据流变形器)的使用方式,详细请看代码~
import 'dart:async'; import 'dart:ffi'; import 'dart:math'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Aaron', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override void initState() { print('已热加载APP'); super.initState(); } @override void dispose() { //销毁时关闭stream _InputController.close(); super.dispose(); } //键盘输入的stream流 (广播) final _InputController = StreamController.broadcast(); final _scoreController = StreamController.broadcast(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: StreamBuilder( /* todo计分的方式很多,如监听_InputController流的数据、 或单独拉一个stf动态widget,或增加变量setState等 以下用transform的方式去做,使其性能在低消耗的情况下 形成数据的监听 和值改变等 this._scoreController.stream.transform(TallyTransformer()) 相当于把当前监听的stream转换成我们自己转后的数据 */ stream: this._scoreController.stream.transform(TallyTransformer()), builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) { if (snapshot.hasData) { return Text( 'Score分数:${snapshot.data}', style: TextStyle(fontSize: 24), ); } return Text( 'Score分数:0', style: TextStyle(fontSize: 24), ); }, ), ), body: Stack( children: [ //数字题目 ...把list拆分出来 ...List.generate( 10, (index) => Puzzle( inputStream: _InputController.stream, scoreStream: _scoreController, ), ), Align( //输入答案 alignment: Alignment.bottomCenter, child: KeyPad(this._InputController), ), ], ), ); } } //处理当前分数汇总 (处理数据流之间的变化 StreamTransformer) class TallyTransformer implements StreamTransformer { int sum = 0; StreamController _controller = StreamController(); @override Stream bind(Stream stream) { /* bind 数据流刚开始接入的时候 给的是初始时的数据流 目的是把初始的数据流转换成我们所需的数据流 后而返回 */ //源头stream stream.listen((event) { //在这里可以做很多很多操作 sum += event; _controller.add(sum); }); //返回的stream return _controller.stream; } //cast 为stream类型检查 @override StreamTransformer<RS, RT> cast<RS, RT>() => StreamTransformer.castFrom(this); //让其自动做检查 } //题目 class Puzzle extends StatefulWidget { //inputStream键盘输入的值 final inputStream; final scoreStream; const Puzzle({Key key, this.inputStream, this.scoreStream}) : super(key: key); @override _PuzzleState createState() => _PuzzleState(); } //with 动画SingleTickerProviderStateMixin class _PuzzleState extends State<Puzzle> with SingleTickerProviderStateMixin { int a, b; Color color; double x; AnimationController _controller; //重新初始化 reset([from = 0.0]) { a = Random().nextInt(5) + 1; b = Random().nextInt(5); x = Random().nextDouble() * 320; color = Colors.primaries[Random().nextInt(Colors.primaries.length)][200]; _controller.duration = Duration(milliseconds: Random().nextInt(5000) + 5000); //让动画循环,from _controller.forward(from: from); } @override void initState() { //初始化动画 _controller = AnimationController( vsync: this, ); //重置动画 0.0-1.0 让其随机起始位 让动画随机在起始位或者在中间显示 reset(Random().nextDouble()); //当动画停止的时候重置下题目和让组件回到初始位置 _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { //减分 widget.scoreStream.add(-1); reset(); } }); //监听当前用户键盘的输入值 widget.inputStream.listen((input) { if (input == a + b) { //加分 widget.scoreStream.add(1); reset(); } }); super.initState(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, child) { return Positioned( left: x, top: 680 * _controller.value - 100, child: Container( decoration: BoxDecoration( color: color.withOpacity(0.5), //半透明 (Opacity透明组件) border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(24), ), padding: EdgeInsets.all(8.0), child: Text( "$a+$b", style: TextStyle(fontSize: 24), ), ), ); }, ); } } //键盘 class KeyPad extends StatelessWidget { final StreamController _controller; KeyPad(this._controller, {Key key}) : super(key: key); @override Widget build(BuildContext context) { return GridView.count( shrinkWrap: true, //不让GridView上下占满 padding: EdgeInsets.all(0.0), //取消默认下方留空(默认底部适配小白条啥的) physics: NeverScrollableScrollPhysics(), //让GridView不能滚动 childAspectRatio: 2 / 1, crossAxisCount: 3, children: List.generate(9, (index) { // ignore: deprecated_member_use return FlatButton( shape: RoundedRectangleBorder(), //取消圆角边 color: Colors.primaries[index][200], onPressed: () { _controller.add(index + 1); }, child: Text('${index + 1}', style: TextStyle(fontSize: 24))); }), ); } }
若无特殊说明,此文章为博主原创。 写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/55.html
Flutter教程- Async(五) 通过stream做一个小游戏
发文时间:2022年04月18日 10:36:07 编辑:Aaron 标签:Flutter异步(Async) 图文详解系列 1283
结合streamBuilder一个键盘小游戏,通过小键盘发出的触摸时间做出对应的响应等,以及StreamTransformer的使用详解。
期间有写到关于StreamTransformer(数据流变形器)的使用方式,详细请看代码~
若无特殊说明,此文章为博主原创。
写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/55.html