当我使用 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?

我的 ListView 构建器的 ListTile 小部件不可滚动并且显示渲染问题

如何在颤动中将 ListTile 连接到音频小部件

在点击按钮之前执行的颤动代码

如何对齐 ListTile 中的文本?

如何缩小 ListTile 中的图像但不展开它?