【问题标题】:Flutter tween basic animation is not working inside `FutureBuilder`颤振补间基本动画在“FutureBuilder”中不起作用
【发布时间】:2019-05-01 03:34:07
【问题描述】:

Flutter tween 基本动画在 FutureBuilder 内部不起作用

我使用 gridview.builder 创建了一个图片库页面,但由于某种原因,动画在 futurebuilder 中不起作用。我直接在 body 容器内的静态图像上尝试了相同的动画,效果非常好。需要一些方法来为 futurebuilder 中的网络图像设置动画。

class _GalleryGridState extends State<GalleryGrid>
    with TickerProviderStateMixin {
  AnimationController _controller;
  Animation _squeezeOutAnimation, transformationAnim;

  List<GalleryModel> lists = List();

  Future<List<GalleryModel>> fetchPost() async {
    final response =
        await http.get("https://jsonplaceholder.typicode.com/photos");
    if (response.statusCode == 200) {
      var datas = json.decode(response.body);
      lists = (datas as List)
          .map((data) => new GalleryModel.fromJson(data))
          .toList();
      return lists;
    } else {
       throw Exception("Failed to load photos");
    }
  }

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(duration: Duration(seconds: 3), vsync: this);
    transformationAnim = BorderRadiusTween(
            begin: BorderRadius.circular(150.0),
            end: BorderRadius.circular(0.0))
        .animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
    _squeezeOutAnimation = Tween<double>(begin: 150.0, end: 1000.0)
        .animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
  }

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

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: fetchPost(),
      builder: (context, data) {

        switch (data.connectionState) {
          case ConnectionState.waiting:
            return Center(child: CircularProgressIndicator());
          default:
            return GridView.builder(
              gridDelegate:
                  SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
              itemCount: lists.length,
              itemBuilder: (BuildContext context, int index) {
                return Stack(
                  children: <Widget>[
                    Container(
                      child: Card(
                        shape: BeveledRectangleBorder(
                            borderRadius: transformationAnim.value),
                        elevation: 10.0,
                        child: GestureDetector(
                          onTap: () {
                            _controller.forward();
                          },
                          child: Container(
                            width: _squeezeOutAnimation.value,
                            height: _squeezeOutAnimation.value,
                            child: Image.network(
                              lists[index].thumbnailUrl,
                              fit: BoxFit.fill,
                              width: _squeezeOutAnimation.value,
                            ),
                          ),
                        ),
                      ),
                    ),
            ])

【问题讨论】:

    标签: dart flutter flutter-layout dart-pub flutter-animation


    【解决方案1】:

    动画正在运行,但您的构建小部件没有更新,即重建

    试试这个代码,如果它按预期工作,请告诉我。

    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    import 'dart:async';
    import 'dart:convert';
    
    
    void main() => runApp(GalleryGrid());
    
    class GalleryGrid extends StatefulWidget {
      @override
      _GalleryGridState createState() => _GalleryGridState();
    }
    
    class GalleryModel {
      final String thumbnailUrl;
    
      GalleryModel(this.thumbnailUrl);
    
      factory GalleryModel.fromJson(Map<String, dynamic> data) {
        return GalleryModel(data['thumbnailUrl']);
      }
    }
    
    class _GalleryGridState extends State<GalleryGrid>
         {
    
    
      List<GalleryModel> lists = List();
    
      Future<List<GalleryModel>> fetchPost() async {
        final response =
            await http.get("https://jsonplaceholder.typicode.com/photos");
        if (response.statusCode == 200) {
          var datas = json.decode(response.body);
          lists = (datas as List)
              .map((data) => new GalleryModel.fromJson(data))
              .toList();
          return lists;
        } else {
          throw Exception("Failed to load photos");
        }
      }
    
    
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: FutureBuilder(
              future: fetchPost(),
              builder: (context, data) {
                switch (data.connectionState) {
                  case ConnectionState.waiting:
                    return Center(child: CircularProgressIndicator());
                  default:
                    return new GridWidget(lists: lists);
                }
              },
            ),
          ),
        );
        //),
        //);
      }
    }
    
    class GridWidget extends StatefulWidget {
      const GridWidget({
        Key key,
        @required this.lists,
    
      }) ;
    
      final List<GalleryModel> lists;
    
    
      @override
      GridWidgetState createState() {
        return new GridWidgetState();
      }
    }
    
    class GridWidgetState extends State<GridWidget> with TickerProviderStateMixin{
      AnimationController _controller;
      Animation _squeezeOutAnimation, transformationAnim;
      @override
      void initState() {
        super.initState();
        _controller =
            AnimationController(duration: Duration(seconds: 3), vsync: this);
        transformationAnim = BorderRadiusTween(
            begin: BorderRadius.circular(150.0),
            end: BorderRadius.circular(0.0))
            .animate(CurvedAnimation(parent: _controller, curve: Curves.ease))
          ..addListener(() {
            setState(() {});
          });
        _squeezeOutAnimation = Tween<double>(begin: 150.0, end: 1000.0)
            .animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
      }
    
      @override
      void dispose() {
        super.dispose();
        _controller.dispose();
      }
      @override
      Widget build(BuildContext context) {
        return GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2),
          itemCount: widget.lists.length,
          itemBuilder: (BuildContext context, int index) {
            return Stack(children: <Widget>[
              Container(
                child: Card(
                  shape: BeveledRectangleBorder(
                      borderRadius: transformationAnim.value),
                  elevation: 10.0,
                  child: GestureDetector(
                    onTap: () {
                      print('Card $index is pressed');
                      _controller.reset();
                      _controller.forward();
                    },
                    child: Container(
                      width: _squeezeOutAnimation.value,
                      height: _squeezeOutAnimation.value,
                      child: Image.network(
                        widget.lists[index].thumbnailUrl,
                        fit: BoxFit.fill,
                        width: _squeezeOutAnimation.value,
                      ),
                    ),
                  ),
                ),
              ),
            ]);
          },
        );
      }
    }
    

    【讨论】:

    • thanx 兄弟它的工作,bt 现在的问题是所有的图像都在一次动画,我希望点击的项目只有动画,使用当前动画是否可以实现。
    • @rahul.sharma 我想是的,如果你设法将一张卡片提取到它自己的小部件中并将动画相关代码放在那里,我认为它可以工作。试一试,让我知道是否我可以提供更多帮助。
    • 是的,我也在想同样的逻辑,谢谢,我会试一试
    【解决方案2】:

    您可以使用Hero 小部件,它使用标签为您完成了很多工作:

    class HomePage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      List<Image> images;
    
      @override
      void initState() {
        images = new List<Image>();
        images.add(Image.asset("assets/blue.png"));
        images.add(Image.asset("assets/red.png"));
        images.add(Image.asset("assets/green.png"));
        images.add(Image.asset("assets/yellow.png"));
        images.add(Image.asset("assets/pink.png"));
        images.add(Image.asset("assets/cyan.png"));
        // get images
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Material(
            child: GridView.builder(
          gridDelegate:
              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          itemCount: images.length,
          itemBuilder: (context, index) {
            String tag = "Image" + index.toString();
    
            return Hero(
                tag: tag,
                child: Material(
                    child: InkWell(
                  child: GridTile(child: images[index]),
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context) {
                      return Scaffold(
                          appBar: AppBar(title: Text(tag)),
                          body: ImagePage(image: images[index], imageTag: tag));
                    }));
                  },
                )));
          },
        ));
      }
    }
    
    class ImagePage extends StatefulWidget {
      final Image image;
      final String imageTag;
    
      ImagePage({this.image, this.imageTag});
    
      @override
      State<StatefulWidget> createState() => new _ImagePageState();
    }
    
    class _ImagePageState extends State<ImagePage> {
      @override
      Widget build(BuildContext context) {
        return Hero(
          tag: widget.imageTag,
          child: Material(
            child: Center(
              child: widget.image,
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 欣赏它,但我的目标是仅在同一屏幕上弹出点击的图像,帮助我实现它
    • 我尝试在没有futurebuilder的情况下为图像制作动画,效果很好,所以futurebuilder导致动画出现问题。
    猜你喜欢
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 2021-07-07
    • 2021-06-18
    • 1970-01-01
    • 2021-05-25
    • 2020-03-07
    相关资源
    最近更新 更多