flutter text内容高度不定问题解决

遇到一个listview嵌套listview 里面的item的Text内容高度不确定,

英文,数字普遍比汉字低4.0  所以最后有三种解决办法,一种是给listview加key 一种是强制输入汉字,第三种是加上缺失高度从而固定高度。

 

又遇到了获取widget的高度的问题,这里有三种方法,都很准确。

https://www.jianshu.com/p/a3834fe82847  转载的

 

想要获取widget的尺寸,必须要等widget的layout结束之后才能取到,目前有三种方式

  • 通过BuildContext获取
  • 通过GlobalKey获取
  • 通过SizeChangedLayoutNotifier获取

通过BuildContext获取

widget的尺寸存在于context?.findRenderObject()?.paintBounds?.size中,过早获取可能为空,需要延时获取.在flutter1.7之前duration=Duration()就能获取到,但是1.7之后必须要设置一百毫秒以上才行.

 

class FindSizeWidget extends StatefulWidget {
  @override
  _FindSizeWidgetState createState() => _FindSizeWidgetState();
}

class _FindSizeWidgetState extends State<FindSizeWidget> {

  @override
  Widget build(BuildContext context) {
    /// 延时一下,需要等state layout结束之后才能获取size
    Future.delayed(Duration(milliseconds: 100), () {
      _printSize();
    });
    return _buildContentWidget();
  }
  Widget _buildContentWidget(){
    return Container(
      color: Colors.red,
      child: Text(
        '''
        1 ...            1    
        2 ...            2    
        3 ...            3    
        4 ...            4    
        ''',
        style: TextStyle(fontSize: 30),
        maxLines: null,
        softWrap: true,
      ),
    );
  }
  _printSize(){
    if (!mounted) return;
    var size = context?.findRenderObject()?.paintBounds?.size;
    print(size.toString());
  }
}

打印结果:
flutter: Size(277.0, 180.0)

通过GlobalKey获取

FindSizeWidget增加构造方法,通过外部传入GlobalKey,方便以后寻找到FindSizeWidget.context对象.

 

class FindSizeWidget extends StatefulWidget {
  const FindSizeWidget({Key key}) : super(key:key);
}

注意一个GlobalKey只能对应一个widget对象,当心复用问题.

增加一个获取尺寸的按钮.点击之后获取尺寸.

 

  class _MyApp extends State<MyApp> {
  GlobalKey _globalKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        FlatButton(
            onPressed: () {
              var size = _globalKey.currentContext
                  ?.findRenderObject()
                  ?.paintBounds
                  ?.size;
              print(size.toString());
            },
            child: Text("获取尺寸")),
        FindSizeWidget(
          key: _globalKey,
        )
      ],
    );
  }
}

打印结果:
flutter: Size(277.0, 180.0)

通过SizeChangedLayoutNotifier获取

使用SizeChangedLayoutNotifier方式,Widget会在layout结束之后会发出一个LayoutChangedNotification通知,我们只需要接收这个通知,即可获取尺寸信息,但是SizeChangedLayoutNotifierRenderObject_RenderSizeChangedWithCallback类,它在第一次布局完成之后并不会发出通知,所以我们要自定义SizeChangedLayoutNotifier_RenderSizeChangedWithCallback两个类.
_RenderSizeChangedWithCallback源码部分:

 

@override
  void performLayout() {
    super.performLayout();
    // Don't send the initial notification, or this will be SizeObserver all
    // over again!
    if (_oldSize != null && size != _oldSize)
      onLayoutChangedCallback();
    _oldSize = size;
  }

修改_RenderSizeChangedWithCallback,只需要去掉_oldSize != null的判断即可.

 

@override
  void performLayout() {
    super.performLayout();
    // Don't send the initial notification, or this will be SizeObserver all
    // over again!
    if (size != _oldSize)
      onLayoutChangedCallback();
    _oldSize = size;
  }

再修改_FindSizeWidgetStatebuild方法:

 

  @override
  Widget build(BuildContext context) {
    return NotificationListener<LayoutChangedNotification>(
      onNotification: (notification) {
        /// 收到布局结束通知,打印尺寸
        _printSize();
        /// flutter1.7之后需要返回值,之前是不需要的.
        return null;
      },
      child: CustomSizeChangedLayoutNotifier(
        child: _buildContentWidget(),
      ),
    );
  }

打印结果:
flutter: Size(277.0, 180.0)

要判断一个`Text`组件的高度是否溢出,可以使用`LayoutBuilder`和`RenderObject`来获取`Text`组件的实际高度和最大高度进行比较。以下是基本步骤: 1. 导入需要的库 ```dart import 'package:flutter/rendering.dart'; ``` 2. 在`Text`组件外层包裹`LayoutBuilder`组件 ```dart LayoutBuilder( builder: (context, constraints) { return Text( '需要检测的文本', maxLines: 1, // 设置最大行数为1 overflow: TextOverflow.ellipsis, // 设置文本溢出时的省略符号 ); }, ); ``` 3. 在`Text`组件渲染完成后,获取`RenderObject`对象 ```dart RenderObject renderObject = context.findRenderObject(); ``` 4. 使用`RenderObject`对象获取`Text`组件的实际高度和最大高度,并进行比较 ```dart if (renderObject.paintBounds.height > constraints.maxHeight) { // 文本高度溢出 } else { // 文本高度未溢出 } ``` 完整代码示例如下: ```dart LayoutBuilder( builder: (context, constraints) { return Text( '需要检测的文本', maxLines: 1, // 设置最大行数为1 overflow: TextOverflow.ellipsis, // 设置文本溢出时的省略符号 style: TextStyle(fontSize: 16), // 设置文本字体大小 textAlign: TextAlign.center, // 设置文本对齐方式 strutStyle: StrutStyle.disabled, // 禁用strut softWrap: true, // 允许文本自动换行 textScaleFactor: 1.0, // 文本缩放因子 textDirection: TextDirection.ltr, // 文本方向 locale: Locale('zh'), // 本地化语言 overflowReplacement: Text('文本溢出'), // 整个文本溢出时的替换组件 textWidthBasis: TextWidthBasis.longestLine, // 文本宽度基准 textHeightBehavior: TextHeightBehavior( // 文本高度行为 applyHeightToFirstAscent: false, applyHeightToLastDescent: false, ), onTextLayout: (textLayout) { // 文本布局回调 RenderObject renderObject = context.findRenderObject(); if (renderObject.paintBounds.height > constraints.maxHeight) { // 文本高度溢出 } else { // 文本高度未溢出 } }, ); }, ); ``` 需要注意的是,在进行高度比较时,需要等到`Text`组件完成渲染后才能获取到实际高度。因此,需要使用`onTextLayout`回调来获取`Text`组件渲染完成的信息。同时,还需要设置`maxLines`和`overflow`属性,以确保`Text`组件的高度是固定的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值