赞
踩
这个组件最能体现Flutter与其他UI框架的一个不同点,那就是在其他UI框架中padding
基本都是作为组件的一个属性,例如在html中常见的布局标签都有padding
属性,Android中也是如此,但是在Flutter中组件并没有一个叫padding
的属性,相反,提供了一个叫作 Padding
的 Widget
组件。(体现了Flutter中万物皆Widget的理念)
Padding
可以给其子节点添加填充(留白),和边距效果类似。
下面是Padding
的定义:
Padding({
...
EdgeInsetsGeometry padding,
Widget child,
})
可以看到它的padding
参数需要传递一个EdgeInsetsGeometry
类型,这是一个抽象类,开发中,我们一般都使用EdgeInsets
类,它是EdgeInsetsGeometry
的一个子类,定义了一些设置填充的便捷方法。
下面是EdgeInsets
提供的便捷方法:
fromLTRB(left, top, right, bottom)
:分别指定四个方向的填充。all(value)
: 所有方向均使用相同数值的填充。only({left, top, right ,bottom })
:可以设置具体某个方向的填充(可以同时指定多个方向)。symmetric({ vertical, horizontal })
:用于设置对称方向的填充,vertical
指top
和bottom
,horizontal
指left
和right
。下面的示例展示了EdgeInsets
的不同用法:
class PaddingTestRoute extends StatelessWidget { const PaddingTestRoute({ Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Padding( //上下左右各添加16像素补白 padding: const EdgeInsets.all(16), child: Column( //显式指定对齐方式为左对齐,排除对齐干扰 crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: const <Widget>[ Padding( //左边添加8像素补白 padding: EdgeInsets.only(left: 8), child: Text("Hello world"), ), Padding( //上下各添加8像素补白 padding: EdgeInsets.symmetric(vertical: 8), child: Text("I am Jack"), ), Padding( // 分别指定四个方向的补白 padding: EdgeInsets.fromLTRB(20, 0, 20, 20), child: Text("Your friend"), ) ], ), ); } }
运行效果:
Container
是一个组合类容器,它本身不对应具体的RenderObject
,它是DecoratedBox
、ConstrainedBox
、Transform
、Padding
、Align
等组件组合的一个多功能容器,所以我们只需通过一个Container
组件可以实现同时需要装饰、变换、限制的场景。下面是Container
的定义:
Container({
this.alignment,
this.padding, //容器内补白,属于decoration的装饰范围
Color color, // 背景色
Decoration decoration, // 背景装饰
Decoration foregroundDecoration, //前景装饰
double width,//容器的宽度
double height, //容器的高度
BoxConstraints constraints, //容器大小的限制条件
this.margin,//容器外补白,不属于decoration的装饰范围
this.transform, //变换
this.child,
...
})
属性 | 说明 |
---|---|
alignment |
topCenter :顶部居中对齐topLeft :顶部左对齐topRight :顶部右对齐center :水平垂直居中对齐centerLeft :垂直居中水平居左对齐centerRight :垂直居中水平居右对齐bottomCenter :底部居中对齐bottomLeft :底部居左对齐bottomRight :底部居右对齐 |
decoration |
BoxDecoration 背景装饰 |
foregroundDecoration |
BoxDecoration 前景装饰 |
margin |
表示Container与外部其他组件的距离。 如margin:EdgeInsets.all(20.0) , |
padding |
Container的内边距,指Container边缘与Child之间的距离,如padding:EdgeInsets.all(10.0) |
transform |
让Container容易进行一些旋转之类的,如transform: Matrix4.rotationZ(0.2) |
height |
容器高度 |
width |
容器宽度 |
child |
容器子元素 |
color |
背景色 |
constraints |
容器大小的限制条件 |
有两点需要特别注意:
width
、height
属性来指定,也可以通过constraints
来指定;如果它们同时存在时,width
、height
优先。实际上Container
内部会根据width
、height
来生成一个constraints
。color
和decoration
是互斥的,如果同时设置它们则会报错!实际上,当指定color
时,Container
内会自动创建一个decoration
。示例代码1:
class MyCard extends StatelessWidget { const MyCard({ Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Container( width: 200, height: 200, color: Colors.blue, alignment: Alignment.center, child: const Text("你好Flutter", style: TextStyle(fontSize: 20)), ), ); } }
效果:
示例代码2:
Container( margin: const EdgeInsets.only(top: 50.0, left: 120.0), constraints: const BoxConstraints.tightFor(width: 200.0, height: 150.0), // 卡片大小 decoration: BoxDecoration( // 背景装饰 gradient: const RadialGradient( // 背景径向渐变 colors: [Colors.red, Colors.orange], center: Alignment.topLeft, radius: .98, ), // LinearGradient 是背景线性渐变 // gradient: LinearGradient( colors: [Colors.red, Colors.orange]), boxShadow: const [ //卡片阴影 BoxShadow( color: Colors.black54, offset: Offset(2.0, 2.0), blurRadius: 4.0, ) ], border: Border.all(color: Colors.red, width: 2.0), borderRadius: BorderRadius.circular(8.0), // 圆角 , color: Colors.blue, ), transform: Matrix4.rotationZ(.2),//卡片倾斜变换 alignment: Alignment.center, //卡片内文字居中 child: const Text("5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),), //卡片文字 ),
效果:
通过Container
创建一个按钮:
class MyButton extends StatelessWidget { const MyButton({ Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( alignment: Alignment.center, width: 200, height: 40, // margin: const EdgeInsets.all(10), //四周margin margin: const EdgeInsets.fromLTRB(0, 40, 0, 0), // padding: const EdgeInsets.fromLTRB(40, 0, 0, 0), decoration: BoxDecoration( color: Colors.blue, borderRadius:BorderRadius.circular(20) ), child: const Text("按钮",style: TextStyle( color: Colors.white, fontSize: 20 )), ); } }
效果:
可以看到Container
具备多种组件的功能,通过查看Container
源码,我们会很容易发现它是多种组件组合而成的。在Flutter中,Container
组件也正是组合优先于继承的实例。
接下来我们来看一下Container
组件margin
和padding
属性的区别:
...
Container(
margin: EdgeInsets.all(20.0), //容器外补白
color: Colors.orange,
child: Text("Hello world!"),
),
Container(
padding: EdgeInsets.all(20.0), //容器内补白
color: Colors.orange,
child: Text("Hello world!"),
),
...
效果:
可以发现,直观的感觉就是margin
的留白是在容器外部,而padding
的留白是在容器内部,需要记住这个差异。事实上,Container
内margin
和padding
都是通过Padding
组件来实现的,上面的示例代码实际上等价于:
... Padding( padding: EdgeInsets.all(20.0), child: DecoratedBox( decoration: BoxDecoration(color: Colors.orange), child: Text("Hello world!"), ), ), DecoratedBox( decoration: BoxDecoration(color: Colors.orange), child: Padding( padding: const EdgeInsets.all(20.0), child: Text("Hello world!"), ), ), ...
double.infinity
和double.maxFinite
可以让当前元素的width
或者height
达到父元素的尺寸。
static const double nan = 0.0 / 0.0;
static const double infinity = 1.0 / 0.0;
static const double negativeInfinity = -infinity;
static const double minPositive = 5e-324;
static const double maxFinite = 1.7976931348623157e+308;
如下代码可以让Container
铺满整个屏幕:
Widget build(BuildContext context) { return Container( height: double.infinity, width: double.infinity, color: Colors.black26, child: const Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Icon(Icons.home, color: Colors.red), Icon(Icons.search, color: Colors.blue), Icon(Icons.send, color: Colors.orange), ], ), ); }
如下代码可以让Container
的宽度和高度等于父元素的宽度高度:
class HomePage extends StatelessWidget { const HomePage({ Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( height: 400, width: 600, color: Colors.red, child: Container( height: double.maxFinite, width: double.infinity, color: Colors.black26, child: const Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Icon(Icons.home, color: Colors.red), Icon(Icons.search, color: Colors.blue), Icon(Icons.send, color: Colors.orange), ], ), ), ); } }
DecoratedBox
可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等。DecoratedBox
定义如下:
const DecoratedBox({
Decoration decoration,
DecorationPosition position = DecorationPosition.background,
Widget? child
})
decoration
:代表将要绘制的装饰,它的类型为Decoration
。Decoration
是一个抽象类,它定义了一个接口 createBoxPainter()
,子类的主要职责是需要通过实现它来创建一个画笔,该画笔用于绘制装饰。position
:此属性决定在哪里绘制Decoration
,它接收DecorationPosition
的枚举类型,该枚举类有两个值:
background
:在子组件之下绘制,即背景装饰。foreground
:在子组件之上绘制,即前景。我们通常会直接使用BoxDecoration
类,它是一个Decoration
的子类,实现了常用的装饰元素的绘制。
BoxDecoration({
Color color, //颜色
DecorationImage image,//图片
BoxBorder border, //边框
BorderRadiusGeometry borderRadius, //圆角
List<BoxShadow> boxShadow, //阴影,可以指定多个
Gradient gradient, //渐变
BlendMode backgroundBlendMode, //背景混合模式
BoxShape shape = BoxShape.rectangle, //形状
})
示例:下面代码实现一个带阴影的背景色渐变的按钮
DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors:[Colors.red,Colors.orange.shade700]), //背景渐变 borderRadius: BorderRadius.circular(3.0), //3像素圆角 boxShadow: [ //阴影 BoxShadow( color:Colors.black54, offset: Offset(2.0,2.0), blurRadius: 4.0 ) ] ), child: Padding( padding: EdgeInsets.symmetric(horizontal: 80.0, vertical: 18.0), child: Text("Login", style: TextStyle(color: Colors.white),), ) )
效果:
上面的例子中使用了LinearGradient
类,它用于定义线性渐变的类,Flutter中还提供了其他渐变配置类,如RadialGradient
、SweepGradient
,若有需要可以自行查看API文档。
Transform
可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效。Matrix4
是一个4D矩阵,通过它我们可以实现各种矩阵操作,下面是一个例子:
Container(
color: Colors.black,
child: Transform(
alignment: Alignment.topRight, //相对于坐标系原点的对齐方式
transform: Matrix4.skewY(0.3), //沿Y轴倾斜0.3弧度
child: Container(
padding: const EdgeInsets.all(8.0),
color: Colors.deepOrange,
child: const Text('Apartment for rent!'),
),
),
)
效果:
由于矩阵变化时发生在绘制时,而无需重新布局和构建等过程,所以性能很好。
Transform.translate
接收一个offset
参数,可以在绘制时沿x、y
轴对子组件平移指定的距离。
DecoratedBox(
decoration:BoxDecoration(color: Colors.red),
child: Transform.translate(
offset: Offset(-20.0, -5.0), // 默认原点为左上角,左移20像素,向上平移5像素
child: Text("Hello world"),
),
)
效果:
Transform.rotate
可以对子组件进行旋转变换,如:
import 'dart:math' as math; // 要使用math.pi需先进行导包
DecoratedBox(
decoration:BoxDecoration(color: Colors.red),
child: Transform.rotate(
angle:math.pi / 2 , // 旋转90度
child: Text("Hello world"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。