You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让SingleChildScrollView内部的ListTile同时支持点击和滚动功能

问题根因

你遇到的滚动冲突本质不是ListTile拦截了事件,而是嵌套的两个滚动组件(外层SingleChildScrollView + 内层ListView.builder)默认的事件消费逻辑冲突:内层ListView默认开启滚动,会优先消费滑动事件,不会把事件向上传递给外层的SingleChildScrollView,同时你给内层ListView加了shrinkWrap: true只是让它自适应内容高度,没有关闭它自身的滚动能力。

解决方案

直接给内层的ListView.builder加属性禁用自身滚动,让滑动事件全部交给外层SingleChildScrollView处理即可,ListTile的点击事件不会受任何影响:

  • 添加physics: const NeverScrollableScrollPhysics(),关闭内层ListView的滚动响应
  • 保留shrinkWrap: true让内层ListView根据子项高度自适应,不会出现高度溢出

修改后的完整代码

return Scaffold(
  appBar: AppBar(title: const Text('Exersizes'),),
  body: Column(
    children: [
      Container(
        height: MediaQuery.of(context).size.height * 0.7,
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                'Exersizes',
                style: TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold
                ),  
              ),
              FutureBuilder(
                future: DBProvider.getData('exerscises'),
                builder: (ctx, AsyncSnapshot<List<Map<String, dynamic>>> snapshot) => snapshot.connectionState == ConnectionState.waiting
                  ? const CircularProgressIndicator()
                  : ListView.builder(
                      shrinkWrap: true,
                      // 新增这行,禁用内层ListView滚动
                      physics: const NeverScrollableScrollPhysics(),
                      itemCount: snapshot.data!.length,
                      itemBuilder: (ctx, i) => ListTile(
                        title: Text(snapshot.data![i]['exersizeName']),
                        subtitle: snapshot.data![i]['iscardio'] == 1 ? const Text('Type: cardio') : const Text('Type: weights'),
                        leading: CircleAvatar(
                          backgroundColor: Theme.of(context).primaryColor,
                          child: FittedBox(child: Text(_weekDays[snapshot.data![i]['weekday']]!)),
                        ),
                        onTap: () {print(snapshot.data![i]['exersizeName']);},
                      )
                    ),
              ),
            ],
          ),
        ),
      ),
      ElevatedButton(
        onPressed: () => Navigator.of(context).pushNamed(FormScreen.routeName), 
        child: const Text('Add Exersize')
      )
    ],
  ),
);

可选优化方案

如果你不需要外层SingleChildScrollView里的Exersizes标题跟着列表一起滚动,也可以直接移除外层的SingleChildScrollView,把标题放到ListView.builder的itemBuilder里作为第一个子项渲染,这样只有一个滚动组件,也不会出现冲突,性能更好。

内容的提问来源于stack exchange,提问作者OptimusPrime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:15:01