我能找到的所有动画小部件示例都需要有状态小部件,并在调用 setState 来更改字段值时以动画方式进行更改。有没有办法将 StreamBuilder 与动画结合起来?
我尝试将动画小部件放入流构建器的构建方法中,但这不会产生任何动画,因为它会在每次更改时创建一个新的动画小部件,并且看不到任何过渡。我本来希望在动画小部件上找到一个可选的“流”参数,以告诉它在新值到达流时进行动画处理。我可以向此示例添加什么以使其在值更改之间产生动画效果? (例如简单的线性过渡)。
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder(
stream: DataStreamSource().dataStream,
initialData: 50,
builder: (BuildContext buildContext, AsyncSnapshot<int> snapshot) {
return InkWell(onTap: DataStreamSource().generate, child: Container(height: snapshot.data?.toDouble(), width: snapshot.data?.toDouble(), color: Colors.deepOrange));
})));
}
}
class DataStreamSource {
static final DataStreamSource _instance = DataStreamSource._internal();
factory DataStreamSource() => _instance;
DataStreamSource._internal();
final BehaviorSubject<int> _dataController = BehaviorSubject();
Stream<int> get dataStream => _dataController.stream;
void generate() => _dataController.add(Random().nextInt(100) + 100);
}
在您提供的示例中,您只需将
Container
更改为 AnimatedContainer
即可“正常工作”:
StreamBuilder(
stream: DataStreamSource().dataStream,
initialData: 50,
builder: (BuildContext buildContext, AsyncSnapshot<int> snapshot) {
return InkWell(
onTap: DataStreamSource().generate,
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
height: snapshot.data?.toDouble(),
width: snapshot.data?.toDouble(),
color: Colors.deepOrange,
),
);
},
);
流触发重建后,Flutter 将
AnimatedContainer
的状态与 AnimatedContainer
的新实例进行匹配。然后该状态发现宽度和高度值已更改并执行动画。 Flutter 能够将状态与 widget 的每个更新版本实例相匹配,因为 widget 树每次都具有相同的结构。如果您有一个更复杂的用例,涉及可以替换的小部件、具有多个相同类型的同级部件等,您可能需要使用键来保持一切正常工作。请参阅此视频了解更多详情。