Reputation: 912
In my Application, I have an AnimatedList in one of my pages. Items are being added to the list by pressing a button. I animate the scrollView when an Item is being inserted to the list. Sometimes the list grows How can I find out than an Item is still visible on the screen at a moment when the list gets too long?
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
class AnimatedListSample extends StatefulWidget {
@override
_AnimatedListSampleState createState() => _AnimatedListSampleState();
}
class _AnimatedListSampleState extends State<AnimatedListSample> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
ListModel<int> _list;
final ScrollController _controller = ScrollController();
int _nextItem;
@override
void initState() {
super.initState();
_list = ListModel<int>(
listKey: _listKey,
initialItems: <int>[0, 1, 2],
);
_nextItem = 3;
}
Widget _buildItem(
BuildContext context, int index, Animation<double> animation) {
return CardItem(
animation: animation,
item: _list[index],
);
}
void _insert() {
_list.insert(_list.length, _list.length + 1);
Timer(
Duration(milliseconds: 300),
() => _controller.animateTo(
_controller.position.maxScrollExtent,
curve: Curves.easeIn,
duration: const Duration(milliseconds: 300),
));
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('AnimatedList'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_circle),
onPressed: _insert,
)
],
),
body: AnimatedList(
controller: _controller,
key: _listKey,
initialItemCount: _list.length,
itemBuilder: _buildItem,
),
),
);
}
}
class ListModel<E> {
ListModel({
@required this.listKey,
Iterable<E> initialItems,
}) : assert(listKey != null),
_items = List<E>.from(initialItems ?? <E>[]);
final GlobalKey<AnimatedListState> listKey;
final List<E> _items;
AnimatedListState get _animatedList => listKey.currentState;
void insert(int index, E item) {
_items.insert(index, item);
_animatedList.insertItem(index);
}
int get length => _items.length;
E operator [](int index) => _items[index];
int indexOf(E item) => _items.indexOf(item);
}
class CardItem extends StatelessWidget {
const CardItem({Key key, @required this.animation, @required this.item})
: assert(animation != null),
assert(item != null && item >= 0),
super(key: key);
final Animation<double> animation;
final int item;
@override
Widget build(BuildContext context) {
TextStyle textStyle = Theme.of(context).textTheme.headline4;
return SizeTransition(
axis: Axis.vertical,
sizeFactor: animation,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
child: SizedBox(
height: 80,
child: Card(
color: Colors.primaries[item % Colors.primaries.length],
child: Center(
child: Text('Item $item', style: textStyle),
),
),
),
),
);
}
}
Upvotes: 3
Views: 4538
Reputation: 17123
You can use the visibility_detector
package, which fires a callback whenever the visibility of a widget changes. So you can wrap each of the widgets in your list with the VisibilityDetector
widget and have the callback change the state as the visibility changes. You can then handle visibility changes however you need based on your application.
Upvotes: 7