如何确保窗口小部件在屏幕上可见?

时间:2020-07-19 12:42:49

标签: flutter dart

在我的应用程序中,我的一个页面中有一个AnimatedList。按下按钮将项目添加到列表中。将项目插入列表时,为 scrollView 设置动画。有时列表变长了。如何找到列表太长时某个项目仍无法在屏幕上看到的东西?

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

1 个答案:

答案 0 :(得分:1)

您可以使用visibility_detector软件包,该软件包会在小部件的可见性发生变化时触发回调。因此,您可以使用VisibilityDetector小部件包装列表中的每个小部件,并随着可见性的更改使回调更改状态。然后,您可以根据自己的应用程序来处理可见性更改。