skip to Main Content

How can I make the text widget’s height increase base on its content?

enter image description here

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

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,
        prototypeItem: MaterialPriceListItem(
          label: a.first.label,
          price: a.first.price,
          priceDiff: a.first.priceDiff,
        ),
        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(
        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,
                ),
              ),
            ),
          ),
          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,
                ),
              ),
            ),
          ),
          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,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  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);
    }
  }
}

3

Answers


  1. Chosen as BEST ANSWER

    Removing protoTypeItem solved the issue. even this is more efficient for ListView but it's not suitable for the list item that has vary height.

    @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,
              );
            },
          ),
        );
      }
    

  2. Wrap your text widgets to Expanded and then add maxlines properties of Text widget to 2 or 3. For example,

    Expanded(
    child: Text("your largeeeeeeee text", maxlines: 3),
    )
    
    
    Login or Signup to reply.
  3. Wrap your text widgets to "Wrap" for example:

    Wrap(
      direction: Axis.vertical,
      children: [
        Text("the very very large text"),
      ],
    ),
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search