我们之前已经介绍过RotatedBox,但是它有两个缺点:一是只能将其子节点以90度的倍数旋转,二是当旋转的角度发生变化时,旋转角度更新过程没有动画。
本节我们将实现一个TurnBox,它可以以任意角度来旋转其子节点,并且在角度发生变化时可以执行一个动画过渡到新状态,同时,我们可以手动指定动画速度。
TurnBox的完整代码如下:
import 'package:flutter/widgets.dart';
class TurnBox extends StatefulWidget {
const TurnBox({
Key key,
this.turns = .0, //旋转的“圈”数,一圈为360度,如0.25圈即90度
this.speed = 200, //过渡动画执行的总时长
this.child
}) :super(key: key);
final double turns;
final int speed;
final Widget child;
@override
_TurnBoxState createState() => new _TurnBoxState();
}
class _TurnBoxState extends State<TurnBox>
with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this,
lowerBound: -double.infinity,
upperBound: double.infinity
);
_controller.value = widget.turns;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return RotationTransition(
turns: _controller,
child: widget.child,
);
}
@override
void didUpdateWidget(TurnBox oldWidget) {
super.didUpdateWidget(oldWidget);
//旋转角度发生变化时执行过渡动画
if (oldWidget.turns != widget.turns) {
_controller.animateTo(
widget.turns,
duration: Duration(milliseconds: widget.speed??200),
curve: Curves.easeOut,
);
}
}
}
代码比较简单,我们主要是通过包装(组合)RotationTransition来实现的。
下面我们测试一下TurnBox的功能,测试代码如下:
import 'package:flutter/material.dart';
import '../widgets/index.dart';
class TurnBoxRoute extends StatefulWidget {
@override
_TurnBoxRouteState createState() => new _TurnBoxRouteState();
}
class _TurnBoxRouteState extends State<TurnBoxRoute> {
double _turns = .0;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
TurnBox(
turns: _turns,
speed: 500,
child: Icon(Icons.refresh, size: 50,),
),
TurnBox(
turns: _turns,
speed: 1000,
child: Icon(Icons.refresh, size: 150.0,),
),
RaisedButton(
child: Text("顺时针旋转1/5圈"),
onPressed: () {
setState(() {
_turns += .2;
});
},
),
RaisedButton(
child: Text("逆时针旋转1/5圈"),
onPressed: () {
setState(() {
_turns -= .2;
});
},
)
],
),
);
}
}
测试代码运行后效果如下图:
当我们点击旋转按钮时,两个图标的旋转都会旋转1/5圈,但旋转的速度是不同的,读者可以自己运行一下示例看看效果。