【发布时间】:2022-01-05 11:56:52
【问题描述】:
我正在开始我的第一个真实世界的颤振应用程序,到目前为止,我无法解决如何解决我拥有的这个非常基本的用例。
我在网上找到了各种信息,但还没有真正解决它。这个用例对我来说似乎很常见,所以必须有一个很好的标准方法来做到这一点。
我有一个列布局。为了说明这一点,有一个徽标(蓝色)、一个表单(红色)、一个按钮(绿色)和底部的一些自定义导航(黑色)。
代码如下:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
children: [
const Placeholder(
color: Colors.blue,
fallbackHeight: 100.0,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 32.0),
child: Placeholder(
color: Colors.red,
fallbackHeight: 300.0,
),
),
const Spacer(),
Column(
children: [
const Placeholder(
color: Colors.green,
fallbackHeight: 40.0,
),
Container(
margin: const EdgeInsets.only(top: 40.0),
child: const Placeholder(
color: Colors.black,
fallbackHeight: 40.0,
),
),
],
)
],
),
),
),
);
}
}
我在 Pixel 5 模拟器上运行它。尺寸不是 100% 准确,但足以解释我认为的场景。
此屏幕是具有相似屏幕的流程的一部分,因此我想从底部向上布局自定义导航和按钮。 IE。当我导航到下一个屏幕时,我希望按钮和导航位于同一位置。
徽标和顶部的主要内容也是如此。因此我在中间放了一个垫片,它会占据中间的空间。
到问题。我在表格中有一些验证。当按下按钮并中断验证时,表单将在每个字段下方显示一堆消息。我通过将表单占位符的高度增加到 500 来模拟这一点。
所以现在所有组件都不再适合屏幕了,我在底部得到了一些溢出。没什么奇怪的。
在研究解决此问题的最惯用方法时,我发现添加 SingleChildScrollView 是有意义的。
但是添加一个SingleChildScrollView 会破坏代码,因为我有一个Spacer。我理解那部分。既然我们现在说“占用尽可能多的空间,我会让它可滚动”,我们有无限的空间可供使用。同时Spacer 基本上说,“我会尽可能地把所有东西往下推,直到没有空间为止”。所以这也是有道理的。让我们移除垫片。
代码如下:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
children: [
const Placeholder(
color: Colors.blue,
fallbackHeight: 100.0,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 32.0),
child: Placeholder(
color: Colors.red,
fallbackHeight: 500.0,
),
),
Column(
children: [
const Placeholder(
color: Colors.green,
fallbackHeight: 40.0,
),
Container(
margin: const EdgeInsets.only(top: 40.0),
child: const Placeholder(
color: Colors.black,
fallbackHeight: 40.0,
),
),
],
)
],
),
),
),
),
);
}
}
它按预期工作。我没有收到任何错误,我可以滚动查看按钮和导航。
现在总结一下。当我的表单恢复到原来的高度 300 像素时会发生什么?当然,由于删除了垫片,我不再需要按钮和导航从底部开始的那种行为。它们现在被拉到表格中。当然,这也是有道理的。
我明白为什么所有不同的场景都会如此行事。但是我怎样才能创建一个灵活的布局,其中一些东西从底部定位,一些从顶部定位,但仍能防止溢出?
我是否必须开始计算何时以及是否会发生任何溢出并动态添加滚动视图?我还没有走这条路,因为我希望有一种更具声明性、更标准的方式来处理这个问题。
【问题讨论】:
-
你到底想要什么
-
我希望我的解释足够好,但我知道这很难。我希望第一张图像始终为真,直到表单增加高度(由于新内容,错误消息)然后我不想要溢出错误,而是想要一个可滚动的视图。但是我愿意接受任何将布局保持在第一张图像中并且在表单高度增加时不会中断的解决方案。无论什么实现都可以解决这个问题,并且在内容不适合屏幕时仍然有效,这很有趣。
-
你想要第二个像输出一样滚动的图像,对吗?
-
仅当内容溢出时。否则我想要第一张图片中的布局。但同样,第一张图片是我想要的布局,这是第一要务。并且我希望防止表单高度增加时发生溢出。