[英]How to make switch animation of two GridView elements in Flutter
我正在尝试在 Flutter 中的 GridView 的两个元素之间制作切换动画。
我已经尝试过 PositionedTransition,以及带有 Tween 的常规动画。 元素根本没有动画。
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: GridView.count(
shrinkWrap: true,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
crossAxisCount: 5,
children: List.generate(25, (index) {
return GestureDetector(
onVerticalDragUpdate: (drag) {
if (drag.delta.dy > 10) print('down');
if (drag.delta.dy < -10) print('up');
},
onHorizontalDragUpdate: (drag) {
if (drag.delta.dx > 10) print('right');
if (drag.delta.dx < -10) print('left');
},
onHorizontalDragEnd: /* ANIMATE NOW */,
onVerticalDragEnd: /* ANIMATE NOW */,
child: Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.all(Radius.circular(5.0))
),
),
);
}),
)
);
}
}
理想情况下,我希望能够在网格元素上向左/向右/向上/向下滑动,并将该元素与其旁边的相应元素(相对于滑动方向)进行切换。
我放弃了尝试使用 GridView。 然而,我确实找到了一种通过 Stack 和 SlideTransition 获得相同结果的方法:
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
String move;
List<Tween> _switchTween = List();
List<Animation> _switchAnim = List();
List<AnimationController> _switchAnimCont = List();
double width;
@override
void initState() {
// Add a tween and a controller for each element
for (int i = 0; i < 5; i++) {
_switchAnimCont.add(AnimationController(
vsync: this,
duration: const Duration(milliseconds: 100),
));
_switchTween.add(Tween<Offset>(begin: Offset.zero, end: Offset(0, 1)));
_switchAnim.add(_switchTween[i].animate(_switchAnimCont[i]));
}
super.initState();
}
@override
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width/5;
return Stack(
children: <Widget>[
square(0, 0, 0),
square(1, width, 0),
square(2, 2*width, 0),
square(3, 3*width, 0),
square(4, 4*width, 0),
],
);
}
Widget square(int index, double left, double bottom) {
return Positioned(
left: left,
bottom: bottom,
width: width,
height: width,
child: SlideTransition(
position: _switchAnim[index],
child: GestureDetector(
// Figure out swipe's direction
onHorizontalDragUpdate: (drag) {
if (drag.delta.dx > 10) move = 'right';
if (drag.delta.dx < -10) move = 'left';
},
onHorizontalDragEnd: (drag) {
switch(move) {
case 'right' : {moveRight(index); break;}
case 'left' : {moveLeft(index); break;}
}
},
child: Container(
margin: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5.0))
),
),
),
),
);
}
void moveRight(int index) {
// Move the grid element that you swiped on
_switchTween[index].end = Offset(1, 0);
_switchAnimCont[index].forward();
// Move the element next to it the opposite way
_switchTween[index+1].end = Offset(-1, 0);
_switchAnimCont[index+1].forward();
// You could need to refresh the corresponding controller to animate again
}
void moveLeft(int index) {
_switchTween[index].end = Offset(-1, 0);
_switchAnimCont[index].forward();
_switchTween[index-1].end = Offset(1, 0);
_switchAnimCont[index-1].forward();
}
}
这将绘制 5 个白色方块,通过向左或向右滑动其中一个,相应的方块将与旁边的方块交换位置。 它也可以扩展为垂直使用(假设添加了一个新行)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.