Flutter 如何确保小部件在屏幕上可见?
在我的应用程序中,我的一个页面中有一个动画列表。通过按下按钮将项目添加到列表中。当一个项目被插入到列表中时,我会设置滚动视图的动画。有时列表会增长,当列表变得太长时,我怎么能发现一个项目在屏幕上仍然可见Flutter 如何确保小部件在屏幕上可见?,flutter,dart,Flutter,Dart,在我的应用程序中,我的一个页面中有一个动画列表。通过按下按钮将项目添加到列表中。当一个项目被插入到列表中时,我会设置滚动视图的动画。有时列表会增长,当列表变得太长时,我怎么能发现一个项目在屏幕上仍然可见 import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'dart:async'; class AnimatedListSample extends StatefulWid
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),
),
),
),
),
);
}
}
导入“包:flift/foundation.dart”;
进口“包装:颤振/材料.省道”;
导入“dart:async”;
类AnimatedListSample扩展StatefulWidget{
@凌驾
_AnimatedListSampleState createState()=>_AnimatedListSampleState();
}
类_AnimatedListSampleState扩展状态{
最终的GlobalKey _listKey=GlobalKey();
ListModel_列表;
最终ScrollController_controller=ScrollController();
int_nextItem;
@凌驾
void initState(){
super.initState();
_列表=列表模型(
listKey:_listKey,
初始项:[0,1,2],
);
_nextItem=3;
}
Widget\u buildItem(
BuildContext上下文、int索引、动画){
回程心脏病(
动画:动画,
项目:_列表[索引],
);
}
void_insert(){
_list.insert(_list.length,_list.length+1);
计时器(
持续时间(毫秒:300),
()=>_controller.animateTo(
_controller.position.maxScrollExtent,
曲线:Curves.easeIn,
持续时间:常量持续时间(毫秒:300),
));
}
@凌驾
小部件构建(构建上下文){
返回材料PP(
家:脚手架(
appBar:appBar(
标题:文本(“动画列表”),
行动:[
图标按钮(
图标:常量图标(图标。添加圆圈),
按下按钮:_插入,
)
],
),
主体:动画列表(
控制器:_控制器,
键:_listKey,
initialItemCount:_list.length,
itemBuilder:\u buildItem,
),
),
);
}
}
类列表模型{
列表模型({
@需要此.listKey,
Iterable initialItems,
}):assert(listKey!=null),
_项目=列表。从(初始项目??[]);
最终GlobalKey列表键;
最终清单项目;
AnimatedListState获取_animatedList=>listKey.currentState;
无效插入(整数索引,E项){
_项目。插入(索引,项目);
_animatedList.insertItem(索引);
}
int get length=>\u items.length;
E运算符[](整数索引)=>_项[索引];
int indexOf(E项)=>\u项。indexOf(项);
}
类CardItem扩展了无状态小部件{
const CardItem({Key Key,@required this.animation,@required this.item})
:assert(动画!=null),
断言(项!=null&&item>=0),
超级(键:键);
最终动画;
最后一项;
@凌驾
小部件构建(构建上下文){
TextStyle TextStyle=Theme.of(context).textTheme.headline4;
返回大小转换(
轴:轴垂直,
sizeFactor:动画,
儿童:手势检测器(
行为:HitTestBehavior.不透明,
孩子:大小盒子(
身高:80,
孩子:卡片(
颜色:颜色.primaries[项目%Colors.primaries.length],
儿童:中心(
子项:文本('Item$Item',样式:textStyle),
),
),
),
),
);
}
}
您可以使用该包,只要小部件的可见性发生变化,该包就会触发回调。因此,您可以使用VisibilityDetector
小部件包装列表中的每个小部件,并让回调在可见性更改时更改状态。然后,您可以根据应用程序的需要处理可见性更改