Flutter Web中CustomScrollView横向滚动鼠标操作失效求助
问题
我基于Flutter官方的CustomScrollView交互示例,仅添加了scrollDirection: Axis.horizontal属性让条目横向排列,但在Web浏览器中添加大量条目后,无法用鼠标进行横向滚动。
代码如下:
import 'package:flutter/material.dart'; /// Flutter code sample for [CustomScrollView]. void main() => runApp(const CustomScrollViewExampleApp()); class CustomScrollViewExampleApp extends StatelessWidget { const CustomScrollViewExampleApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: CustomScrollViewExample(), ); } } class CustomScrollViewExample extends StatefulWidget { const CustomScrollViewExample({super.key}); @override State<CustomScrollViewExample> createState() => _CustomScrollViewExampleState(); } class _CustomScrollViewExampleState extends State<CustomScrollViewExample> { List<int> top = <int>[]; List<int> bottom = <int>[0]; @override Widget build(BuildContext context) { const Key centerKey = ValueKey<String>('bottom-sliver-list'); return Scaffold( appBar: AppBar( title: const Text('Press on the plus to add items above and below'), leading: IconButton( icon: const Icon(Icons.add), onPressed: () { setState(() { top.add(-top.length - 1); bottom.add(bottom.length); }); }, ), ), body: CustomScrollView( center: centerKey, scrollDirection: Axis.horizontal, // <-- 添加的横向滚动属性 slivers: <Widget>[ SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( alignment: Alignment.center, color: Colors.blue[200 + top[index] % 4 * 100], height: 100 + top[index] % 4 * 20.0, child: Text('Item: ${top[index]}'), ); }, childCount: top.length, ), ), SliverList( key: centerKey, delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( alignment: Alignment.center, color: Colors.blue[200 + bottom[index] % 4 * 100], height: 100 + bottom[index] % 4 * 20.0, child: Text('Item: ${bottom[index]}'), ); }, childCount: bottom.length, ), ), ], ), ); } }
期望实现像默认纵向滚动那样的鼠标操作支持,求解决建议。
解决建议
1. 给横向滚动的子项设置固定宽度
原代码中,SliverList的子Container仅设置了height,没有定义width。横向滚动时,子项需要明确的宽度才能让内容超出视口范围,否则所有子项会挤在一起,没有滚动空间。
修改每个Container,添加width属性,比如:
width: 200.0,
2. 为Web端添加鼠标横向滚动支持
Flutter Web默认不会将鼠标滚轮事件映射到横向滚动,需要自定义ScrollBehavior来开启鼠标交互支持:
- 先创建自定义ScrollBehavior类:
class HorizontalScrollBehavior extends MaterialScrollBehavior { @override Set<PointerDeviceKind> get dragDevices => { PointerDeviceKind.touch, PointerDeviceKind.mouse, }; }
- 用
ScrollConfiguration包裹CustomScrollView,应用这个自定义行为:
body: ScrollConfiguration( behavior: HorizontalScrollBehavior(), child: CustomScrollView( // 原CustomScrollView的配置... ), ),
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:flutter/gestures.dart'; /// Flutter code sample for [CustomScrollView]. void main() => runApp(const CustomScrollViewExampleApp()); class CustomScrollViewExampleApp extends StatelessWidget { const CustomScrollViewExampleApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: CustomScrollViewExample(), ); } } class HorizontalScrollBehavior extends MaterialScrollBehavior { @override Set<PointerDeviceKind> get dragDevices => { PointerDeviceKind.touch, PointerDeviceKind.mouse, }; } class CustomScrollViewExample extends StatefulWidget { const CustomScrollViewExample({super.key}); @override State<CustomScrollViewExample> createState() => _CustomScrollViewExampleState(); } class _CustomScrollViewExampleState extends State<CustomScrollViewExample> { List<int> top = <int>[]; List<int> bottom = <int>[0]; @override Widget build(BuildContext context) { const Key centerKey = ValueKey<String>('bottom-sliver-list'); return Scaffold( appBar: AppBar( title: const Text('点击加号在上下添加条目'), leading: IconButton( icon: const Icon(Icons.add), onPressed: () { setState(() { top.add(-top.length - 1); bottom.add(bottom.length); }); }, ), ), body: ScrollConfiguration( behavior: HorizontalScrollBehavior(), child: CustomScrollView( center: centerKey, scrollDirection: Axis.horizontal, slivers: <Widget>[ SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( alignment: Alignment.center, color: Colors.blue[200 + top[index] % 4 * 100], height: 100 + top[index] % 4 * 20.0, width: 200.0, // 添加固定宽度 child: Text('条目: ${top[index]}'), ); }, childCount: top.length, ), ), SliverList( key: centerKey, delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( alignment: Alignment.center, color: Colors.blue[200 + bottom[index] % 4 * 100], height: 100 + bottom[index] % 4 * 20.0, width: 200.0, // 添加固定宽度 child: Text('条目: ${bottom[index]}'), ); }, childCount: bottom.length, ), ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Alejandro Hellin
相关产品推荐
相关产品推荐

