AnimationBuilder 和 FutureBuilder - 如何在未来 returns 和构建之后执行动画?

AnimationBuilder with FutureBuilder - How to execute animation after future returns and builds?

我正在调用 api 来获取一些数据,然后我想在(从底部)显示它的小部件中设置动画。每部分的代码都是单独工作的,但我似乎无法弄清楚在 FutureBuilder 从其构建器函数返回后如何执行动画?我在哪里或如何调用 cardController.forward()?

 Widget mapCard(Area area) {
return Align(
  alignment: Alignment.bottomCenter,
  child: AnimatedBuilder(
    builder: (BuildContext context, Widget child) {
      return InkWell(
        onTap: () {
          Navigator.of(context).push(_createHeroRoute(area));
        },
        child: Container(
          margin: cardMargin.value,
          width: 300,
          height: 150,
          child: Hero(
            tag: 'location',
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Container(
                    width: 274,
                    height: 150,
                    child: Image.network(area.images[0].url,
                        fit: BoxFit.cover)),
                Align(
                    alignment: Alignment.centerRight,
                    child: Container(
                        height: 150,

                        //30, 42, 65
                        // 412A1E
                        decoration: new BoxDecoration(
                          color: Color.fromARGB(255, 30, 42, 65),
                        ),
                        child:
                            Icon(Icons.arrow_right, color: Colors.white))),
              ],
            ),
          ),
        ),
      );
    },
    animation: cardController,

  ),
);
}

在构建堆栈中:

FutureBuilder(
                  future: fArea,
                  builder: (context, AsyncSnapshot<Area> snap) {
                    if (snap.hasData) {
                      return mapCard(snap.data);
                    } else {
                      return Text('here');
                    }
                  })

您可以复制粘贴 运行 下面的完整代码
您可以将 MapCard 设为 StatefulWidget 并在 initState

中调用 cardController.forward
@override
  void initState() {
    super.initState();
    cardController =
        AnimationController(duration: const Duration(seconds: 10), vsync: this);
    animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
      ..addStatusListener((state) => print('$state'));
    cardController.forward();
  }

工作演示

完整代码

import 'package:flutter/material.dart';
import 'dart:math' as math;

class MapCard extends StatefulWidget {
  Area area;
  MapCard(Area data, {Key key}) : super(key: key);

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

class _MapCardState extends State<MapCard> with TickerProviderStateMixin {
  AnimationController cardController;
  Animation<double> animation;

  @override
  void initState() {
    super.initState();
    cardController =
        AnimationController(duration: const Duration(seconds: 10), vsync: this);
    animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
      ..addStatusListener((state) => print('$state'));
    cardController.forward();
  }

  @override
  void dispose() {
    cardController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: AlignmentDirectional.bottomCenter,
      child: AnimatedBuilder(
        animation: cardController,
        child: InkWell(
          onTap: () {
            //Navigator.of(context).push(_createHeroRoute(area));
          },
          child: Container(
            //margin: cardMargin.value,
            width: 300,
            height: 150,
            child: Hero(
              tag: 'location',
              child: Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Container(
                      width: 274,
                      height: 150,
                      child: Image.network("https://picsum.photos/250?image=9",
                          fit: BoxFit.cover)),
                  Align(
                      alignment: Alignment.centerRight,
                      child: Container(
                          height: 150,

                          //30, 42, 65
                          // 412A1E
                          decoration: new BoxDecoration(
                            color: Color.fromARGB(255, 30, 42, 65),
                          ),
                          child: Icon(Icons.arrow_right, color: Colors.white))),
                ],
              ),
            ),
          ),
        ),
        builder: (BuildContext context, Widget child) {
          return Transform.translate(
            offset: Offset(0, animation.value),
            child: child,
          );
        },
      ),
    );
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      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 Area {
  String data;
  Area(this.data);
}

class _MyHomePageState extends State<MyHomePage> {
  Future<Area> fArea;

  Future<Area> getArea() async {
    await Future.delayed(Duration(seconds: 3), () {});
    return Future.value(Area("data"));
  }

  @override
  void initState() {
    fArea = getArea();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: FutureBuilder(
            future: fArea,
            builder: (context, AsyncSnapshot<Area> snap) {
              switch (snap.connectionState) {
                case ConnectionState.none:
                  return Text('none');
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                case ConnectionState.active:
                  return Text('');
                case ConnectionState.done:
                  if (snap.hasData) {
                    return MapCard(snap.data);
                  } else {
                    return Center(child: CircularProgressIndicator());
                  }
              }
            }));
  }
}