Flexible是flutter的一个内置小部件,它控制基本 flex 小部件(即 Row、Column 和 Flex)的子级如何填充可用空间。 flutter的Expanded小部件是Flexible 的简写,默认配合FlexFit.tight 。灵活的小部件在制作响应式应用程序中起着非常重要的作用,该应用程序在多种设备尺寸上的外观和感觉都相同。但是,如果您只想通过小部件对空间进行基本填充,那么Expanded也是一个不错的选择。
灵活类的构造函数:
const Flexible(
{Key key,
int flex: 1,
FlexFit fit: FlexFit.loose,
@required Widget child}
)
灵活控件的属性:
- debugTypicalAncestorWidgetClass:此属性以 Type 作为参数来设置错误消息的ParentData 。
- fit:此属性以FlexFit值作为参数。它决定了一个灵活的子小部件将如何填充它可用的空间。子小部件可以选择使用FlexFit占据最大区域。紧值或它可以选择最小面积与FlexFit 。松价值。或者可以为其分配 FlexFit.vlaues。
- flex:这个属性接受一个整数作为参数。它决定沿主轴的子小部件的大小(对于Row ,它是水平的和垂直的Column )相对于其他子小部件。
示例 1:无响应 应用程序
Dart
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GeeksforGeeks'),
backgroundColor: Colors.greenAccent[400],
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
tooltip: 'Menu',
) //IconButton
), //AppBar
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
children: [
Row(
children: [
Container(
width: 175,
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
), //BoxDecoration
), //Container
SizedBox(
width: 20,
), //SizedBox
Container(
width: 175,
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
) //BoxDecoration
) //Container
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
Container(
width: 380,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue), //BoxDecoration
), //Container
Row(
children: [
Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
), //BoxDecoration
), //Container
SizedBox(
width: 20,
), //SizedBox
Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
) //BoxedDecoration
) //Container
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
], //[]
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
), //Column
) //Padding
), //Container
) //Center
), //Scaffold
debugShowCheckedModeBanner: false,
)); //MaterialApp
}
Dart
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GeeksforGeeks'),
backgroundColor: Colors.greenAccent[400],
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
tooltip: 'Menu',
) //IconButton
), //AppBar
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
children: [
Row(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 1,
fit: FlexFit.loose,
child: Container(
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
Flexible(
flex: 1,
fit: FlexFit.loose,
child: Container(
width: 380,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue), //BoxDecoration
), //Container
), //Flexible
Row(
children: [
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SixedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
) //BoxDecoration
) //Container,
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
], //[]
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
), //Column
) //Padding
), //Container
) //Center
), //Scaffold
debugShowCheckedModeBanner: false,
)); //MaterialApp
}
Dart
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GeeksforGeeks'),
backgroundColor: Colors.greenAccent[400],
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
tooltip: 'Menu',
) //IconButton
), //AppBar
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Row(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
), //Flexible
SizedBox(
height: 20,
), //SixedBox
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
width: 380,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue), //BoxDecoration
), //Container
), //Flexible
SizedBox(
height: 20,
), //SixedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Row(
children: [
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
), //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
), //Column
) //Padding
), //Container
) //Container
), //Scaffold
debugShowCheckedModeBanner: false,
)); //MaterialApp
}
输出:
说明:查看代码,我们可以看到在屏幕顶部,我们有一个基本的应用栏构建,其中 AppBar 小部件包含一个前导菜单IconButton 。应用栏的背景颜色是greenAccent[400] ,并且图标有一个工具提示,上面写着“菜单”。在应用程序的主体中,父小部件是Center,然后是Container和Padding。之后,我们有一个Column小部件,它将小部件列表作为子部件。在该列表中,第一个小部件是一个Row ,其中包含两个 Container 和一个 SizedBox。 Containers 的高度和宽度分别为 175,在装饰属性的帮助下,颜色设置为红色,border-radius 设置为 10。接下来是Row外的一个Container ,宽度为 380,高度为 200。颜色设置为蓝色,边框半径设置为 10。接下来是另一行,其中包含两个容器,每个容器都具有青色,高度为 300,宽度为 180。在容器之间,有一个 SizedBox 小部件宽度为 20。在两行中,主轴对齐设置为居中,在列中,主轴对齐设置为spaceBetween交叉轴对齐设置为居中。
我们可以在这个应用程序中看到有五个容器不会根据屏幕大小改变它们的大小,这意味着小部件没有响应。
示例 2:水平响应式应用程序。
Dart
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GeeksforGeeks'),
backgroundColor: Colors.greenAccent[400],
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
tooltip: 'Menu',
) //IconButton
), //AppBar
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
children: [
Row(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 1,
fit: FlexFit.loose,
child: Container(
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
Flexible(
flex: 1,
fit: FlexFit.loose,
child: Container(
width: 380,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue), //BoxDecoration
), //Container
), //Flexible
Row(
children: [
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SixedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
) //BoxDecoration
) //Container,
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
], //[]
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
), //Column
) //Padding
), //Container
) //Center
), //Scaffold
debugShowCheckedModeBanner: false,
)); //MaterialApp
}
输出:
说明:再次通过查看应用程序的代码,我们可以看到这次每个Container小部件都与Flexible小部件重合。在顶部Row的Container小部件内, 两个Container的 flex 属性都设置为 1,用于控制区域在它们之间的分布方式,并且 fit 属性设置为 FlexFlit.loose 以确保这两个容器小部件都可以选择占用最小面积。再次对于蓝色Container ,flex 属性设置为 1,fit 属性设置为 FlexFlit.loose。在底部Row的 Container 小部件中,flex 属性设置为 2,它们也将占用相等的一半空间,我们通过在 Top Row中将 flex 设置为 1 来实现相同的结果。在这种情况下,两个Container 的fit 都设置为 FlexFit.tight,这将迫使它们占用最大的可用空间。
可以看到,当屏幕尺寸在水平方向上增加时,行中容器的宽度会根据屏幕尺寸变化进行调整,但蓝色容器不会改变其宽度,因为它是Column和Flexible的直接子项小部件仅允许沿父小部件的主轴更改子部件的大小,在Column 的情况下是垂直的。当屏幕尺寸在垂直方向上改变时,我们可以看到蓝色容器的高度发生了变化,但其他容器在这个方向上没有响应,因为它们是Row小部件的子级。
示例 3:使用Flexible小部件包装顶部和底部Row小部件
Dart
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GeeksforGeeks'),
backgroundColor: Colors.greenAccent[400],
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
tooltip: 'Menu',
) //IconButton
), //AppBar
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Row(
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
), //Flexible
SizedBox(
height: 20,
), //SixedBox
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
width: 380,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue), //BoxDecoration
), //Container
), //Flexible
SizedBox(
height: 20,
), //SixedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Row(
children: [
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
), //BoxDecoration
), //Container
), //Flexible
SizedBox(
width: 20,
), //SizedBox
Flexible(
flex: 2,
fit: FlexFit.tight,
child: Container(
width: 180,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.cyan,
) //BoxDecoration
), //Container
) //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.center,
), //Row
), //Flexible
], //[]
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
), //Column
) //Padding
), //Container
) //Container
), //Scaffold
debugShowCheckedModeBanner: false,
)); //MaterialApp
}
输出:
说明:现在,在这个应用程序中,我们用灵活的小部件包装了顶部和底部的Row小部件,每个小部件的 flex 值为 1。这个应用程序中的所有适合属性都是对 FlexFit.tight 的更改,以强制子小部件采用所有他们可用的空间。还增加了两个SizeBox小部件,一个在蓝色Container的顶部,一个在其下方。
再看一下app我们可以看到,当屏幕尺寸在垂直方向发生变化时,所有容器的高度也随之变化,但是当屏幕尺寸在水平方向发生变化时,除了所有容器的蓝色容器宽度变化也。这是因为蓝色Container只是 Column 小部件的直接子级,它允许它在唯一的垂直方向上改变方向。虽然我们也可以通过用Row小部件敲击蓝色Container来使其具有响应性,这将使其能够在使用Flexible包裹时在水平方向上调整其大小,
因此,这就是我们如何通过使用Flexible小部件使整个应用程序的小部件在flutter中具有响应性。