繁体   English   中英

如何在 Flutter 中制作两个 GridView 元素的切换动画

[英]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 个白色方块,通过向左或向右滑动其中一个,相应的方块将与旁边的方块交换位置。 它也可以扩展为垂直使用(假设添加了一个新行)。

您可以使用drag_and_drop_gridview

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM