Flutter - 动画小部件以在点击时从 GridView 移动到 BottomBar

Flutter - Animate a widget to move from GridView to BottomBar upon tapping

我想制作一个图像小部件的动画,使其从网格视图移动到底部栏,如下所示,但要简单得多。谁能为我提供有关如何实现这一目标的任何指导?我倾向于转换动画,但在尝试计算源屏幕点和目标屏幕点时遇到了困难。非常感谢任何帮助。

试试这个包,add_cart_parabola:

import 'dart:ui';
import 'package:add_cart_parabola/add_cart_parabola.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);



  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  GlobalKey floatKey = GlobalKey();
  GlobalKey rootKey = GlobalKey();
  Offset floatOffset ;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      RenderBox renderBox = floatKey.currentContext.findRenderObject();
      floatOffset = renderBox.localToGlobal(Offset.zero);
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text(widget.title),
      ),
      body: Container(
        key: rootKey,
        width: double.infinity,
        height: double.infinity,
        color: Colors.grey,
        child: ListView(
          children: List.generate(40, (index){
            return generateItem(index);
          }).toList(),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.yellow,
        key: floatKey,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
  Widget generateItem(int index){
    Text text = Text("item $index",style: TextStyle(fontSize:
    25),);

    Offset temp;
    return GestureDetector(
      onPanDown: (details){
        temp = new Offset(details.globalPosition.dx, details.globalPosition
            .dy);
      },
      onTap: (){
        Function callback ;
        setState(() {
          OverlayEntry entry = OverlayEntry(
              builder: (ctx){
                return ParabolaAnimateWidget(rootKey,temp,floatOffset,
                    Icon(Icons.cancel,color: Colors.greenAccent,),callback,);
              }
          );

          callback = (status){
            if(status == AnimationStatus.completed){
              entry?.remove();
            }
          };

          Overlay.of(rootKey.currentContext).insert(entry);
        });
      },
      child: Container(
        color: Colors.orange,
        child: text,
      ),
    );
  }
}