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
相关产品推荐
相关产品推荐

