Flutter中同步ListWheelScrollView:FixedExtentScrollPhysics适配难题
解决ListWheelScrollView双向同步滚动(兼容FixedExtentScrollPhysics)
针对两个ListWheelScrollView双向滚动卡顿、linked_scroll_controller不兼容FixedExtentScrollPhysics的问题,直接自己实现同步逻辑即可解决,无需依赖第三方包。
核心解决思路
- 给两个列表分别配置
FixedExtentScrollController,独立控制各自的滚动 - 添加一个布尔标记位,防止同步时触发循环回调(比如A同步B时,B的滚动回调不会反过来再同步A)
- 利用列表的选中项变化回调(或控制器滚动监听),直接调用
jumpToItem同步位置——这个方法比animateToItem更贴合ListWheelScrollView的对齐特性,不会产生动画延迟导致的卡顿
完整代码实现
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: '双向同步列表', theme: ThemeData(primarySwatch: Colors.blue), debugShowCheckedModeBanner: false, home: const SyncListWheelPage(), ); } } class SyncListWheelPage extends StatefulWidget { const SyncListWheelPage({Key? key}) : super(key: key); @override _SyncListWheelPageState createState() => _SyncListWheelPageState(); } class _SyncListWheelPageState extends State<SyncListWheelPage> { final _greenController = FixedExtentScrollController(); final _redController = FixedExtentScrollController(); bool _isSyncing = false; @override void dispose() { _greenController.dispose(); _redController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("双向同步列表"), backgroundColor: Colors.green, ), body: Row( children: [ SizedBox( height: 600, width: 300, child: ListWheelScrollView( itemExtent: 100, physics: const FixedExtentScrollPhysics(), controller: _greenController, onSelectedItemChanged: (index) { if (_isSyncing) return; _isSyncing = true; _redController.jumpToItem(index); _isSyncing = false; }, children: [ for (int i = 0; i < 5; i++) Container( color: Colors.green, height: 50, width: 50, ) ], ), ), SizedBox( height: 600, width: 300, child: ListWheelScrollView( itemExtent: 100, physics: const FixedExtentScrollPhysics(), controller: _redController, onSelectedItemChanged: (index) { if (_isSyncing) return; _isSyncing = true; _greenController.jumpToItem(index); _isSyncing = false; }, children: [ for (int i = 0; i < 5; i++) Container( color: Colors.red, height: 50, width: 50, ) ], ), ), ], ), ); } }
关键细节说明
- 用
onSelectedItemChanged替代滚动监听:这个回调是ListWheelScrollView专门针对选中项变化设计的,比监听控制器滚动更精准,避免不必要的同步触发 _isSyncing标记位:彻底解决双向同步时的循环回调问题,确保只有主动操作的列表才会触发同步jumpToItem方法:直接让目标列表跳转到对应项,完全贴合FixedExtentScrollPhysics的对齐逻辑,滚动过程无卡顿延迟
内容的提问来源于stack exchange,提问作者Ramji
相关产品推荐
相关产品推荐

