flutter 2
flutter layout
抽取Widget
- 创建一个dart文件,命名为 listview_test_demo
class ListviewDemo extends StatelessWidget {
const ListviewDemo({Key? key}) : super(key: key);
Widget _itemBuilder(BuildContext context, int index) => customContainer(index);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.amberAccent,
appBar: AppBar(
title: const Text('hello flutter'),
),
body: ListView.builder(itemBuilder: _itemBuilder,itemCount: datas.length)
);
}
}
Container customContainer(a){
return Container(
color: Colors.white,
margin: const EdgeInsets.all(5),
child: Column(
children: <Widget>[
Image.network(datas[a].imageUrl!),
const SizedBox(height: 10,),
Text(datas[a].name!,style:
const TextStyle(fontWeight: FontWeight.w800,fontSize: 18,fontStyle: FontStyle.italic))
],
)
);
}
使用
void main() => runApp(const RocApplication4());
class RocApplication4 extends StatelessWidget {
const RocApplication4({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return const MaterialApp(
debugShowMaterialGrid: false,
debugShowCheckedModeBanner: false, // 清除斜杠
home: ListviewDemo()
);
}
}
常用 Widget
-
创建一个dart文件 命名 base_widget_demo
-
Container 不能够被const修饰
- padding 内
- margin 外
- flutter 是弹性盒子布局
案例1:代码 这里的代码可以理解一下封装思路(优秀的女孩子总是适时暴露内心的渴望,只为我能理解
)
// Container
class KWidgetContainer extends StatelessWidget {
KWidgetContainer({Key? key}) : super(key: key);
final Container _container = _kContainer()!;
@override
Widget build(BuildContext context) {
return _container;
}
}
Container? _kContainer(){
Container container = Container(color: Colors.tealAccent,
child: Row(
children: <Widget>[
Container(color: Colors.red,height: 100,width: 100,
padding: const EdgeInsets.all(30), // 内
margin: const EdgeInsets.all(20), // 外
child: const Icon(Icons.add),
),
],
)
);
return container;
}
使用
class SharedCenter extends StatelessWidget{
const SharedCenter({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
//drawerScrimColor: Colors.deepOrange,
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('hello flutter'),
),
body: const MyBody(),
);
}
}
class MyBody extends StatelessWidget{
const MyBody({Key? key}) : super(key: key);
@override
// Widget build(BuildContext context) => const WidgetListview();
// Widget build(BuildContext context) => KWidgetTextRich();
Widget build(BuildContext context) => KWidgetContainer();
}
-------------------------------------------------------------
// mian.dart 中
void main() => runApp(const RocApplication4());
class RocApplication4 extends StatelessWidget {
const RocApplication4({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return const MaterialApp(
debugShowMaterialGrid: false,
debugShowCheckedModeBanner: false, // 清除斜杠
home: SharedCenter()
);
}
}
案例2: RichText
// // RichText
class KWidgetTextRich extends StatelessWidget {
KWidgetTextRich({Key? key}) : super(key: key);
final RichText _richText = _richTextOne()!;
@override
Widget build(BuildContext context) {
return _richText;
}
}
// RichText
RichText? _richTextOne(){
RichText richText = RichText(
text: const TextSpan(text: '重磅消息',style: TextStyle(fontSize: 30,color: Colors.blue),
children:<TextSpan>[
TextSpan(text: '--'),
TextSpan(text: 'roc')
]),
);
return richText;
}
布局 Row Column Stack
-
x -1 ~ 1
-
y -1 ~ 1
-
布局部件 横向Row 纵向Column
横向布局
布局1
// Container 对应 MyBody 布局
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
//alignment: const Alignment(0,0),
child: const Text('hello flutter'),
);
return container;
}

布局2
// Container 对应 body 布局
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
// 位于中心点布局,即整个body的中心点
alignment: const Alignment(0,0),
child: const Text('hello flutter'),
);
return container;
}

