一、Padding
Padding通常用于设置子Widget到父Widget的边距(你可以称之为是父组件的内边距或子Widget的外边距)
Padding({
...
EdgeInsetsGeometry padding,
Widget child,
})
EdgeInsetsGeometry是一个抽象类,开发中,我们一般都使用EdgeInsets类,它是EdgeInsetsGeometry的一个子类,定义了一些设置填充的便捷方法。
二、EdgeInsets
EdgeInsets提供的便捷方法:
fromLTRB(double left, double top, double right, double bottom):分别指定四个方向的填充。all(double value): 所有方向均使用相同数值的填充。only({left, top, right ,bottom }):可以设置具体某个方向的填充(可以同时指定多个方向)。symmetric({ vertical, horizontal }):用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right。
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("容器组件"),
backgroundColor: Colors.red,
),
body:Column(
children: [
Padding(
// 左边添加8像素
padding: EdgeInsets.only(left: 8),
child: Text('Hello world'),
),
Padding(
// 上下添加8像素
padding: EdgeInsets.symmetric(vertical: 8),
child: Text('Hello world'),
),
Padding(
// 四个方向添加
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Text('Hello world'),
)
],
),
),
);
}
}
三、BoxDecoration(装饰器)
BoxDecoration类,它是一个Decoration的子类(Decoration类型是一个抽象类),实现了常用的装饰元素的绘制。
BoxDecoration常见属性:
const BoxDecoration({
this.color, // 颜色,会和Container中的color属性冲突
this.image, // 背景图片
this.border, // 边框,对应类型是Border类型,里面每一个边框使用BorderSide
this.borderRadius, // 圆角效果
this.boxShadow, // 阴影效果
this.gradient, // 渐变效果
this.backgroundBlendMode, // 背景混合
this.shape = BoxShape.rectangle, // 形变
})
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("容器组件"),
backgroundColor: Colors.red,
),
body:Center(
child: Container(
width: 150,
height: 150,
child: Icon(Icons.pets,size: 32,color: Colors.white,),
decoration: BoxDecoration(
color: Colors.red,
//边框
border: Border.all(
color: Colors.orange,
width: 10,
style: BorderStyle.solid,
),
// 圆角,
borderRadius: BorderRadius.circular(20), // 这里也可以使用.only分别设置
),
),
),
),
);
}
}
四、 DecoratedBox(装饰容器)
DecoratedBox可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等。DecoratedBox定义如下:
const DecoratedBox({
Decoration decoration,
DecorationPosition position = DecorationPosition.background,
Widget? child
})
-
decoration:代表将要绘制的装饰,它的类型为Decoration。Decoration是一个抽象类,它定义了一个接口createBoxPainter(),子类的主要职责是需要通过实现它来创建一个画笔,该画笔用于绘制装饰。 -
position:此属性决定在哪里绘制Decoration,它接收DecorationPosition的枚举类型,该枚举类有两个值:-
background:在子组件之后绘制,即背景装饰。 -
foreground:在子组件之上绘制,即前景。
-
例: 实现一个带阴影的背景色渐变的按钮:
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("容器组件"),
backgroundColor: Colors.red,
),
body:Center(
child: DecoratedBox(
decoration: BoxDecoration(
// 背景渐变
gradient: LinearGradient(colors: [Colors.red,Colors.orange.shade700]),
// 圆角
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black54,
offset: Offset(2.0, 2.0),
blurRadius: 4.0
),
],
),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 80,vertical: 20),
child: Text("Login",style: TextStyle(color: Colors.white,fontSize: 20),),
),
)
),
),
);
}
}
五、 Container(容器组件)
Container组件类似于Android中的View,iOS中的UIView。
如果你需要一个视图,有一个背景颜色、图像、有固定的尺寸、需要一个边框、圆角等效果,那么就可以使用Container组件。
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,
...
})
Container的大多数属性在介绍其他容器时都已经介绍过了,不再赘述,但有两点需要说明:
- 容器的大小可以通过
width、height属性来指定,也可以通过constraints来指定;如果它们同时存在时,width、height优先。实际上Container内部会根据width、height来生成一个constraints。 color和decoration是互斥的,如果同时设置它们则会报错!实际上,当指定color时,Container内会自动创建一个decoration。
例
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("容器组件"),
backgroundColor: Colors.red,
),
body:Center(
child:Container(
color: Colors.red,
width: 100,
height: 100,
child: Icon(Icons.pets,size: 32,color: Colors.white,),
),
),
),
);
}
}
六、Container组件中的margin和padding
接下来我们来研究一下Container组件margin和padding属性的区别:
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("容器组件"),
backgroundColor: Colors.red,
),
body:Column(
children: [
Container(
margin: EdgeInsets.all(20),
color: Colors.orange,
child: Text("Hello word!"),
),
Container(
padding: EdgeInsets.all(20),
color: Colors.orange,
child: Text("Hello word!"),
)
],
),
),
);
}
}
可以发现,直观的感觉就是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!"),
),
),
...