1.listview 中只用利用custom才能监听到第一个条目 new ListView.custom( controller: controller, cacheExtent: 1.0, // 只有设置了1.0 才能够准确的标记position 位置 childrenDelegate: MyChildrenDelegate( (BuildContext context, int index) { return new Dismissible( key: new Key(list[index]), onDismissed: (direction) { //被移除回掉 list.removeAt(index); var item = list[index]; Scaffold.of(context).showSnackBar( new SnackBar(content: new Text("$item"))); }, child: new ListTile( title: new Text(list[index]), )); }, childCount: list.length, ), )
2. SliverChildBuilderDelegate
class _SaltedValueKey extends ValueKey<Key>{ const _SaltedValueKey(Key key): assert(key != null), super(key); } class MyChildrenDelegate extends SliverChildBuilderDelegate { MyChildrenDelegate( Widget Function(BuildContext, int) builder, { int childCount, bool addAutomaticKeepAlive = true, bool addRepaintBoundaries = true, }) : super(builder, childCount: childCount, addAutomaticKeepAlives: addAutomaticKeepAlive, addRepaintBoundaries: addRepaintBoundaries); // Return a Widget for the given Exception Widget _createErrorWidget(dynamic exception, StackTrace stackTrace) { final FlutterErrorDetails details = FlutterErrorDetails( exception: exception, stack: stackTrace, library: 'widgets library', context: ErrorDescription('building'), ); FlutterError.reportError(details); return ErrorWidget.builder(details); } @override Widget build(BuildContext context, int index) { assert(builder != null); if (index < 0 || (childCount != null && index >= childCount)) return null; Widget child; try { child = builder(context, index); } catch (exception, stackTrace) { child = _createErrorWidget(exception, stackTrace); } if (child == null) return null; final Key key = child.key != null ? _SaltedValueKey(child.key) : null; if (addRepaintBoundaries) child = RepaintBoundary(child: child); if (addSemanticIndexes) { final int semanticIndex = semanticIndexCallback(child, index); if (semanticIndex != null) child = IndexedSemantics(index: semanticIndex + semanticIndexOffset, child: child); } if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child); return KeyedSubtree(child: child, key: key); } @override void didFinishLayout(int firstIndex, int lastIndex) { // TODO: implement didFinishLayout super.didFinishLayout(firstIndex, lastIndex); } ///监听 在可见的列表中 显示的第一个位置和最后一个位置 @override double estimateMaxScrollOffset(int firstIndex, int lastIndex, double leadingScrollOffset, double trailingScrollOffset) { print('firstIndex sss : $firstIndex, lastIndex ssss : $lastIndex, leadingScrollOffset ssss : $leadingScrollOffset,' 'trailingScrollOffset ssss : $trailingScrollOffset ' ); return super.estimateMaxScrollOffset(firstIndex, lastIndex, leadingScrollOffset, trailingScrollOffset); } }