当我使用 ListView 时,ListTile OnTap 正在工作。但是当我使用 ListWheelScrollView 它不起作用
Posted
技术标签:
【中文标题】当我使用 ListView 时,ListTile OnTap 正在工作。但是当我使用 ListWheelScrollView 它不起作用【英文标题】:ListTile OnTap is working when I use ListView. But when i use ListWheelScrollView it doesnt work 【发布时间】:2019-10-08 21:04:37 【问题描述】:当我使用 ListView 时,ListTile OnTap 正在工作。但是当我使用 ListWheelScrollView 时它不起作用。我的意思是它不会被窃听。视图发生变化。但我似乎无法点击它。我在很多地方和链接中寻找解决方案,但仍然找不到解决方案。
这些是我做的代码。
@override
Widget build(BuildContext context)
return new ListWheelScrollView(
physics:FixedExtentScrollPhysics(),
children: getPostList(),
itemExtent: 100.0,
);
List<PostListItem> getPostList()
return _postModal
.map((contact) => new PostListItem(contact))
.toList();
这就是我构建 ListTile 的地方
@override
Widget build(BuildContext context)
return new ListTile(
onTap: ()
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new OnTapPost(value: _postModal.fullName),
);
Navigator.of(context).push(route);
,
leading: new Image.asset('assets/images/logo.png'),
title: new Text(_postModal.fullName),
subtitle: new Text(_postModal.email)
);
在上面的代码中,列表项没有被点击。但是,如果我将 ListWheelScrollView 替换为 ListView ,如下所示,它可以完美运行。
@override
Widget build(BuildContext context)
return new ListView(
children: getPostList(),
);
List<PostListItem> getPostList()
return _postModal
.map((contact) => new PostListItem(contact))
.toList();
【问题讨论】:
这可能是个问题,您现在只需要使用不同类型的列表。见github.com/flutter/flutter/issues/38803 我猜终于发布了解决方案。它在链接pub.dev/packages/clickable_list_wheel_view 【参考方案1】:更新:Flutter 团队的另一个外观尚未更新,但另一个 hack 解决方案。通过用 Gesturedetector 包装整个 listscrollwheel 小部件。每个滚动都使用列表滚动视图的“onSelectedItemChanged”设置状态。但是手势检测器小部件只有在点击时才会使用它。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ServicesList extends StatefulWidget
final type;
ServicesList(this.type);
@override
_ServicesListState createState() => _ServicesListState();
class _ServicesListState extends State<ServicesList>
double _height ,_width;
int serviceIndex;
final FixedExtentScrollController _controller = FixedExtentScrollController();
List<Service> serviceList = [
Service(name: 'service 1'),
Service(name: 'service 4'),
Service(name: 'service 3'),
];
@override
void initState()
serviceIndex = 0;
// TODO: implement initState
super.initState();
detectService(index)
print('clicked container : $index'); //do whatever you want with the clicked index
@override
Widget build(BuildContext context)
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
return scrollWheel();
Widget scrollWheel()
return GestureDetector(
onTap: ()
detectService(serviceIndex);
,
child: ListWheelScrollView(
controller: _controller,
diameterRatio: 1.5,
itemExtent: 80,
onSelectedItemChanged: (e)=>
setState(()
serviceIndex = e;
)
,
magnification: 0.2,
physics: FixedExtentScrollPhysics(),
children: serviceList.map((e)
return Container(
padding: const EdgeInsets.all(6.0),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.blue,
),
child:Text('item $e.name');
);
).toList(), //List of widgets
),
);
class Service
String name;
Service( this.name );
【讨论】:
【参考方案2】:两到三年后,@TWL (https://github.com/flutter/flutter/issues/38803) 提供的链接中也进行了一次大讨论,该问题似乎已通过 ListWheelScrollView 的包装器解决,该包装器允许儿童响应 onTap 事件。 https://pub.dev/packages/clickable_list_wheel_view
虽然这些年来我现在不需要这个解决方案,但我希望它可以帮助其他想要解决这个问题的人。
干杯!
【讨论】:
【参考方案3】:我有同样的问题 如果您仍想在您的情况下使用 ListWheelScrollView 而不是 ListView,
您可以将 ListWheelScrollView 包装在 GestureDetector 中,并制作一个您的 _postModals 列表。 使用 onSelectedItemChanged 确定当前选择的列表项索引,然后创建全局索引变量。这是我的意思的一个例子:
import 'package:flutter/material.dart';
class ListScrollWheelExample extends StatelessWidget
@override
Widget build(BuildContext context)
List<PostModal> _postModals = [
//Add your postModals here
];
int Index;
return GestureDetector(
onTap: ()
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new OnTapPost(value: _postModals[Index].fullName),
);
Navigator.of(context).push(route);
,
child: ListWheelScrollView(
onSelectedItemChanged: (int index)
Index = index;
,
offAxisFraction: -0.85,
diameterRatio: 0.75,
physics: FixedExtentScrollPhysics(),
itemExtent: 100,
children: <Widget>[
getPostList(),
],
),
);
在你的 ListTile 中:
leading: new Image.asset('assets/images/logo.png'),
title: new Text(_postModals[Index].fullName),
subtitle: new Text(_postModals[Index].email)
我使用这种方式是因为我仍然喜欢滚轮的外观,并且我不想转换为 ListView,但尽量不要使 ListWheelScrollView 的直径过大以保持点击功能按预期工作。
编辑: 如果您希望多个项目可点击(3 或 4 个可见项目),您可以将 ListWheelScrollView 包装在具有 3 或 4 个手势检测器的堆栈中。然后使用 Index-1 和 Index+1 ,...等
【讨论】:
这不能解决问题。问题是关于点击列表中的任何项目,而不仅仅是在 ListWheelScrollView 中心选择的项目, @BrysonThill 我的回答解决了这个问题,因为在我们的例子中,我们使用 FixedExtentScrollPhysics() ,它的用法主要用于单击 ScrollWheel 中的当前项目,而且它再次不是 ListView,不是所有项目都出现在前面。以上是关于当我使用 ListView 时,ListTile OnTap 正在工作。但是当我使用 ListWheelScrollView 它不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何将特定的 ListTile 变量传递给新的页面路由 onTap?