【问题标题】:How to make switch animation of two GridView elements in Flutter如何在 Flutter 中制作两个 GridView 元素的切换动画
【发布时间】:2023-03-07 01:59:01
【问题描述】:

我正在尝试在 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))
                ),
              ),
            );
          }),
        )
    );
  }

}

理想情况下,我希望能够在网格的一个元素上向左/向右/向上/向下滑动,并将该元素与旁边的相应元素切换(相对于滑动方向)。

【问题讨论】:

    标签: animation gridview flutter grid


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      你可以使用 drag_and_drop_gridview

      【讨论】:

        猜你喜欢
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 2017-03-31
        • 2013-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多