command + option + L 格式化代码
option + enter 代码补全
隐式动画用animated开头
补间动画
child: TweenAnimationBuilder(
tween: Tween<double>(begin: 50, end: 100),
duration: const Duration(seconds: 4),
builder: (BuildContext context, double? value, Widget? child) {
return Container(
width: 300,
height: 200,
color: Colors.blue,
child: Center(
child: Text(
"Hi",
style: TextStyle(fontSize: value),
)),
);
}),
Transform.rotate, scale,translate
child: TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: 6.28),
duration: const Duration(seconds: 4),
builder: (BuildContext context, double? value, Widget? child) {
return Container(
width: 300,
height: 200,
color: Colors.blue,
child: Center(
child: Transform.rotate(
angle: value??0,//取值是0--2pi之间,0 -- 6.28
child: const Text(
"Hi",
style: TextStyle(fontSize: 50),
)),
));
}),
例子:
body: Center(
child: Container(
width: 300,
height: 120,
color: Colors.blue,
child: TweenAnimationBuilder(
duration: const Duration(seconds: 1),
tween: Tween<double>(begin: 7, end: 7),
builder: (BuildContext context, double? value, Widget? child) {
final whole = value! ~/ 1;
final decimal = value - whole;
return Stack(children: [
Positioned(
top: -100 * decimal,//0 -> -100
child: Opacity(
opacity: 1 - decimal,//1 -> 0,
child: Text(
"$whole",
style: const TextStyle(fontSize: 100),
),
),
),
Positioned(
top: 100 - decimal * 100,//100 -> 0,
child: Opacity(
opacity: decimal,// 0 -> 1,
child: Text(
"${whole + 1}",
style: const TextStyle(fontSize: 100),
),
),
),
]);
},
),
),
),
上下滚动的计数器:
class Counter extends StatelessWidget {
final int value;
final Duration duration;
const Counter({required this.duration, required this.value, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
duration: duration,
tween: Tween<double>(end: value.toDouble()),
builder: (BuildContext context, double? value, Widget? child) {
final whole = value! ~/ 1;
final decimal = value - whole;
return Stack(children: [
Positioned(
top: -100 * decimal, //0 -> -100
child: Opacity(
opacity: 1 - decimal, //1 -> 0,
child: Text(
"$whole",
style: const TextStyle(fontSize: 100),
),
),
),
Positioned(
top: 100 - decimal * 100, //100 -> 0,
child: Opacity(
opacity: decimal, // 0 -> 1,
child: Text(
"${whole + 1}",
style: const TextStyle(fontSize: 100),
),
),
),
]);
},
);
}
}
显式动画用Transition结尾
FadeTransition, RotationTransition, ScaleTransition, SlideTransition
都可以使用AnimationController, 默认值是 0 — 1。
AnimationController 的使用:
repeat(reverse: true) 重置动画。
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController? _controller;
bool _loading = false;
@override
void initState() {
_controller = AnimationController(
//转两圈
lowerBound: 3.0,
upperBound: 5.0,
vsync: this,
duration: const Duration(seconds: 1),
);
super.initState();
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: RotationTransition(
turns: _controller!,
child: const Icon(
Icons.refresh,
size: 100,
)),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if(!_loading){
_controller!.repeat();
}else{
_controller!.stop();
}
_loading = !_loading;
},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
自动生成带有AnimationController的代码;
controller和tween一起使用:
turns: _controller!.drive(Tween(begin: 0.5, end: 2.0)),
x轴移动10%
child: SlideTransition(
position: _controller!.drive(Tween(begin: const Offset(0,0), end: const Offset(0.1,0))),
child: const Icon(
Icons.refresh,
size: 100,
)),
position: Tween(begin: const Offset(0,0), end: const Offset(0.1,0)).animate(_controller!),