一統天下 flutter - widget 佈局類(可以有多個子): CustomMultiChildLayout - 自定義多組件佈局
示例如下:
lib\widget\layout\custom_multi_child_layout.dart
/*
* CustomMultiChildLayout - 自定義多組件佈局
*
* 注:約束是從上向下傳遞的,尺寸是從下向上傳遞的
*/
import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';
class CustomMultiChildLayoutDemo extends StatefulWidget {
const CustomMultiChildLayoutDemo({Key? key}) : super(key: key);
@override
_CustomMultiChildLayoutDemoState createState() => _CustomMultiChildLayoutDemoState();
}
class _CustomMultiChildLayoutDemoState extends State<CustomMultiChildLayoutDemo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("title"),),
backgroundColor: Colors.orange,
/// 自定義佈局
body: CustomMultiChildLayout(
/// 通過指定的 delegate 實現具體的佈局
delegate: _MyMultiChildLayoutDelegate(),
children: [
/// 通過 LayoutId 指定需要佈局的組件的 id
LayoutId(
id: 'a',
child: Container(
color: Colors.red,
),
),
LayoutId(
id: 'b',
child: Container(
width: 200,
height: 200,
color: Colors.green,
),
),
],
),
);
}
}
class _MyMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
/// 用於對每個子組件做佈局
@override
void performLayout(Size size) {
/// 這個 size 就是 CustomMultiChildLayout 的可用空間
log("performLayout size:$size");
/// 用於判斷 CustomMultiChildLayout 的 children 內是否存在指定 id 的組件
/// 在 CustomMultiChildLayout 的 children 內需要通過 LayoutId 指定組件的 id
if (hasChild('a')) {
}
/// 對 id 爲 a 的組件佈局,父把約束告訴子,然後子會把自己的尺寸告訴父
var size_a = layoutChild("a", BoxConstraints(minWidth: 100, minHeight: 100, maxWidth: 100, maxHeight: 100));
/// 對 id 爲 b 的組件佈局,父把約束告訴子,然後子會把自己的尺寸告訴父
var size_b = layoutChild("b", BoxConstraints(minWidth: 0, minHeight: 0, maxWidth: 100, maxHeight: size.height));
/// 設置 id 爲 a 的組件的位置
positionChild("a", Offset(0, 0));
/// 設置 id 爲 b 的組件的位置
positionChild("b", Offset(100, 100));
}
/// 當 MultiChildLayoutDelegate 發生變化時,通過這裏決定是否需要重新佈局
@override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
return true;
}
/// constraints 爲 CustomMultiChildLayout 的父傳給 CustomMultiChildLayout 的約束
/// 返回值爲 CustomMultiChildLayout 根據約束決定的自己的尺寸
@override
Size getSize(BoxConstraints constraints) {
var size = super.getSize(constraints);
log('getSize constraints:$constraints, size:$size');
return size;
}
/// constraints 爲 CustomMultiChildLayout 傳給 id 爲 childId 的子的約束
/// 返回值爲子根據約束決定的自己的尺寸
@override
Size layoutChild(Object childId, BoxConstraints constraints) {
var size = super.layoutChild(childId, constraints);
log('layoutChild childId:$childId, constraints:$constraints, size:$size');
return size;
}
}