Flutter 如何在点击按钮时为 matrix4 翻译设置动画
Flutter how to animate matrix4 translate when button is tapped
我有 2 个按钮,用于控制 InteractiveViewer 小部件的左右滚动,希望在我对 matrix4Tween 有了更好的了解后,我可以自己添加上下滚动
现在按钮就是这样
Row(
children: [
ElevatedButton(
onPressed: () {
controller.value = Matrix4.identity()..translate(0.0, 0.0);
},
child: Text('<'),
),
ElevatedButton(
onPressed: () {
controller.value = Matrix4.identity()..translate(-(width), 0.0);
},
child: Text('>'),
),
],
),
下面是一个包含 4 个 gridview
的 interactiveViewer 小部件
Container(
color: Colors.grey,
width: gridboxwidth,
height: gridboxheight,
child: InteractiveViewer(
alignPanAxis: true,
constrained: false,
transformationController: controller,
scaleEnabled: true,
minScale: 0.1,
maxScale: 1,
child: Column(
children: [
Row(
children: [
grid1(size),
grid3(size),
],
),
Row(
children: [
grid2(size),
grid4(size),
],
),
],
),
),
),
它工作得很好,点击按钮,网格就会进入视图,但我认为它不够直观,可能需要添加一些动画来显示网格已经改变。
非常感谢任何帮助和指导。
这是一个使用Matrix4Tween
的示例小部件,重要的代码行标有// NOTE:
注释:
class FooInteractiveViewer extends StatefulWidget {
@override
_FooInteractiveViewerState createState() => _FooInteractiveViewerState();
}
class _FooInteractiveViewerState extends State<FooInteractiveViewer> with TickerProviderStateMixin {
AnimationController _ctrl;
Animation<Matrix4> _matrixAnimation = AlwaysStoppedAnimation(Matrix4.identity());
final _transformationController = TransformationController();
@override
void initState() {
super.initState();
_ctrl = AnimationController(
vsync: this,
duration: Duration(milliseconds: 500),
)
// NOTE: add listener to be called each time _ctrl changes
..addListener(_listener);
}
void _listener() {
print(MatrixUtils.transformPoint(_matrixAnimation.value, Offset.zero));
// NOTE: this is the most important part of this code:
_transformationController.value = _matrixAnimation.value;
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return InteractiveViewer(
// panEnabled: false,
alignPanAxis: true,
constrained: false,
transformationController: _transformationController,
child: SizedBox(
width: constraints.maxWidth * 2,
height: constraints.maxHeight * 2,
child: Column(
children: [
Expanded(
child: Row(
children: [
button(Colors.red, constraints.biggest, 1, 0, 'green'),
button(Colors.green, constraints.biggest, 0, 1, 'blue'),
],
),
),
Expanded(
child: Row(
children: [
button(Colors.blue, constraints.biggest, 1, 1, 'orange'),
button(Colors.orange, constraints.biggest, 0, 0, 'red'),
],
),
),
],
),
)
);
},
);
}
Widget button(Color color, Size size, int x, int y, String name) {
return Expanded(
child: Material(
color: color,
child: InkWell(
onTap: () async {
// timeDilation = 10;
// NOTE: create new Animation<Matrix4> that will be used inside _listener
_matrixAnimation = Matrix4Tween(
begin: _transformationController.value,
end: Matrix4.translationValues(-size.width * x, -size.height * y, 0)
).chain(CurveTween(curve: Curves.decelerate)).animate(_ctrl);
// NOTE: lets start the show
await _ctrl.forward(from: 0);
print('### animation finished ###');
},
child: Center(child: Text('go to $name', textScaleFactor: 2)),
),
),
);
}
@override
void dispose() {
super.dispose();
_ctrl.dispose();
}
}
我有 2 个按钮,用于控制 InteractiveViewer 小部件的左右滚动,希望在我对 matrix4Tween 有了更好的了解后,我可以自己添加上下滚动
现在按钮就是这样
Row(
children: [
ElevatedButton(
onPressed: () {
controller.value = Matrix4.identity()..translate(0.0, 0.0);
},
child: Text('<'),
),
ElevatedButton(
onPressed: () {
controller.value = Matrix4.identity()..translate(-(width), 0.0);
},
child: Text('>'),
),
],
),
下面是一个包含 4 个 gridview
的 interactiveViewer 小部件 Container(
color: Colors.grey,
width: gridboxwidth,
height: gridboxheight,
child: InteractiveViewer(
alignPanAxis: true,
constrained: false,
transformationController: controller,
scaleEnabled: true,
minScale: 0.1,
maxScale: 1,
child: Column(
children: [
Row(
children: [
grid1(size),
grid3(size),
],
),
Row(
children: [
grid2(size),
grid4(size),
],
),
],
),
),
),
它工作得很好,点击按钮,网格就会进入视图,但我认为它不够直观,可能需要添加一些动画来显示网格已经改变。
非常感谢任何帮助和指导。
这是一个使用Matrix4Tween
的示例小部件,重要的代码行标有// NOTE:
注释:
class FooInteractiveViewer extends StatefulWidget {
@override
_FooInteractiveViewerState createState() => _FooInteractiveViewerState();
}
class _FooInteractiveViewerState extends State<FooInteractiveViewer> with TickerProviderStateMixin {
AnimationController _ctrl;
Animation<Matrix4> _matrixAnimation = AlwaysStoppedAnimation(Matrix4.identity());
final _transformationController = TransformationController();
@override
void initState() {
super.initState();
_ctrl = AnimationController(
vsync: this,
duration: Duration(milliseconds: 500),
)
// NOTE: add listener to be called each time _ctrl changes
..addListener(_listener);
}
void _listener() {
print(MatrixUtils.transformPoint(_matrixAnimation.value, Offset.zero));
// NOTE: this is the most important part of this code:
_transformationController.value = _matrixAnimation.value;
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return InteractiveViewer(
// panEnabled: false,
alignPanAxis: true,
constrained: false,
transformationController: _transformationController,
child: SizedBox(
width: constraints.maxWidth * 2,
height: constraints.maxHeight * 2,
child: Column(
children: [
Expanded(
child: Row(
children: [
button(Colors.red, constraints.biggest, 1, 0, 'green'),
button(Colors.green, constraints.biggest, 0, 1, 'blue'),
],
),
),
Expanded(
child: Row(
children: [
button(Colors.blue, constraints.biggest, 1, 1, 'orange'),
button(Colors.orange, constraints.biggest, 0, 0, 'red'),
],
),
),
],
),
)
);
},
);
}
Widget button(Color color, Size size, int x, int y, String name) {
return Expanded(
child: Material(
color: color,
child: InkWell(
onTap: () async {
// timeDilation = 10;
// NOTE: create new Animation<Matrix4> that will be used inside _listener
_matrixAnimation = Matrix4Tween(
begin: _transformationController.value,
end: Matrix4.translationValues(-size.width * x, -size.height * y, 0)
).chain(CurveTween(curve: Curves.decelerate)).animate(_ctrl);
// NOTE: lets start the show
await _ctrl.forward(from: 0);
print('### animation finished ###');
},
child: Center(child: Text('go to $name', textScaleFactor: 2)),
),
),
);
}
@override
void dispose() {
super.dispose();
_ctrl.dispose();
}
}