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

Flutter构建ListView时ExpansionTile添加onTap方法报错求解

问题描述

通过读取本地JSON文件数据构建ListView时,基础功能运行正常,但在_buildList组件内给ExpansionTile添加onTap: (){}形式的点击回调,触发如下编译报错:

Error: No named parameter with the name 'onTap'. onTap: (){}, ^^^^^ /C:/src/flutter/packages/flutter/lib/src/material/expansion_tile.dart:51:9: Context: Found this candidate, but the arguments don't match. const ExpansionTile({ ^^^^^^^^^^^^^

对应出错的main.dart代码如下:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'datamodel.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}


class _MyAppState extends State<MyApp> {

    Future<List<Menu>> ReadJsonData() async {
    //read json file
    final jsondata = await rootBundle.loadString('assets/data0.json');
    //decode json data as list
    final list = json.decode(jsondata) as List<dynamic>;
    //map json and initialize using Model
    return list.map((e) => Menu.fromJson(e)).toList();
  }
  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home:Scaffold(
            appBar: AppBar(
              title: const Text('My Title'),
            ),
        body: FutureBuilder(
          future: ReadJsonData(),
          builder: (context,data){
            if(data.hasError){
              return Center(child: Text("${data.error}"));
            }else if(data.hasData){
              var items =data.data as List<Menu>;
              return ListView.builder(
                itemCount: items.length,
                itemBuilder: (BuildContext context, int index) =>
                    _buildList(items[index]),
              );
            }else{
              return Center(child: CircularProgressIndicator(),);
            }
          },
        )
    )
    );
  }

    Widget _buildList(Menu list) {
    return ExpansionTile(
      leading: Icon(list.icon),
      // 报错行
      onTap: (){},
      title: Text(
        list.name!,
        style: TextStyle(fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
      ),
      children: list.subMenu!.map(_buildList).toList(),
    );
  }
}
报错原因

Flutter 内置的ExpansionTile组件没有定义onTap这个命名参数,直接传入该参数就会触发找不到匹配参数的编译错误。

实现方案

要给每个ExpansionTile绑定点击触发逻辑,选下面任意一种方式即可:

  • 方式一:使用组件自带的onExpansionChanged回调
    这个是ExpansionTile原生提供的回调,用户点击标题触发展开/收起时就会触发,回调参数是布尔值,代表点击后组件的展开状态,直接替换原来写的onTap即可:
    Widget _buildList(Menu list) {
      return ExpansionTile(
        leading: Icon(list.icon),
        // 替换原onTap参数
        onExpansionChanged: (bool isExpanded) {
          // 写自己的点击逻辑即可,isExpanded为true表示点击后展开,false表示点击后收起
          debugPrint("点击菜单:${list.name},当前展开状态:$isExpanded");
        },
        title: Text(
          list.name!,
          style: TextStyle(fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
        ),
        children: list.subMenu!.map(_buildList).toList(),
      );
    }
    
  • 方式二:用GestureDetector包裹ExpansionTile
    如果不需要获取展开状态,只需要捕获点击动作,直接给组件套一层手势识别容器即可,点击事件不会和组件自带的展开收起逻辑冲突:
    Widget _buildList(Menu list) {
      return GestureDetector(
        onTap: () {
          // 写自己的点击逻辑
          debugPrint("点击菜单:${list.name}");
        },
        child: ExpansionTile(
          leading: Icon(list.icon),
          title: Text(
            list.name!,
            style: TextStyle(fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
          ),
          children: list.subMenu!.map(_buildList).toList(),
        ),
      );
    }
    

内容的提问来源于stack exchange,提问作者safaa al-wajidi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:19:19