Flutter ListView中多行TextField高度变化后ListTile位置不更新问题求解
Flutter多行TextField后ListTile错位问题解决方案
问题根因
该错位问题是Flutter ListView的默认布局优化机制导致的:当TextField高度随输入换行变化时,ListView仅触发了子组件的内容更新,没有完整重新计算所有子组件的绘制位置,因此ListTile的背景色绘制区域仍停留在旧位置,而内部的文字、图标等子元素正常更新,就出现了视觉上的错位,滑动ListView时触发了完整重绘才会恢复正常。
可用解决方案
- 方案1:用
SingleChildScrollView嵌套Column替代ListView,适合子组件数量少的场景,完全规避ListView的子组件缓存优化,不会出现错位问题,代码示例如下:
@override Widget build(BuildContext context) { final scrollView = SingleChildScrollView( child: Column( children: [ TextField(maxLines: null), SizedBox(height: 50, child: ColoredBox(color: Colors.yellow,child: Text("Tile1"),) ), ListTile(tileColor: Colors.blueGrey,title: Text("Tile1"),), ListTile(tileColor: Colors.blueGrey,title: Icon(Icons.looks_two_rounded),) ], ), ); return Scaffold(backgroundColor: Color(0xdcdcffff), body: Center(child: scrollView)); }
- 方案2:保留ListView的使用,关闭其默认的子组件保活优化,构造ListView时添加
addAutomaticKeepAlives: false参数即可,代码示例如下:
@override Widget build(BuildContext context) { ListView l = new ListView( addAutomaticKeepAlives: false, children: [ TextField(maxLines: null), SizedBox(height: 50, child: ColoredBox(color: Colors.yellow,child: Text("Tile1"),) ), ListTile(tileColor: Colors.blueGrey,title: Text("Tile1"),), ListTile(tileColor: Colors.blueGrey,title: Icon(Icons.looks_two_rounded),) ]); return Scaffold(backgroundColor: Color(0xdcdcffff), body: Center(child: l)); }
- 方案3:如果需要保留ListView的懒加载能力,可给TextField添加onChanged回调,每次输入时触发页面重绘,强制ListView重新计算布局:
TextField( maxLines: null, onChanged: (_) => setState(() {}), )
内容的提问来源于stack exchange,提问作者OneUsernamePlease
相关产品推荐
相关产品推荐

