Search code examples
dartflutterflutter-layoutdart-pubflutter-animation

Flutter tween basic animation is not working inside `FutureBuilder`


Flutter tween basic animation is not working inside FutureBuilder

I have created a image gallery page using gridview.builder , but the animation doesnt works inside futurebuilder for some reason. I tried same animation on an static image directly inside the container of the body and it worked perfectly fine.Need some way to animate network images inside 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,
                            ),
                          ),
                        ),
                      ),
                    ),
            ])

Solution

  • The animation is running but your build widget is not updating i.e. rebuild

    try this code if it works as you expected let me know.

    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,
                      ),
                    ),
                  ),
                ),
              ),
            ]);
          },
        );
      }
    }