Android Flutter:那些不可忽视的基础布局!
2020-09-14 本文已影响0人
Carson带你学安卓
前言
- Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架,正在被越来越多的开发者和组织使用,包括阿里的咸鱼、腾讯的微信等。
示意图
今天,我主要讲解Flutter
中布局方面的基础布局组件,主要包括:
- Container
- Row
- Column
- Expanded
- Center
1. Container
1.1 定义
布局容器,属于组合widget,内部有绘制widget、定位widget、尺寸widget
1.2 布局原理
由于Container结合了许多其他Widget;而每个Widget都有自己的布局行为,因此Container的布局行为十分复杂,具体介绍如下:
1.3 属性说明
Container({
Key key, // 控制框架在widget重建时与哪些其他widget匹配
this.alignment, // 子Widget对齐,生效范围:父Widget尺寸 > child Widget尺寸
this.padding, // 内边距,即本Widget边框和内容区之间距离
this.margin, // 外边距:本Widget与父边框的距离。
Color color, // Container背景色
Decoration decoration, // 绘制背景图案,注:container背景色和decoration不能同时设置
this.foregroundDecoration, // 前景。设置了foregroundDecoration可能会遮盖child内容,一般半透明遮盖(蒙层)效果使用!
double width, // container的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局。
double height, // container的高度,设置为double.infinity可以强制在高度上撑满。
BoxConstraints constraints, // 添加到child上额外的约束条件,用于设置child的宽高范围值
this.child, // 控件内容widget。
})
关于Decoratiton的使用,具体请看文章:
1.4 具体使用
import 'package:flutter/material.dart';// Material UI组件库
void main() => runApp(MyApp());
// 无状态控件显示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //标题
theme: ThemeData(primarySwatch: Colors.blue), //主题色
home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
);
}
}
// 返回的Widget对象
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//设置appbar
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
//主体
body: new Container(
alignment: Alignment.center,// 对齐
padding: const EdgeInsets.all(5.0),// 内边距
margin: const EdgeInsets.all(10.0),// 外边距
color: Colors.grey,// 背景色
// 装饰(无法和color一起设置)
// decoration: new BoxDecoration(
// border: new Border.all(width: 2.0, color: Colors.red),
// borderRadius: new BorderRadius.all(new Radius.circular(20.0)),
// image: new DecorationImage(
// image: new AssetImage('assetImage/photo.jpg'),
// centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0),
// ),
// ),
// 添加到child上额外的约束条件,用于设置child的宽高范围值
constraints: new BoxConstraints.expand(
height: Theme
.of(context)
.textTheme
.display1
.fontSize * 1.1 + 200.0,
),
// 设置子空间
child: Text("carson ho Demo",),
)
);
}
}
1.5 测试效果
2. Row
2.1 作用
水平展示多个子控件的控件,即将一系列控件排成一行显示
注:该控件无法滚动。若超过一行则会报错,应考虑使用ListView类。
2.2 概念解析:主轴 & 纵轴
对于线性布局:
- 若布局沿水平方向(如Row),那么主轴 = 水平方向、纵轴 = 垂直方向
- 若布局沿垂直方向(如Colum),那么主轴 = 垂直方向、纵轴 = 水平方向
2.3 属性说明
// 属性说明
Row({
Key key, // 全局key来唯一标识子widget
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 子控件放置方式
MainAxisSize mainAxisSize = MainAxisSize.max, // 子控件应该如何沿着主轴放置
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 子控件对齐方式
TextDirection textDirection, // 排列方式:从左到右,还是从右到左排序
VerticalDirection verticalDirection = VerticalDirection.down, // 垂直排序
TextBaseline textBaseline, // 对齐文本的水平线
List<Widget> children = const <Widget>[], // 子控件
})
// 属性详解
// 1. mainAxisAlignment
// 说明:子控件根据主轴的对齐方式,枚举对象(默认值为start)
enum MainAxisAlignment {
start, // 内部的子组件将从主轴起始位置开始排列(正向排列)
end, // 内部的子组件将从主轴末尾位置开始排列(反向排列)
center, // 内部的子组件将从主轴中间位置开始排列(居中)
spaceBetween, // 内部的首尾子组件靠近首尾两端,其余子组件居中排列且组件间的间距一样
spaceAround, // 内部的子组件居中排列,且每个子组件的左右边距一样大
spaceEvenly, // 内部的子组件居中显示,每个空间的左边和右边都有相同的间距
}
// 2. mainAxisSize
// 说明:子控件如何放置,枚举对象(默认值为max)
enum MainAxisSize {
min, // 控件尽可能小,相当于wrap_content(取此值时,上面的MainAxisAlignment 无效),
max, // 控件尽可能大,相当于match_parent
}
// 3. crossAxisAlignment
// 说明:子控件对于纵轴的对齐方式,当子控件高度不一样时,如何被放置在主轴(中心轴),而MainAxisAlignment 决定了子控件间的间隔
enum CrossAxisAlignment {
start, // 内部的子组件将从非主轴起始位置开始排列(正向排列)
end, // 内部的子组件将从非主轴末尾位置开始排列(反向排列)
center, // 内部的子组件将从非主轴中间位置开始排列(居中)
stretch, // 内部的子组件将从非主轴中间位置开始排列,并且完全填充非主轴方向
baseline, // 内部的子组件将从baseline的方向对齐,这个需要设置textBaseline属性,不然的话会报错
}
// 4. textBaseline
// 说明:对齐文本的水平线
enum TextBaseline {
alphabetic, // 用于对齐字母字符的字形底部的水平线
ideographic, // 用于对齐表意文字的水平线
}
// 5. textDirection
// 说明:子控件排序方向 (一般不用设置,除非想反转子控件排序)
// Row 使用 TextDirection
// Column 使用 VerticalDirection
enum VerticalDirection {
up, // 子控件从下到上排序
down, // 子控件从上到下排序
}
enum TextDirection {
rtl, // 子控件从右到左排序
ltr, // 子控件从左到右排序
}
// 6. children
// 设置子控件
2.4 具体使用
import 'package:flutter/material.dart'; // Material UI组件库
void main() => runApp(MyApp());
// 无状态控件显示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //标题
theme: ThemeData(primarySwatch: Colors.blue), //主题色
home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
);
}
}
// 返回的Widget对象
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//设置appbar
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
//主体
body: new Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
children: <Widget>[
Text(" Carson Ho "),
Text(" Kobe Bryant "),
Text(" LeBorn James "),
Text(" Michael Jordan "),
],
),
);
}
}
2.5 效果图
3. Column
3.1 作用
垂直方向展示多个子控件的控件,即将一系列控件排成一列显示
3.2 属性说明
属性类似于Row的属性,主要包括:
// 属性说明
Column({
Key key, // 全局key来唯一标识子widget
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 子控件放置方式
MainAxisSize mainAxisSize = MainAxisSize.max, // 子控件应该如何沿着主轴放置
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 子控件对齐方式
TextDirection textDirection, // 排列方式:从左到右,还是从右到左排序
VerticalDirection verticalDirection = VerticalDirection.down, // 垂直排序
TextBaseline textBaseline, // 对齐文本的水平线
List<Widget> children = const <Widget>[], // 子控件
})
// 属性详解
// 1. mainAxisAlignment
// 说明:子控件根据主轴的对齐方式,枚举对象(默认值为start)
enum MainAxisAlignment {
start, // 内部的子组件将从主轴起始位置开始排列(正向排列)
end, // 内部的子组件将从主轴末尾位置开始排列(反向排列)
center, // 内部的子组件将从主轴中间位置开始排列(居中)
spaceBetween, // 内部的首尾子组件靠近首尾两端,其余子组件居中排列且组件间的间距一样
spaceAround, // 内部的子组件居中排列,且每个子组件的左右边距一样大
spaceEvenly, // 内部的子组件居中显示,每个空间的左边和右边都有相同的间距
}
// 2. mainAxisSize
// 说明:子控件如何放置,枚举对象(默认值为max)
enum MainAxisSize {
min, // 控件尽可能小,相当于wrap_content(取此值时,上面的MainAxisAlignment 无效),
max, // 控件尽可能大,相当于match_parent
}
// 3. crossAxisAlignment
// 说明:子控件对于纵轴的对齐方式,当子控件高度不一样时,如何被放置在主轴(中心轴),而MainAxisAlignment 决定了子控件间的间隔
enum CrossAxisAlignment {
start, // 内部的子组件将从非主轴起始位置开始排列(正向排列)
end, // 内部的子组件将从非主轴末尾位置开始排列(反向排列)
center, // 内部的子组件将从非主轴中间位置开始排列(居中)
stretch, // 内部的子组件将从非主轴中间位置开始排列,并且完全填充非主轴方向
baseline, // 内部的子组件将从baseline的方向对齐,这个需要设置textBaseline属性,不然的话会报错
}
// 4. textBaseline
// 说明:对齐文本的水平线
enum TextBaseline {
alphabetic, // 用于对齐字母字符的字形底部的水平线
ideographic, // 用于对齐表意文字的水平线
}
// 5. textDirection
// 说明:子控件排序方向 (一般不用设置,除非想反转子控件排序)
// Row 使用 TextDirection
// Column 使用 VerticalDirection
enum VerticalDirection {
up, // 子控件从下到上排序
down, // 子控件从上到下排序
}
enum TextDirection {
rtl, // 子控件从右到左排序
ltr, // 子控件从左到右排序
}
// 6. children
// 设置子控件
3.3 具体使用
import 'package:flutter/material.dart'; // Material UI组件库
void main() => runApp(MyApp());
// 无状态控件显示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //标题
theme: ThemeData(primarySwatch: Colors.blue), //主题色
home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
);
}
}
// 返回的Widget对象
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//设置appbar
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
//主体
body: new Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Text(" Carson Ho "),
Text(" Kobe Bryant "),
Text(" LeBorn James "),
Text(" Michael Jordan "),
],
),
);
}
}
3.4 具体效果
4. Expanded
4.1 作用
按比例伸缩 / 扩展 Row、Column和Flex子组件所占用的空间大小
4.2 属性说明
const Expanded({
Key key, // 唯一标识符
int flex = 1, // 弹性系数,默认值 = 1
// 若为 0 或 null,则 child 是没有弹性的,即不会被扩伸占用的空间。
// 若大于 0,所有的Expanded按照其flex的比例来分割主轴的全部空闲空间。
@required Widget child, // 子控件
})
4.3 具体使用
import 'package:flutter/material.dart'; // Material UI组件库
void main() => runApp(MyApp());
// 无状态控件显示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //标题
theme: ThemeData(primarySwatch: Colors.blue), //主题色
home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
);
}
}
// 返回的Widget对象
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//设置appbar
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
//主体:配合Row使用(采用两个容器Container来展示)
body: new Row(
children: <Widget>[
Expanded(
flex: 2, // 占2份空间
child: Container(
color: Colors.red,
)),
Expanded(
flex: 1, // 占1份空间
child: Container(
color: Colors.green,
)),
],
),
);
}
}
4.4 测试效果
5. Center
中心定位控件,能够将子控件放在其内部中心
class Page extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("正中央"), // 将text放到文本中央
);
}
}
总结
本文全面介绍了Flutter
常用的基础布局组件,总结如下:
接下来推出的文章,我将继续讲解Flutter的相关知识,包括使用语法、实战等,感兴趣的读者可以继续关注我的博客哦:Carson_Ho的Android博客
请点赞!因为你们的赞同/鼓励是我写作的最大动力!
相关文章阅读
Android开发:最全面、最易懂的Android屏幕适配解决方案
Android开发:史上最全的Android消息推送解决方案
Android开发:最全面、最易懂的Webview详解
Android开发:JSON简介及最全面解析方法!
Android四大组件:Service服务史上最全面解析
Android四大组件:BroadcastReceiver史上最全面解析
欢迎关注Carson_Ho的简书!
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。