可以检测到父容器的区域大小,并根据父容器的尺寸信息可以完成自定义布局。是一个非常实用的布局组件。

LayoutBuilder基本认识

  1. <br />【builder】 : 布局构造器 【LayoutWidgetBuilder】<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/326147/1589506707793-bb1759aa-9164-4031-96b2-8b7d8bc081f8.png#align=left&display=inline&height=126&margin=%5Bobject%20Object%5D&name=image.png&originHeight=126&originWidth=361&size=5902&status=done&style=none&width=361)
import 'package:flutter/material.dart';
class CustomLayoutBuilder extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('CustomLayoutBuild');
    return Container(
      alignment: Alignment.center,
      height: 80,
      width: 150,
      color: Colors.green,
      child: LayoutBuilder(
        builder: (_, zone) {
          return Text(
            '父容器宽:${zone.maxWidth}\n'
            '父容器高:${zone.maxHeight}',
            style: TextStyle(color: Colors.white, fontSize: 16),
          );
        },
      ),
    );
  }
}

LayoutBuilder的适应布局

   <br />可以根据区域的大小进行组件展示设计。"<br />比如在不同的宽度区域显示不同的布局结构。"<br />毕竟很多地方不容易获取父组件区域,使用LayoutBuilder就会非常爽口。<br />![182.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589506796133-add64b0c-db36-4668-99fb-cb930370c68d.gif#align=left&display=inline&height=241&margin=%5Bobject%20Object%5D&name=182.gif&originHeight=241&originWidth=381&size=310416&status=done&style=none&width=381)
import 'package:flutter/material.dart';
class FitByLayoutBuilder extends StatefulWidget {
  @override
  _FitByLayoutBuilderState createState() => _FitByLayoutBuilderState();
}

class _FitByLayoutBuilderState extends State<FitByLayoutBuilder> {
  double _width = 100;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          width: _width,
          child: LayoutBuilder(
            builder: (_, zone) {
              if (zone.maxWidth <= 150) {
                return _buildType1();
              } else {
                return _buildType2(zone);
              }
            },
          ),
        ),
        _buildSlider(),
      ],
    );
  }

  Widget _buildSlider() {
    return Slider(
          min: 50,
          max: 300,
          label: "父宽:${_width.toStringAsFixed(1)}",
          value: _width,
          onChanged: (v) => setState(() {
              _width = v;
            }));
  }

  Widget _buildType1() => Container(
        color: Colors.blue,
        child: Column(
          children: <Widget>[
            _buildTitle(),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: _buildContent(),
            ),
          ],
        ),
      );

  Widget _buildType2(BoxConstraints zone) => Container(
        height: 100,
        width: zone.maxWidth,
        color: Colors.orange,
        child: Row(
          children: <Widget>[
            Container(
              margin: EdgeInsets.all(10),
              height: 80,
              width: 30,
              color: Colors.grey,
            ),
            Expanded(child: _buildContent())
          ],
        ),
      );

  Widget _buildTitle() => Container(
        margin: EdgeInsets.only(left: 10, right: 10, top: 10),
        color: Colors.grey,
        height: 30,
      );

  Widget _buildContent() => Wrap(
        runSpacing: 3,
        children: <Widget>[
          Container(
            color: Colors.red,
            height: 30,
          ),
          Container(
            color: Colors.yellow,
            height: 30,
          ),
          Container(
            color: Colors.green,
            height: 30,
          ),
        ],
      );
}

LayoutBuilder的展开使用

   <br />使用TextPainter来检测文字的行数,实现展开或收起功能。<br />![183.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589506873023-53c3748d-10d0-4714-b93a-94d6927e1bc0.gif#align=left&display=inline&height=241&margin=%5Bobject%20Object%5D&name=183.gif&originHeight=241&originWidth=381&size=340967&status=done&style=none&width=381)
import 'package:flutter/material.dart';
class SimpleExpandableText extends StatefulWidget {

  @override
  createState() => _SimpleExpandableTextState();
}

class _SimpleExpandableTextState extends State<SimpleExpandableText> {

  final text = '桃树、杏树、梨树,你不让我,我不让你,都开满了花赶趟儿。'
      '红的像火,粉的像霞,白的像雪。'
      '花里带着甜味儿;闭了眼,树上仿佛已经满是桃儿、杏儿、梨儿。'
      '花下成千成百的蜜蜂嗡嗡地闹着,大小的蝴蝶飞来飞去。'
      '野花遍地是:杂样儿,有名字的,没名字的,散在草丛里,像眼睛,像星星,还眨呀眨的。';

  bool expand = false;
  int maxLines =3;


  final style = TextStyle(fontSize: 15, color: Colors.grey, shadows: [
    Shadow(
        color: Colors.white, offset: Offset(1,1)
    )
  ]);

  @override
  build(context) => Container(
    decoration: BoxDecoration(
        color: Colors.cyanAccent.withAlpha(8),
        borderRadius: BorderRadiusDirectional.all(Radius.circular(20))),
    padding: EdgeInsets.all(15),
    child: LayoutBuilder(builder: (context, size) {

      final painter = TextPainter(
        text: TextSpan(text: text, style: style),
        maxLines: maxLines,
        textDirection: TextDirection.ltr,
      );
      painter.layout(maxWidth: size.maxWidth);
      if (!painter.didExceedMaxLines)
        return Text(text, style: style);

      return Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(text, maxLines: expand ? null : 3, style: style),
          GestureDetector(
            onTap: () => setState(() {
                expand = !expand;
              }),
            child: Text(
              expand ? '<< 收起' : '展开 >>',
              style: TextStyle(color: Colors.blue),
            ),
          ),
        ],
      );
    }),
  );
}