Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimatedList doesn't animate items when inserting or removing to an index that is offscreen. #74031

Open
adendiamond opened this issue Jan 15, 2021 · 9 comments
Labels
f: scrolling Viewports, list views, slivers, etc. found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team

Comments

@adendiamond
Copy link

Hi there,
I have found that AnimatedList doesn't animate items when inserting or removing to an index that is offscreen, i.e. when the surrounding widgets are destroyed (and the widget itself when removing it).

Here is a dartpad to explain:
https://dartpad.dev/3b8f07c4148c78a9284c7806a0608872?
(Please note that this isn't my code, I am having the same issue in my app, this code is from https://medium.com/flutter-community/updating-data-in-an-animatedlist-in-flutter-9dbfb136e515)

Steps to reproduce:

  • Click 'insert single item' 12 times.
  • Scroll to bottom
  • Click 'insert single item' once
    And observe how the behavior is identical to a normal ListView, no animation.

Any help is appreciated!

@xu-baolin xu-baolin added f: scrolling Viewports, list views, slivers, etc. has reproducible steps The issue has been confirmed reproducible and is ready to work on found in release: 1.26 Found to occur in 1.26 labels Jan 15, 2021
@TahaTesser TahaTesser added the framework flutter/packages/flutter repository. See also f: labels. label Jan 15, 2021
@HansMuller
Copy link
Contributor

CC @darrenaustin

@diegoveloper
Copy link
Member

I have a similar issue, the selected item is animated but the others are not. Check this video I captured.

Screen.Recording.2021-08-31.at.5.15.48.PM.mov

This is the code sample:

class _MainPageState extends State<MainPage> {
  final key = GlobalKey<AnimatedListState>();
  final items = List.generate(10, (index) => '$index');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black38,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: [
          SizedBox(
            height: 100,
            child: AnimatedList(
              key: key,
              initialItemCount: items.length,
              scrollDirection: Axis.horizontal,
              itemBuilder: (context, index, animation) => buildItem(items[index], index, animation),
            ),
          ),
          MaterialButton(
            child: Text(
              'Insert item',
              style: TextStyle(fontSize: 15),
            ),
            color: Colors.white,
            onPressed: () => insertItem(0, 'X'),
          ),
          MaterialButton(
            child: Text(
              'Remove item',
              style: TextStyle(fontSize: 15),
            ),
            color: Colors.white,
            onPressed: () => removeItem(0),
          ),
        ],
      ),
    );
  }

  Widget buildItem(String item, int index, Animation<double> animation) => ScaleTransition(
        scale: animation,
        key: ValueKey(item),
        child: Container(
          width: 60,
          margin: EdgeInsets.all(8),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(12),
            color: Colors.white,
          ),
          child: FittedBox(
            child: Text(item),
          ),
        ),
      );

  void insertItem(int index, String item) {
    items.insert(index, item);
    key.currentState.insertItem(index);
  }

  void removeItem(int index) {
    final item = items.removeAt(index);

    key.currentState.removeItem(
      index,
      (context, animation) => buildItem(item, index, animation),
    );
  }
}

And this is my flutter version:

[✓] Flutter (Channel stable, 2.2.2, on macOS 11.5.2 20G95 darwin-x64, locale en-US)

@Piinks Piinks added the P2 Important issues not at the top of the work list label Jun 16, 2022
@narayananulaganathan-cred

seems like this is not fixed yet. on 2.10.3

@diegoveloper were you able to workaround this?

@diegoveloper
Copy link
Member

seems like this is not fixed yet. on 2.10.3

@diegoveloper were you able to workaround this?

I had to use SizeTransition https://youtu.be/KZGi5kgnjbQ?t=917

@narayananulaganathan-cred

hey thanks @diegoveloper ! that worked!

@huycozy
Copy link
Member

huycozy commented Mar 22, 2023

This issue is reproducible on the latest stable and master channels.

Screen.Recording.2023-03-22.at.18.32.19.mov
Sample code (be compatible with the new flutter version)
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: Text('Update AnimatedList data')),
        body: BodyWidget(),
      ),
    );
  }
}

class BodyWidget extends StatefulWidget {
  @override
  BodyWidgetState createState() {
    return new BodyWidgetState();
  }
}