布局3 不加 Alignment
- Row 中的布局需要通过children
- Row会显示一整行,没有Row则根据实际内容大小 如:布局一和布局2 所示
// Container 对应 body 布局
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
//alignment: const Alignment(0,0),
child: Row(
children: <Widget>[
Container(color: Colors.red,child: Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局4 添加 Alignment(0,0) Row(仅 y 可改变布局)
- 此时修改x毫无意义因为Row已经霸占一整行,可以调整y看看各种效果(x,y 都是:-1~1)
// Container 对应 body 布局 Row
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
children: <Widget>[
Container(color: Colors.red,child: Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

- 到这里如果你的理解能力还ok,知道某个女孩子想和你做什么,那么基本上可以遵循 行列行列 实现布局
常规的布局方式 都是先列在行(先竖抱再横推😂)一列一个Container,一个Container一行(墨守陈规
)
布局5 改变y 之后
// Container 对应 body 布局 Row
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,-1),
child: Row(
children: <Widget>[
Container(color: Colors.red,child: Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;

布局6 Column(仅 x 可改变布局)
// Container 对应 body 布局 Column
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Column(
children: <Widget>[
Container(color: Colors.red,child: Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局7 Stack 叠加 (z轴)
- 最后一个叠加在做上面,如果大小相同底下将完全被覆盖
// Container 对应 body 布局 Stack
Container? _kLayoutContainer(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Stack(
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 90,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 60,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 40,))
],
),
);
return container;
}

主轴 mainAxisAlignment
居中 | 开始 | 结束 |
---|---|---|
Column | 上 | 下 |
Row | 左 | 右 |
Stack | 底部 | 顶部 |
- 主轴属性
start 解释 停靠 左或上
end 解释 停靠 右或下
center
spaceBetween 解释 Place the free space evenly between the children.
spaceAround 解释 Place the free space evenly between the children as well as half of that space before and after the first and last child.
spaceEvenly 解释 Place the free space evenly between the children as well as before and after the first and last child.
设置主轴之前
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Row(
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

设置主轴之后
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局10
- spaceBetween
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局11
- spaceAround
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局12
- spaceEvenly
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

交叉轴 crossAxisAlignment
- 垂直于主轴方向的轴位
start
end
center
stretch
baseline
布局13
- start
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

布局14
- baseline 需要结合 textBaseline 使用
- 主要用于文字基线对齐
- 图片可底部对齐
// Container 对应 body 布局 Row
Container? _kLayoutContainer1(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,)),
Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,)),
Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,))
],
),
);
return container;
}

- stretch 填充满交叉轴方向(类似于竖向拉伸)
// Container 对应 body 布局 Row
Container? _kLayoutContainer3(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
textDirection: TextDirection.rtl,
crossAxisAlignment: CrossAxisAlignment.stretch,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
Expanded(child: Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,))),
Expanded(child: Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,))),
Expanded(child: Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,)))
],
),
);
return container;
}

Expanded
- 1.会填充满主轴方向,不会留下间隙,所以主轴方向设置大小没有意义
- 2.放不下内容时会自动换行
- 3.横屏竖屏中的使用
布局15
// Container 对应 body 布局 Row
Container? _kLayoutContainer3(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
Expanded(child: Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,))),
Expanded(child: Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,))),
Expanded(child: Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,)))
],
),
);
return container;
}

- textDirection 在Row 作用强大
textDirection设置之前

textDirection设置之后
// Container 对应 body 布局 Row
Container? _kLayoutContainer3(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(0,0),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
textDirection: TextDirection.rtl,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
Expanded(child: Container(color: Colors.red,child: const Icon(Icons.access_alarm,size: 60,))),
Expanded(child: Container(color: Colors.blue,child: const Icon(Icons.ac_unit_outlined,size: 70,))),
Expanded(child: Container(color: Colors.white,child: const Icon(Icons.access_time_filled,size: 80,)))
],
),
);
return container;
}

Stack
- stack 结合 Positioned 使用
- 如果是挪动位置用Positioned
- 如果时保持边距用margin:EdgeInsets.only
- margin 和子部件产生关系
- padding 和父部件产生关系
Container? _kLayoutContainer4(){
Container container = Container(
color: Colors.yellow,
alignment: const Alignment(1,-1),
child: Stack(
children: <Widget>[
Positioned(child: Container(color: Colors.red,width: 200,height: 200,child: const Icon(Icons.access_alarm,size: 90,))),
Positioned(left: -1,child: Container(color: Colors.blue,width: 100,height: 100,child: const Icon(Icons.ac_unit_outlined,size: 60,)),),
Positioned(right: 1,child: Container(color: Colors.white,width: 50,height: 50,margin: const EdgeInsets.only(right: 20),child: const Icon(Icons.access_time_filled,size: 40,)))
],
),
);
return container;
}

AspectRatio
-
AspectRatio 是根据父部件来调整宽高比的
-
如果子视图只设置高度没有设置宽度,宽度会根据父视图的宽度填充满
-
使用AspectRatio时,宽度 或 高度
仅
需要设置一个
,然后根据宽高比做调整 如:aspectRatio:1/1(宽高相等) -
不要配置AspectRatio的child没有意义
-
Stack Positioned margin padding AspectRatio 结合使用却有很大的作用
Container? _kLayoutContainer5(){
Container container = Container(
color: Colors.yellow,
//width: 300,
//height: 300,
alignment: const Alignment(0,0),
child: Container(
color: Colors.blue,
//width: 300,
//height: 300,
height: 300,
child: const AspectRatio(aspectRatio: 1/2,
// 不要配置AspectRatio的child没有意义
// child: Container(
// color: Colors.red,
// width: 100,
// height: 100,
// child: const AspectRatio(aspectRatio: 1/3),
// ),
),
),
);
return container;
}

总结 :
- 1.flutter 的布局方案就是 Row Column Stact
- 2.flutter 的布局调整则是 Positioned margin padding AspectRatio mainAxisAlignment(主轴) crossAxisAlignment(交叉轴)
- 3.flutter 的布局常用控件 Container Listview Text。。。
网友评论