如何在CustomScrollView的SliverList中实现滚动到指定索引功能?
问题修复方案
核心错误原因
CustomScrollView绑定的是独立的普通ScrollController,和你初始化的用于滚动定位的AutoScrollController完全没有关联,滚动指令无法作用到实际视图- 视口边界计算没有扣除顶部固定的
SliverAppBar高度,会导致滚动定位偏移错误 SliverChildBuilderDelegate未指定childCount,会出现列表条目越界问题
修复后完整代码
import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Scroll To Index Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Scroll To Index Demo'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const maxCount = 100; final random = math.Random(); final scrollDirection = Axis.vertical; late AutoScrollController controller; late List<List<int>> randomList; @override void initState() { super.initState(); controller = AutoScrollController( // 修正视口边界,扣除顶部固定的SliverAppBar高度 viewportBoundaryGetter: () => Rect.fromLTRB(0, kToolbarHeight, 0, MediaQuery.of(context).padding.bottom), axis: scrollDirection); randomList = List.generate( maxCount, (index) => <int>[index, (200 * random.nextDouble()).toInt()]); } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( // 替换为AutoScrollController实例 controller: controller, slivers: [ SliverAppBar( pinned: true, title: Text("App bar"), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) { return Padding( padding: EdgeInsets.all(8), child: _getRow( randomList[index][0], math.max(randomList[index][1].toDouble(), 50.0), ), ); }, // 补充列表总条目数 childCount: maxCount ), ), ], ), floatingActionButton: FloatingActionButton( onPressed: _scrollToIndex, tooltip: 'Increment', child: Text(counter.toString()), ), ); } int counter = -1; Future _scrollToIndex() async { setState(() { counter++; if (counter >= maxCount) counter = 0; }); await controller.scrollToIndex(counter, preferPosition: AutoScrollPosition.begin); controller.highlight(counter); } Widget _getRow(int index, double height) { return _wrapScrollTag( index: index, child: Container( padding: EdgeInsets.all(8), alignment: Alignment.topCenter, height: height, decoration: BoxDecoration( border: Border.all(color: Colors.lightBlue, width: 4), borderRadius: BorderRadius.circular(12)), child: Text('index: $index, height: $height'), ), ); } Widget _wrapScrollTag({required int index, required Widget child}) => AutoScrollTag( key: ValueKey(index), controller: controller, index: index, child: child, highlightColor: Colors.black.withOpacity(0.7), ); }
内容的提问来源于stack exchange,提问作者Enqvida
相关产品推荐
相关产品推荐

