flutter 中间组件自适应宽度

字体大小变化

1、使用ConstrainedBox+ auto_size_text 插件

ConstrainedBox(
     constraints: BoxConstraints(maxWidth: 375.w - 246),
        child: AutoSizeText(
          item.tagName,
          style: TextStyle(
            fontSize: TextSize.x14.fontSize,
            color: TextColor.black.color,
          ), // 初始字体大小
          minFontSize: TextSize.x8.fontSize, // 最小字体大小
          softWrap: false,

          maxLines: 1, // 最大行数
          overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
        ),
      )

字体大小不变化

1、使用Flexible + IntrinsicWidth

Row(
  children: [
    Text('第一个text'),
    IntrinsicWidth(
        child: ConstrainedBox(
          constraints: BoxConstraints(maxWidth: 200), // 最大宽度限制
          child: Text(
            '中间的text可能很长也可能很短',
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
          ),
        ),
    ),
    Text('第三个text'),
  ],
)

2、使用LayoutBuilder + 自定义计算

LayoutBuilder(
  builder: (context, constraints) {
    final firstText = '第一个text';
    final middleText = '中间的text可能很长也可能很短';
    final thirdText = '第三个text';
    
    // 计算文本宽度
    final textPainter = TextPainter(
      text: TextSpan(text: middleText),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    
    final middleTextWidth = textPainter.width;
    final maxWidth = 200.0;
    
    // 使用实际宽度或最大宽度中的较小值
    final actualWidth = middleTextWidth < maxWidth ? middleTextWidth : maxWidth;
    
    return Row(
      children: [
        Text(firstText),
        SizedBox(
          width: actualWidth,
          child: Text(
            middleText,
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
          ),
        ),
        Text(thirdText),
      ],
    );
  },
)

3、使用CustomMultiChildLayout

CustomMultiChildLayout(
  delegate: _ThreeTextLayoutDelegate(maxWidth: 200),
  children: [
    LayoutId(
      id: 'first',
      child: Text('第一个text'),
    ),
    LayoutId(
      id: 'middle',
      child: Text(
        '中间的text可能很长也可能很短',
        overflow: TextOverflow.ellipsis,
        maxLines: 1,
      ),
    ),
    LayoutId(
      id: 'third',
      child: Text('第三个text'),
    ),
  ],
)

class _ThreeTextLayoutDelegate extends MultiChildLayoutDelegate {
  final double maxWidth;
  
  _ThreeTextLayoutDelegate({required this.maxWidth});
  
  @override
  void performLayout(Size size) {
    // 获取第一个text的尺寸
    final firstSize = layoutChild('first', BoxConstraints.loose(size));
    
    // 获取第三个text的尺寸
    final thirdSize = layoutChild('third', BoxConstraints.loose(size));
    
    // 计算中间text可用的最大宽度
    final availableWidth = size.width - firstSize.width - thirdSize.width;
    
    // 计算中间text的实际宽度(不超过maxWidth)
    final middleConstraints = BoxConstraints(
      maxWidth: availableWidth.clamp(0, maxWidth),
      minWidth: 0,
    );
    final middleSize = layoutChild('middle', middleConstraints);
    
    // 布局
    positionChild('first', Offset.zero);
    positionChild('middle', Offset(firstSize.width, 0));
    positionChild('third', Offset(firstSize.width + middleSize.width, 0));
  }

  @override
  bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => false;
}

4、使用StatefulWidget + 动态计算

class AdaptiveTextRow extends StatefulWidget {
  final String firstText;
  final String middleText;
  final String thirdText;
  final double maxMiddleWidth;
  
  const AdaptiveTextRow({
    super.key,
    required this.firstText,
    required this.middleText,
    required this.thirdText,
    this.maxMiddleWidth = 200,
  });

  @override
  State<AdaptiveTextRow> createState() => _AdaptiveTextRowState();
}

class _AdaptiveTextRowState extends State<AdaptiveTextRow> {
  double? middleTextWidth;
  
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _calculateMiddleTextWidth();
    });
  }
  
  void _calculateMiddleTextWidth() {
    final textPainter = TextPainter(
      text: TextSpan(text: widget.middleText),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    
    setState(() {
      middleTextWidth = textPainter.width;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    if (middleTextWidth == null) {
      return Row(
        children: [
          Text(widget.firstText),
          Flexible(
            child: Text(
              widget.middleText,
              overflow: TextOverflow.ellipsis,
              maxLines: 1,
            ),
          ),
          Text(widget.thirdText),
        ],
      );
    }
    
    final actualWidth = middleTextWidth! < widget.maxMiddleWidth 
        ? middleTextWidth! 
        : widget.maxMiddleWidth;
    
    return Row(
      children: [
        Text(widget.firstText),
        SizedBox(
          width: actualWidth,
          child: Text(
            widget.middleText,
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
          ),
        ),
        Text(widget.thirdText),
      ],
    );
  }
}

// 使用方式
AdaptiveTextRow(
  firstText: '第一个text',
  middleText: '中间的text可能很长也可能很短',
  thirdText: '第三个text',
  maxMiddleWidth: 200,
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值