Flutter 如何检测小部件中的溢出
我想知道是否有方法检测小部件中发生的溢出,并返回一个布尔值,根据Flutter 如何检测小部件中的溢出,flutter,flutter-layout,flutter-widget,Flutter,Flutter Layout,Flutter Widget,我想知道是否有方法检测小部件中发生的溢出,并返回一个布尔值,根据true或false值进行一些更改 例如,我有一个里面有文本的容器。我想在文本溢出容器时检测,之后我会在某些条件下使容器变大。我知道有一些方法,比如自动调整大小\u文本,但这里的要点是检测溢出,我们可以测量文本的宽度,并使用它确定边界框: import 'package:flutter/material.dart'; class Demo extends StatefulWidget { @override _DemoSt
true
或false
值进行一些更改
例如,我有一个里面有文本的容器。我想在文本溢出容器时检测,之后我会在某些条件下使容器变大。我知道有一些方法,比如自动调整大小\u文本
,但这里的要点是检测溢出,我们可以测量文本的宽度,并使用它确定边界框:
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
String text = "text";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
text += " text";
});
},
),
body: Padding(
padding: const EdgeInsets.all(32.0),
child: LayoutBuilder(
builder: (ctx, constraints) {
final style = Theme.of(context).textTheme.headline1;
final span = TextSpan(
text: text,
style: style,
);
final painter = TextPainter(
text: span,
maxLines: 1,
textScaleFactor: MediaQuery.of(context).textScaleFactor,
textDirection: TextDirection.ltr,
);
painter.layout();
final overflow = painter.size.width > constraints.maxWidth;
return Container(
color: overflow ? Colors.red : Colors.green,
child: Text.rich(span, style: style),
);
},
),
),
);
}
}
导入“包装:颤振/材料.省道”;
类Demo扩展StatefulWidget{
@凌驾
_DemoState createState();
}
类_DemoState扩展了状态{
String text=“text”;
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(),
浮动操作按钮:浮动操作按钮(
子:图标(Icons.add),
已按下:(){
设置状态(){
文本+=“文本”;
});
},
),
主体:填充物(
填充:常数边集全部(32.0),
子:布局生成器(
生成器:(ctx,约束){
最终样式=Theme.of(context).textTheme.headline1;
最终跨度=文本跨度(
文本:文本,
风格:风格,
);
最终油漆工=文本油漆工(
文本:span,
maxLines:1,
textScaleFactor:MediaQuery.of(context).textScaleFactor,
textDirection:textDirection.ltr,
);
painter.layout();
最终溢出=painter.size.width>constraints.maxWidth;
返回容器(
颜色:溢出?颜色。红色:颜色。绿色,
child:Text.rich(span,style:style),
);
},
),
),
);
}
}
在CodePen上,我不认为改变容器的大小是个好主意,如果容器再次溢出,它的父容器会怎么样?正确的方法是使用以下命令调整容器内文本的大小:
在我看来,试图检测何时发生溢出似乎是一个错误 在Flutter中,子窗口小部件的大小受其父窗口小部件的限制,很少会发生溢出。例如,考虑下面的代码:
Container(
height: 100,
width: 100,
color: Colors.red,
child: Container(
width: 200,
height: 800,
color: Colors.green,
),
)
对于没有经验的颤振开发人员来说,看起来内部容器(200x800)将溢出其父容器(100x100),但事实上,内部容器的大小将自动调整以匹配其父容器,因此您不会看到黑色/黄色溢出条纹,您只会在屏幕上看到一个100x100的绿色容器
那么,我们什么时候能指望孩子们在颤栗中泛滥呢?通常有4种情况会导致溢出:
列
和行
小部件继承自Flex
小部件,您也可以直接使用它。在这些小部件中,当执行布局时,它们将在主轴中传递一个“无界”约束。例如,在列
的情况下,它的主轴是垂直轴,因此它将允许其子对象达到他们想要的高度(而不是宽度)。如果其子项的组合高度超过列本身的布局约束(由列的父项传递),则它将溢出。基本上,如果将一个列放在100x100容器中,则该列的高度不能超过100,如果其子列超过100,则会溢出
LayoutBuilder
获取列
本身的父约束,这样您就可以知道您可能拥有的最大大小(例如100x100,因为列放置在这样的容器中),然后您需要获得每个子项的大小,这对于列来说并不容易,因为在布局过程完成之前,您不知道它们的大小。(如果在布局完成之前必须知道它们的大小,可以考虑查看<代码> Cuto MultudieDays或编写自定义<代码> RealBox )。您可以使用GlobalKey
来获取任何小部件的大小,但这必须在下一帧中完成,一旦孩子们第一次被布置好
也许这里有一个更好的问题要问:为什么你想知道它是否会溢出?如果它溢出,你能做什么?如果可以为列分配更多空间,那么首先为什么不这样做呢?您可以在列上设置MainAxisSize.min
,告诉它收缩,并且除非确实需要,否则不要浪费所有额外的空间。或者,也许您想允许滚动?如果是这样,只需使用SingleChildScrollView
小部件包装整个列
,只要该列变得太高,它就会自动开始滚动。(顺便说一句,这与使用ListView
不同,如果要滚动的项目很多,则应使用ListView
。)
定位的
小部件,可能会溢出堆栈。例如,通过设置left:-10,top:-20
,您有意地在边界之外呈现一个小部件(略高于左上角)。但stack会自动为您剪辑,所以您甚至看不到那些溢出的内容。要查看它们,实际上需要手动更改堆栈的clipBehavior
。如果你正在做所有这些工作,我不认为“检测算法”是完全必要的
textpainer
帮助您完成所有计算,Container(
height: 100,
width: 100,
color: Colors.red,
child: Container(
width: 200,
height: 800,
color: Colors.green,
),
)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var dimension = 40.0;
increaseWidgetSize() {
setState(() {
dimension += 20;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(children: <Widget>[
Text('Dimension: $dimension'),
Container(
color: Colors.teal,
alignment: Alignment.center,
height: dimension,
width: dimension,
// LayoutBuilder inherits its parent widget's dimension. In this case, the Container in teal
child: LayoutBuilder(builder: (context, constraints) {
debugPrint('Max height: ${constraints.maxHeight}, max width: ${constraints.maxWidth}');
return Container(); // create function here to adapt to the parent widget's constraints
}),
),
]),
),
floatingActionButton: FloatingActionButton(
onPressed: increaseWidgetSize,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
height = MediaQuery.of(context).size.height;
weight = MediaQuery.of(context).size.width;