ListView中Text组件高度无法自适应内容,如何实现高度随内容调整?
Flutter ListView内Text组件高度无法自动包裹内容的解决方案
你的问题主要来自两个关键点:
Text组件默认不会自动换行,长文本会被截断,导致高度无法跟随内容扩展ListView.builder使用了prototypeItem参数,它会强制所有列表项使用原型项的固定高度,即使内容更多也无法撑开
解决步骤:
- 给所有需要自适应高度的
Text组件添加softWrap: true和maxLines: null,允许文本自动换行并占据足够高度 - 移除
ListView.builder的prototypeItem参数,让每个列表项根据自身内容计算高度(如果追求性能,也可以用itemExtent但不推荐,因为无法适配动态内容)
修改后的关键代码片段:
1. 调整MaterialPriceListItem中的Text组件:
// 标签文本部分 Text( label, style: const TextStyle(fontSize: 22), softWrap: true, maxLines: null, ) // 价格文本部分 Text( "${moneyFormat(price)} \$", style: TextStyle(color: getColor(priceDiff), fontSize: 18), softWrap: true, maxLines: null, ) // 价格变动文本部分 Text( getPriceChangeText(priceDiff), style: TextStyle(color: getColor(priceDiff), fontSize: 14), softWrap: true, maxLines: null, )
2. 修改ListView.builder移除prototypeItem:
ListView.builder( itemCount: a.length, // 移除prototypeItem参数 itemBuilder: (context, index) { return MaterialPriceListItem( label: a[index].label, price: a[index].price, priceDiff: a[index].priceDiff, ); }, )
完整修改后的代码:
import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; void main() { runApp(const MyApp()); } class MaterialData { final String label; final double price; final double priceDiff; MaterialData(this.label, this.price, this.priceDiff); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'ตลาดหลักทรัพย์', theme: ThemeData(primarySwatch: Colors.indigo), home: const MyHomePage(title: 'ตลาดหลักทรัพย์'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final List<MaterialData> data = [ MaterialData('ไม้กระดาน', 48, 0), MaterialData('วิญญาณร้าย', 39, 1), MaterialData('ตุ๊กตาหิมะ', 31, 0), MaterialData('ทองคำ', 609000000000, 1), MaterialData('ไข่เอเลียน', 31, 0), MaterialData('ทับทิม', 582, -18), MaterialData('ล็อบสเตอร์ทอง', 2500, 0), MaterialData('เหล็ก', 43000, 5000), MaterialData('น้ำมันกลั่น', 43, 0), MaterialData('ไก่ในถาด', 34, 1), ]; List<MaterialData> a = List<MaterialData>.empty(); @override void initState() { a = List<MaterialData>.generate(10000, (i) => data[i % 10]); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: ListView.builder( itemCount: a.length, itemBuilder: (context, index) { return MaterialPriceListItem( label: a[index].label, price: a[index].price, priceDiff: a[index].priceDiff, ); }, ), ); } } class MaterialPriceListItem extends StatelessWidget { final String label; final double price; final double priceDiff; const MaterialPriceListItem({ Key? key, required this.label, required this.price, required this.priceDiff, }) : super(key: key); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.fromLTRB(8, 13.0, 8, 13.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, // 确保行内元素垂直居中 children: [ getIcon(priceDiff), Expanded( flex: 7, child: Container( padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0), alignment: Alignment.centerLeft, child: Text( label, style: const TextStyle(fontSize: 22), softWrap: true, maxLines: null, ), ), ), Expanded( flex: 2, child: Container( padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0), alignment: Alignment.center, child: Text( "${moneyFormat(price)} \$", style: TextStyle(color: getColor(priceDiff), fontSize: 18), softWrap: true, maxLines: null, ), ), ), Expanded( flex: 1, child: Container( padding: const EdgeInsets.fromLTRB(8.0, 0, 0, 0), alignment: Alignment.center, child: Text( getPriceChangeText(priceDiff), style: TextStyle(color: getColor(priceDiff), fontSize: 14), softWrap: true, maxLines: null, ), ), ), ], ), ); } String moneyFormat(double value) { var nf = NumberFormat("##,###.##", "en_US"); return nf.format(value); } String getPriceChangeText(double priceChange) { if (priceChange.sign > 0) { return "+${moneyFormat(priceChange.abs())}"; } else if (priceChange.sign < 0) { return "-${moneyFormat(priceChange.abs())}"; } else { return moneyFormat(priceChange); } } Widget getIcon(double priceChange) { if (priceChange < 0) { return FaIcon( FontAwesomeIcons.arrowDown, color: getColor(priceChange), size: 18, ); } else if (priceChange > 0) { return FaIcon( FontAwesomeIcons.arrowUp, color: getColor(priceChange), size: 18, ); } else { return Center( child: FaIcon( FontAwesomeIcons.arrowRight, color: getColor(priceChange), size: 18, ), ); } } Color getColor(double priceChange) { if (priceChange < 0) { return const Color.fromARGB(255, 198, 40, 40); } else if (priceChange > 0) { return const Color.fromARGB(255, 46, 125, 50); } else { return const Color.fromARGB(255, 21, 101, 192); } } }
内容的提问来源于stack exchange,提问作者Jongz Puangput
相关产品推荐
相关产品推荐

