配置插件依赖
设置组件大小
通过属性 childConstraints 实现
分别设置 约束布局一 和 约束布局二 大大小为:160 和 200
class SummaryPageState extends State<SummaryPage1> {
ConstraintId constraintId_1 = ConstraintId('ConstraintId_1');
ConstraintId constraintId_2 = ConstraintId('ConstraintId_2');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
childConstraints: [
// todo 约束布局一
Constraint(
id: constraintId_1,
size: 160,
bottomLeftTo: parent,
zIndex: 20,
),
// todo 约束布局二
Constraint(
id: constraintId_2,
size: 200,
topRightTo: parent,
zIndex: 20,
),
],
children: [
// todo 约束布局一
Container(
color: Colors.redAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_1'),
).applyConstraintId(id: constraintId_1),
// todo 约束布局二
Container(
color: Colors.blueAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_2'),
).applyConstraintId(id: constraintId_2),
],
),
);
}
}
位于某个视图底部
约束布局ID:ConstraintId_4 位于 ConstraintId_3 下面
import 'package:flutter/material.dart';
import 'package:flutter_constraintlayout/flutter_constraintlayout.dart';
class SummaryPage2 extends StatefulWidget {
const SummaryPage2({super.key});
@override
State<StatefulWidget> createState() {
return SummaryPageState();
}
}
class SummaryPageState extends State<SummaryPage2> {
ConstraintId constraintId_3 = ConstraintId('ConstraintId_3');
ConstraintId constraintId_4 = ConstraintId('ConstraintId_4');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 约束布局三
Container(
color: Colors.blue,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_3'),
).applyConstraint(
id: constraintId_3,
width: 200,
height: 150,
top: parent.top,
left: parent.left,
right: parent.right),
// todo 约束布局四
Container(
color: Colors.orange,
width: 200,
height: 150,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_4\n位于 ConstraintId_3 下面'),
).applyConstraint(
id: constraintId_4,
left: parent.left,
top: constraintId_3.bottom,
),
],
),
);
}
}
位于某个视图底部中间
约束布局ID:ConstraintId_6 位于 ConstraintId_5 底部 中间 位置
import 'package:flutter/material.dart';
import 'package:flutter_constraintlayout/flutter_constraintlayout.dart';
class SummaryPage3 extends StatefulWidget {
const SummaryPage3({super.key});
@override
State<StatefulWidget> createState() {
return SummaryPageState();
}
}
class SummaryPageState extends State<SummaryPage3> {
ConstraintId constraintId_5 = ConstraintId('ConstraintId_5');
ConstraintId constraintId_6 = ConstraintId('ConstraintId_6');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 约束布局三
Container(
color: Colors.blue,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_5'),
).applyConstraint(
id: constraintId_5,
width: 200,
height: 150,
top: parent.top,
left: parent.left,
right: parent.right),
// todo 约束布局四
Container(
color: Colors.orange,
width: 200,
height: 150,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_6 \n 位于 ConstraintId_5 底部 中间 位置'),
).applyConstraint(
id: constraintId_6,
left: constraintId_5.left,
top: constraintId_5.bottom,
right: constraintId_5.right,
),
],
),
);
}
}
位于父视图中间
约束布局ID:ConstraintId_7 位于 父视图 中间 位置
// todo © 国宝宝 2024年09月19日 周四 17:31
class SummaryPageState extends State<SummaryPage4> {
ConstraintId constraintId_7 = ConstraintId('ConstraintId_7');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 约束布局七
Container(
color: Colors.blue,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_7 位于 父视图中间位置'),
).applyConstraint(
id: constraintId_7,
width: 200,
height: 150,
centerTo: parent),
],
),
);
}
}
拖拽约束布局
约束布局ID:ConstraintId_8 进行拖拽 x:y
// todo © 国宝宝 2024年09月19日 周四 17:40
class SummaryPageState extends State<SummaryPage5> {
ConstraintId constraintId_8 = ConstraintId('ConstraintId_8');
double x = 0;
double y = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 约束布局七
GestureDetector(
child: Container(
color: Colors.orangeAccent,
alignment: Alignment.center,
child: Text('约束布局ID:ConstraintId_8 进行拖拽\n x:$x y:$y'),
),
onPanUpdate: (details) {
setState(() {
x += details.delta.dx;
y += details.delta.dy;
});
},
).applyConstraint(
id: constraintId_8,
width: 200,
height: 160,
centerTo: parent,
zIndex: 100,
translate: Offset(x, y),
translateConstraint: true,
),
],
),
);
}
}
约束布局 verticalBias 属性
中间垂直对齐 verticalBias 向上或者向下偏移的比例
// todo © 国宝宝 2024年09月19日 周四 17:53
class SummaryPageState extends State<SummaryPage6> {
ConstraintId constraintId_9 = ConstraintId('ConstraintId_9');
ConstraintId constraintId_10 = ConstraintId('ConstraintId_10');
ConstraintId constraintId_11 = ConstraintId('ConstraintId_11');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
childConstraints: [
// todo 约束布局九
Constraint(
id: constraintId_9,
width: 100,
height: 240,
centerLeftTo: parent,
zIndex: 20,
),
],
children: [
// todo 约束布局九
Container(
color: Colors.blueAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_9'),
).applyConstraintId(id: constraintId_9),
// todo 约束布局十
Container(
color: Colors.lightGreen,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_10 中间对齐'),
).applyConstraint(
id: constraintId_10,
size: 120,
margin: const EdgeInsets.only(right: 100),
centerVerticalTo: constraintId_9,
verticalBias: 0.5,// todo 偏移量0
right: parent.right,
),
// todo 约束布局十一
Container(
color: Colors.orangeAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_11 中间对齐 向上偏移'),
).applyConstraint(
id: constraintId_11,
width: 80,
height: 200,
centerVerticalTo: constraintId_9,
verticalBias: 0.1,// todo 向上偏移量 0.4
right: parent.right,
),
],
),
);
}
}
约束布局 matchConstraint 属性
matchConstraint 和 widthPercent (设置宽度百分比) 一起使用才有效
// todo © 国宝宝 2024年09月20日 周四 12:35
class SummaryPageState extends State<SummaryPage7> {
ConstraintId constraintId_9 = ConstraintId('ConstraintId_9');
ConstraintId constraintId_10 = ConstraintId('ConstraintId_10');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.lightGreen,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_9'),
).applyConstraint(
id: constraintId_9,
width: matchConstraint,// todo
height: 200,
widthPercent: 0.5,// todo 占 宽度百分之50
bottomCenterTo: parent,
),
Container(
color: Colors.orangeAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_10'),
).applyConstraint(
id: constraintId_10,
width: matchConstraint,// todo
height: 200,
widthPercent: 0.7,// todo 占 宽度百分之70
topCenterTo: parent,
),
],
),
);
}
}
约束ID.baseLine
以某个约束布局组件的ID为基准 来改变位置
// todo © 国宝宝 2024年09月20日 周四 13:47
class SummaryPageState extends State<SummaryPage9> {
ConstraintId constraintId_9 = ConstraintId('ConstraintId_9');
ConstraintId constraintId_10 = ConstraintId('ConstraintId_10');
ConstraintId constraintId_11 = ConstraintId('ConstraintId_11');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.lightGreen,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_9'),
).applyConstraint(
id: constraintId_9,
height: matchConstraint, // todo
width: 100,
heightPercent: 0.3, // todo 占 高度百分之50
centerLeftTo: parent,
),
Container(
color: Colors.orangeAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_10'),
).applyConstraint(
id: constraintId_10,
width: 100,
height: 200,
left: constraintId_9.right,// 位于 ConstraintId_9 右边
baseline: constraintId_9.baseline,// 约束ID.baseLine
),
Container(
color: Colors.greenAccent,
alignment: Alignment.center,
child: const Text('约束布局ID:ConstraintId_11'),
).applyConstraint(
id: constraintId_11,
width: 100,
height: 200,
left: constraintId_10.right,// 位于 ConstraintId_10 右边
baseline: constraintId_10.baseline,// 约束ID.baseLine
),
],
),
);
}
}
栅栏(屏障)Barrier
Barrier 是一个虚拟的组件并不会显示
// todo © 国宝宝 2024年09月20日 周四 14:23
class SummaryPageState extends State<SummaryPage10> {
ConstraintId constraintId_9 = ConstraintId('constraintId_9');
ConstraintId constraintId_10 = ConstraintId('constraintId_10');
ConstraintId barrier_11 = ConstraintId('barrier_11');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.greenAccent,
).applyConstraint(
id: constraintId_9,
size: 200,
topLeftTo: parent,
),
Container(
color: Colors.orangeAccent,
).applyConstraint(
id: constraintId_10,
width: 200,
height: matchConstraint,
centerRightTo: parent,
heightPercent: 0.5,
verticalBias: 0,
),
Barrier(
id: barrier_11,
direction: BarrierDirection.bottom, // todo 方向
referencedIds: [
constraintId_9,
constraintId_10
], // todo 引用的子元素的 id,此处的 id 不能为相对 id
),
const Text(
'位于 栅栏(屏障)Barrier 底部',
style: TextStyle(
fontSize: 20,
color: Colors.blue,
),
).applyConstraint(
centerHorizontalTo: parent,
top: barrier_11.bottom,
)
],
),
);
}
}
通过 setId 设置相对位置
setId (1) 代表第 1 个子元素,setId(2)代表第 2 个子元素,以此类推
setId (-1) 代表 倒数 第 1 个子元素,setId(-2)代表 倒数 第 2 个子元素,以此类推
// todo © 国宝宝 2024年09月20日 周四 14:49
class SummaryPageState extends State<SummaryPage11> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.greenAccent,
).applyConstraint(
size: 50,
topLeftTo: parent,
margin: const EdgeInsets.only(
left: 20,
top: 100,
),
),
Container(
color: Colors.yellowAccent,
).applyConstraint(
size: 100,
top: sId(1).bottom,// todo 相对于第一个子元素 的底部
right: parent.right.margin(100),
),
Container(
color: Colors.purpleAccent,
).applyConstraint(
size: 50,
topRightTo: parent.rightMargin(20).topMargin(0),
),
Container(
color: Colors.cyanAccent,
).applyConstraint(
size: 50,
topRightTo: parent.rightMargin(20).topMargin(200),
),
Container(
color: Colors.blueAccent,
).applyConstraint(
size: 50,
// todo 相对于 倒数 第4个子元素 的底部中心
outBottomCenterTo: sId(-4).topMargin(20),
)
],
)
);
}
}
引导线 Guideline
Guideline 有四个属性可以设置,分别是 horizontal、guidelinePercent、guidelineBegin、guidelineEnd。后三个属性都是相对于 parent 而言。
点击查看代码文件
// todo © 国宝宝 2024年09月20日 周四 16:41
class SummaryPageState extends State<SummaryPage12> {
ConstraintId guideline = ConstraintId('guideline');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: const Color(0xFF005BBB),
).applyConstraint(
width: matchParent,
height: matchConstraint,
top: parent.top,
bottom: guideline.top,
margin: const EdgeInsets.only(top: 150)),
Guideline(
id: guideline,
horizontal: true, //todo 方向,true 为水平,false 为垂直
guidelinePercent: 0.5,
),
Container(
color: const Color(0xFFFFD500),
).applyConstraint(
width: matchParent,
height: matchConstraint,
top: guideline.bottom,
bottom: parent.bottom,
margin: const EdgeInsets.only(bottom: 150)),
const Text(
'引导线 Guideline',
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
textAlign: TextAlign.center,
).applyConstraint(
centerHorizontalTo: parent,
top: guideline.bottom,// todo 位于 引导线 底部
)
],
));
}
}
zIndex 属性
zIndex 越大视图所处的层级就越高(试图层级越高视图就会位于其他视图上面)
// todo © 国宝宝 2024年09月20日 周四 17:01
class SummaryPageState extends State<SummaryPage13> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 位于左上角 zIndex =3 位于最上面
Container(
color: Colors.blueAccent,
).applyConstraint(
width: 160,
height: 160,
topLeftTo: parent,
zIndex: 3,
),
// todo 位于左上角 zIndex =1 位于最下面
Container(
color: Colors.greenAccent,
).applyConstraint(
width: 160,
height: 160,
topLeftTo: parent,
zIndex: 1,
margin: const EdgeInsets.only(top: 30, left: 30)),
// todo 位于左上角 zIndex =2 位于中间
Container(
color: Colors.redAccent,
).applyConstraint(
width: 160,
height: 160,
topLeftTo: parent,
zIndex: 2,
margin: const EdgeInsets.only(top: 60, left: 60)),
],
));
}
}
clickPadding
改变视图点击区域无需改变视图本身大小
// todo © 国宝宝 2024年09月20日 周四 17:21
class SummaryPageState extends State<SummaryPage14> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
// todo 位于 父视图中间
GestureDetector(
onTap: () {
debugPrint('当前区域是否被点击......');
},
child: Container(
color: Colors.blueAccent,
),
).applyConstraint(
width: 160,
height: 160,
centerTo: parent,
clickPadding: const EdgeInsets.all(30)),
],
));
}
}
translate 平移布局
对子视图位置进行平移
// todo © 国宝宝 2024年09月20日 周四 17:43
class SummaryPageState extends State<SummaryPage15> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.blueAccent,
).applyConstraint(
width: 160,
height: 160,
translate: const Offset(80, 0), // todo 向右边平移动 80 距离
centerTo: parent,// todo 位于 父视图 中间位置
),
// todo 位于 父视图中间
Container(
color: Colors.greenAccent,
).applyConstraint(
width: 160,
height: 160,
translate: const Offset(0, -200), // todo 向上边平移动 200 距离
centerTo: parent,// todo 位于 父视图 中间位置
),
],
));
}
}
根据宽高比例布局
宽高比例属性 widthHeightRatio,根据宽高比例来设置视图高度或者宽度
// todo © 国宝宝 2024年09月20日 周四 17:52
class SummaryPageState extends State<SummaryPage16> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: ConstraintLayout(
children: [
Container(
color: Colors.blueAccent,
).applyConstraint(
width: 100,
height: matchConstraint,
widthHeightRatio: 2 / 5, // todo 宽高比例 2/5
centerLeftTo: parent // todo 位于 父视图 左边 中间位置
),
Container(
color: Colors.greenAccent,
).applyConstraint(
width: 100,
height: matchConstraint,
widthHeightRatio: 2 / 3, // todo 宽高比例 2/3
centerRightTo: parent // todo 位于 父视图 右边 中间位置
),
],
));
}
}
网格列表
// todo © 国宝宝 2024年09月21日 周四 19:22
class SummaryPageState extends State<SummaryPage17> {
List<Color> colors = [ Colors.yellowAccent, Colors.indigoAccent, Colors.orangeAccent, Colors.purpleAccent, Colors.indigoAccent, Colors.amberAccent, Colors.lightBlueAccent ];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: SingleChildScrollView(
child: ConstraintLayout(
children: [
...constraintGrid(
id: ConstraintId('grid'),
left: parent.left,
top: parent.top,
itemCount: 160,
columnCount: 6,
itemSize: 60,
itemBuilder: (index, _, __) {
return Container(
color: colors[index % colors.length],
);
},
itemMarginBuilder: (index, _, __) {
return const EdgeInsets.only(
left: 10,
top: 10,
);
})
],
),
));
}
}
wrapContent
不限制视图大小,自适应
// todo © 国宝宝 2024年09月21日 周四 20:09
class SummaryPageState extends State<SummaryPage18> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Summary'),
),
body: Center(
child: ConstraintLayout(
size: wrapContent,
children: [
Container(
color: Colors.blueAccent,
).applyConstraint(
size: matchParent,
),
Container(
color: Colors.yellowAccent,
).applyConstraint(
width: 250,
height: 150,
topLeftTo: parent,
margin: const EdgeInsets.only(
top: 10,
left: 10,
),
),
Container(
color: Colors.orangeAccent,
).applyConstraint(
size: 50,
topRightTo: parent,
),
const Text(
'wrapContent',
).applyConstraint(
outBottomRightTo: rId(1),
),
Container(
color: Colors.redAccent,
).applyConstraint(
size: 50,
centerVerticalTo: parent,
right: rId(2).left,
)
],
),
));
}
}