[英]Flutter How to use lifecycle events in stateless widget? App on close
[英]Flutter: Understanding how does a Stateless/Statefull widget layout its child?
如果没有关于小部件的文档,我如何知道小部件的布局规则(它会从其父级请求什么大小以及它将向其子级传递什么约束)?
我有这个非常基本的应用程序
void main() {
runApp(
Container(
color: Colors.red,
width: 20,
height: 20,
),
);
}
我期望Container
的宽度和高度为 20,但我得到了一个填满整个屏幕的Container
。
在flutter.dev上阅读这篇关于理解约束的文章,在其最后一部分“学习特定小部件的布局规则”中,他们提到如何通过找到createRenderObject
方法然后找到performLayout
方法来做到这一点。
但是,此createRenderObject
方法仅适用于RenderObjectWidget
的子类。 例如,浏览Transform
小部件的代码,我发现createRenderObject
返回一个RenderTransform
,它扩展了RenderProxyBox
,最终performLayout
实现为:
@override
void performLayout() {
if (child != null) {
child!.layout(constraints, parentUsesSize: true);
size = child!.size;
} else {
size = computeSizeForNoChild(constraints);
}
}
我可以得出结论,由于这条线size = child.;size;
, Transform
小部件最终将采用其子部件的大小。 .
但在上面的Container
的情况下,是直接扩展StatelessWidget
。 通过浏览它的代码,我找不到方法performLayout
和createRenderObject
,我只能找到createElement
,但我正在寻找渲染树中与 Container 而不是元素关联的RenderObject
。
所以问题是如何找到与无状态小部件/有状态小部件相关联的渲染 object,以便了解该小部件将为其子项提供的布局规则,并在这种情况下自行遵循这些规则?
你有一定道理。 我会说我的文章在这方面不够精确。
小部件不需要创建RenderObject
。 相反,它可以使用自己创建RenderObjects
的其他小部件的组合。
如果小部件是其他小部件的组合,则无需查看performLayout
您只需查看该小部件的build
方法即可了解它在做什么。 对于Container
,这是它的build
方法:
Widget build(BuildContext context) {
Widget? current = child;
if (child == null && (constraints == null || !constraints!.isTight)) {
current = LimitedBox(
maxWidth: 0.0,
maxHeight: 0.0,
child: ConstrainedBox(constraints: const BoxConstraints.expand()),
);
}
if (alignment != null)
current = Align(alignment: alignment!, child: current);
final EdgeInsetsGeometry? effectivePadding = _paddingIncludingDecoration;
if (effectivePadding != null)
current = Padding(padding: effectivePadding, child: current);
if (color != null)
current = ColoredBox(color: color!, child: current);
if (clipBehavior != Clip.none) {
assert(decoration != null);
current = ClipPath(
clipper: _DecorationClipper(
textDirection: Directionality.maybeOf(context),
decoration: decoration!,
),
clipBehavior: clipBehavior,
child: current,
);
}
if (decoration != null)
current = DecoratedBox(decoration: decoration!, child: current);
if (foregroundDecoration != null) {
current = DecoratedBox(
decoration: foregroundDecoration!,
position: DecorationPosition.foreground,
child: current,
);
}
if (constraints != null)
current = ConstrainedBox(constraints: constraints!, child: current);
if (margin != null)
current = Padding(padding: margin!, child: current);
if (transform != null)
current = Transform(transform: transform!, alignment: transformAlignment, child: current);
return current!;
}
如您所见,它是根据其他小部件定义的。 并且这些widget也可以根据其他widget等来定义。 但是在某些时候,您将到达创建RenderObject
的小部件。
关于Container
不是 20x20 的原因,这是因为,正如文章所解释的,尺寸是由父母设置的。 因此Container
的大小由Container
的父级设置,在这种情况下是screen 。 并且屏幕总是强制它的孩子占据所有可用空间,在这种情况下忽略了Container
想要成为 20x20 的愿望。 这里的修复是给Container
另一个父级。 一种允许Container
选择自己的大小。 例如, Center
和Align
都会让这种情况发生,这就是您可以通过执行以下操作来解决问题的原因:
void main() {
runApp(
Center(
child: Container(
color: Colors.red,
width: 20,
height: 20,
),),);
}
至于为什么屏幕会强迫它的孩子占据所有可用空间:这正是 Flutter 创作者决定的方式。 如果你深入研究 Flutter 的代码,你会在那里找到它。 但最好记住这个事实。
希望能帮助到你!
您在这里缺少架构,我们需要使用Scaffold 。 喜欢
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: Container(
color: Colors.red,
width: 20,
height: 20,
),
)),
);
}
嗯,不要太复杂了。 这是我可以向您解释的最简单的事情,让我们将应用程序分成 4 个不同的层。
MaterialApp
创建一个材质应用程序Stateless
或StatefulWidget
,这取决于您的需要。 如果你需要动态的,有很多变化的状态,你可以使用StatefulWidget
或者你可以使用StatelessWidget
创建一个静态页面。Scaffold
,可以添加 appBar、fab、body、bottomNavigationBar 等。所以你的代码必须是这样的
/// This block is the first point of your application, this will run your application
void main() {
runApp(myApp());
}
/// Then you need an material app, this part should return your app
class MyApp extends StatelessWidget{
/// This is very important, both StatelessWidget / StatefullWidget
/// always having a build method. It's should returning a Widget. But in this case we will return an material application
@override
Widget build(BuildContext context){
return MaterialApp(
home: MyHome(),
),
}
}
class MyHome extends StatelessWidget{
/// This is home page, it's have Scaffold so the page will using, material guidelines.
@override
Widget build(BuildContext context){
return Scaffold(
body:Container(
color: Colors.red,
width: 20,
height: 20,
),
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.