Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scrolling to the end of a AnimatedList

Tags:

flutter

dart

I have a scrollable AnimatedList and I want whenever a new item is added to the end of the list, it would scroll to the end.

I try to apply this code form ListView but it doesn't work.

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  List<String> list = ["a", "a", "a", "a", "a", "a", "a"];
  final ScrollController _listScrollController = new ScrollController();
  final GlobalKey<AnimatedListState> _listKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: AnimatedList(
          key: _listKey,
          controller: _listScrollController,
          initialItemCount: list.length,
          itemBuilder: (BuildContext context, int index, Animation animation) {
            return FadeTransition(
              opacity: animation,
              child: Container(
                width: itemSize,
                height: itemSize,
                child: Text(list[index]),
              ),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(onPressed: _addNewItem),
    );
  }

  _addNewItem() {
    list.add(list.length.toString());
    _listKey.currentState.insertItem(
      list.length - 1,
      duration: Duration(seconds: 1),
    );

    _listScrollController.animateTo(
      _listScrollController.position.maxScrollExtent, // wrong value (this value is before add new item)
      duration: const Duration(milliseconds: 250),
      curve: Curves.ease,
    );
  }
}

So I need to change the scroll code a little bit.

const double itemSize = 40.0;

_listScrollController.animateTo(
   _listScrollController.position.maxScrollExtent + itemSize,
   duration: const Duration(milliseconds: 250),
   curve: Curves.ease,
);

But it need itemSize to hardcode(itemSize) or use BuildLayout, RenderBox to determine new item size. Do you guys have any better solutions?

like image 646
ltvu93 Avatar asked Jan 27 '23 11:01

ltvu93


1 Answers

The issue is you were animating the stuff before adding the item. You were taking a duration of 1s to add item, use this timer that will run after 1s.

Timer(
  Duration(milliseconds: 1100),
  () {
    _listScrollController.animateTo(
      _listScrollController.position.maxScrollExtent,
      duration: const Duration(milliseconds: 250),
      curve: Curves.ease,
    );
  },
);

Replace yours with mine.

_addNewItem() {
  list.add(list.length.toString());
  _listKey.currentState.insertItem(
    list.length - 1,
    duration: Duration(milliseconds: 200),
  );

  Timer(
    Duration(milliseconds: 220),
    () {
      _listScrollController.animateTo(
        _listScrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 500),
        curve: Curves.ease,
      );
    },
  );
}

Output:

enter image description here

like image 111
CopsOnRoad Avatar answered Feb 05 '23 22:02

CopsOnRoad