Flutter tween basic animation is not working inside `FutureBuilder`

Issue

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

Answered By – Saed Nabil

Answer Checked By – Mary Flores (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.