class BodyWidgetState extends State<BodyWidget> {
  // the GlobalKey is needed to animate the list
  final GlobalKey<AnimatedListState> _listKey = GlobalKey(); // backing data
  List<String> _data = ['Horse', 'Cow', 'Camel', 'Sheep', 'Goat'];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 400,
          child: AnimatedList(
            key: _listKey,
            initialItemCount: _data.length,
            itemBuilder: (context, index, animation) {
              return _buildItem(_data[index], animation);
            },
          ),
        ),
        TextButton(
          child: Text(
            'Insert single item',
            style: TextStyle(fontSize: 20),
          ),
          onPressed: () {
            _onButtonPress();
          },
        )
      ],
    );
  }

  Widget _buildItem(String item, Animation<double> animation) {
    return SizeTransition(
      sizeFactor: animation,
      child: Card(
        child: ListTile(
          title: Text(
            item,
            style: TextStyle(fontSize: 20),
          ),
        ),
      ),
    );
  }

  void _onButtonPress() {
    // replace this with method choice below
    _insertSingleItem();
  }

  void _insertSingleItem() {
    String item = "Pig";
    int insertIndex = 2;
    _data.insert(insertIndex, item);
    _listKey.currentState?.insertItem(insertIndex);
  }

  void _insertMultipleItems() {
    final items = ['Pig', 'Chichen', 'Dog'];
    int insertIndex = 2;
    _data.insertAll(insertIndex, items);
    // This is a bit of a hack because currentState doesn't have
    // an insertAll() method.
    for (int offset = 0; offset < items.length; offset++) {
      _listKey.currentState?.insertItem(insertIndex + offset);
    }
  }

  void _removeSingleItems() {
    int removeIndex = 2;
    String removedItem = _data.removeAt(removeIndex);
    // This builder is just so that the animation has something
    // to work with before it disappears from view since the
    // original has already been deleted.
    AnimatedListRemovedItemBuilder builder = (context, animation) {
      // A method to build the Card widget.
      return _buildItem(removedItem, animation);
    };
    _listKey.currentState?.removeItem(removeIndex, builder);
  }

  void _removeMultipleItems() {
    int removeIndex = 2;
    int count = 2;
    for (int i = 0; i < count; i++) {
      String removedItem = _data.removeAt(removeIndex);
      AnimatedListRemovedItemBuilder builder = (context, animation) {
        return _buildItem(removedItem, animation);
      };
      _listKey.currentState?.removeItem(removeIndex, builder);
    }
  }

  void _removeAllItems() {
    final length = _data.length;
    for (int i = length - 1; i >= 0; i--) {
      String removedItem = _data.removeAt(i);
      AnimatedListRemovedItemBuilder builder = (context, animation) {
        return _buildItem(removedItem, animation);
      };
      _listKey.currentState?.removeItem(i, builder);
    }
  }

  void _updateSingleItem() {
    final newValue = 'I like sheep';
    final index = 3;
    setState(() {
      _data[index] = newValue;
    });
  }
}
flutter doctor -v (stable and master)
[✓] Flutter (Channel stable, 3.7.7, on macOS 13.0.1 22A400 darwin-x64, locale en-EE)
    • Flutter version 3.7.7 on channel stable at /Users/huynq/Documents/GitHub/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2ad6cd72c0 (10 hours ago), 2023-03-08 09:41:59 -0800
    • Engine revision 1837b5be5f
    • Dart version 2.19.4
    • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/huynq/Library/Android/sdk
    • Platform android-33, build-tools 31.0.0
    • ANDROID_HOME = /Users/huynq/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14B47b
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[!] Android Studio
    • Android Studio at /Applications/Android Studio Preview.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    ✗ Unable to find bundled Java version.
    • Try updating or re-installing Android Studio.

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
    • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.76.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.60.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 13.0.1 22A400 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 110.0.5481.177

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.
[!] Flutter (Channel master, 3.9.0-12.0.pre.17, on macOS 13.0.1 22A400 darwin-x64, locale en-VN)
    • Flutter version 3.9.0-12.0.pre.17 on channel master at /Users/huynq/Documents/GitHub/flutter_master
    ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
    ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 6b7c60d69a (2 hours ago), 2023-03-20 18:08:51 -0700
    • Engine revision ea6ed14b4e
    • Dart version 3.0.0 (build 3.0.0-345.0.dev)
    • DevTools version 2.22.2
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/huynq/Library/Android/sdk
    • Platform android-33, build-tools 31.0.0
    • ANDROID_HOME = /Users/huynq/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14B47b
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
    • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.76.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.60.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 13.0.1 22A400 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 111.0.5563.64

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.

@huycozy huycozy added found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 and removed found in release: 1.26 Found to occur in 1.26 labels Mar 22, 2023
@ivan-dubovenko-m10
Copy link

I can't insert any after remove, and nothing happend with no errors.

@radomir9720
Copy link

radomir9720 commented May 7, 2023

Hi! I have published my own package recently, that solves this issue. You can try it out, but keep in mind that there are many untested cases so far.

https://pub.dev/packages/animated_scroll_view

@flutter-triage-bot flutter-triage-bot bot added team-framework Owned by Framework team triaged-framework Triaged by Framework team labels Jul 8, 2023
@romawizard
Copy link

Is there any solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
f: scrolling Viewports, list views, slivers, etc. found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team
Projects
None yet
Development

No branches or pull requests