可容納一個子組件,並指定代理類對子組件進行排布。代理類可獲取父容器區域和子組件的區域大小,及區域約束狀況。android
名稱: CustomSingleChildLayout 通用單子排布
類型: 佈局型
重要性: ☆☆☆
相關組件: 【Align】、【FractionallySizedBox】、【CustomMultiChildLayout】
家族: RenderObjectWidget
|--- SingleChildRenderObjectWidget
|--- CustomSingleChildLayout
複製代碼
這裏父容器使用
11灰的300*200的盒子
,子組件爲不設寬高的橙色Container
。
以下: 默認的約束條件,會使橙色Container
伸展佔滿父容器。git
class CustomSingleChildLayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 200,
color: Colors.grey.withAlpha(11),
child:nContainer(
color: Colors.orange,
),
);
}
}
複製代碼
CustomSingleChildLayout容納一個child,且須要一個抽象代理類
SingleChildLayoutDelegate
Flutter並無提供可用的實現類,因此只能自定義_TolySingleChildLayoutDelegate
。github
class CustomSingleChildLayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 200,
color: Colors.grey.withAlpha(11),
child: CustomSingleChildLayout(
delegate: _TolySingleChildLayoutDelegate(),
child: Container(
color: Colors.orange,
),
),
);
}
}
複製代碼
SingleChildLayoutDelegate
必須實現shouldRelayout
方法,可重寫:Size getSize(BoxConstraints)
: 可獲取父容器約束條件Offset getPositionForChild(Size, Size)
可獲取父子組件的區域,返回子組件偏移量BoxConstraints getConstraintsForChild(BoxConstraints)
可獲取父容器約束條件,並返回新的約束條件class _TolySingleChildLayoutDelegate extends SingleChildLayoutDelegate {
@override
bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
return true;
}
@override
Size getSize(BoxConstraints constraints) {
print('----getSize:----constraints:$constraints----');
return super.getSize(constraints);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
print('----size:$size----childSize:$childSize----');
return super.getPositionForChild(size, childSize);
}
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
print('----getConstraintsForChild:----constraints:$constraints----');
return super.getConstraintsForChild(constraints);
}
}
複製代碼
看一下運行打印結果:編程
I/flutter (28366): ----getSize:----constraints:BoxConstraints(w=300.0, h=200.0)----
I/flutter (28366): ----getConstraintsForChild:----constraints:BoxConstraints(w=300.0, h=200.0)----
I/flutter (28366): ----size:Size(300.0, 200.0)----childSize:Size(300.0, 200.0)----
複製代碼
getConstraintsForChild
能夠根據原約束區域
返回新的約束區域
。以下:bash
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
print('----getConstraintsForChild:----constraints:$constraints----');
return BoxConstraints(
maxHeight: constraints.maxHeight/2,
maxWidth: constraints.maxWidth/2,
minHeight: constraints.maxHeight/4,
minWidth: constraints.maxWidth/4,
);
}
複製代碼
Offset getPositionForChild(Size, Size)
可獲取父、子組件的區域,返回子組件偏移量@override
Offset getPositionForChild(Size size, Size childSize) {
print('----size:$size----childSize:$childSize----');
return Offset(size.width/2,0 );
}
複製代碼
從上面能夠看出,使用
CustomSingleChildLayout
能夠獲取父組件和子組件的佈局區域。並能夠對子組件進行盒約束
及偏移定位
。一句話來講用於排佈一個組件。
微信
傳入一個
Offset對象
控制子組件的偏移。less
class _OffSetDelegate extends SingleChildLayoutDelegate {
final Offset offset;
_OffSetDelegate({this.offset = Offset.zero});
@override
bool shouldRelayout(_OffSetDelegate oldDelegate) =>
offset != oldDelegate.offset;
@override
Offset getPositionForChild(Size size, Size childSize) {
return offset;
}
}
複製代碼
OffSetWidget
你能夠直接用
CustomSingleChildLayout組件
,但爲了方便使用,通常都會進行封裝使用
下面的OffSetWidget組件
能夠實現子組件相對於父組件的偏移。ide
class OffSetWidget extends StatelessWidget {
final Offset offset;
final Widget child;
OffSetWidget({this.offset = Offset.zero, this.child});
@override
Widget build(BuildContext context) {
return CustomSingleChildLayout(
delegate: _OffSetDelegate(offset: offset),
child: child,
);
}
}
複製代碼
這樣就可讓子組件在父組件中發生相對偏移。
簡約派表明:"等等...老子看了半天,你給我個簡易版的Padding?還花裏胡哨的。"
兄臺莫急,且往下看。佈局
class OffSetWidgetDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 100,
alignment: Alignment.topRight,
color: Colors.grey.withAlpha(11),
child: OffSetWidget(
offset: Offset(20, 20),
child: Icon(Icons.android, size: 30,color: Colors.green,),
));
}
}
複製代碼
這裏最大的優點是:
Offset支持負偏移
測試
child: OffSetWidget(
offset: Offset(-20, 20),
child: Icon(Icons.android, size: 30,color: Colors.green,),
));
複製代碼
經過動態計算,能夠鎖定訪問進行偏移,以下:
這樣就像Position的能力,但Position有必須用於Stack的如今。
而OffSetWidget
隨意 而且支持負偏移
class OffSetWidget extends StatelessWidget {
final Offset offset;
final Widget child;
final Direction direction;
OffSetWidget({this.offset = Offset.zero,
this.child,
this.direction = Direction.topLeft});
@override
Widget build(BuildContext context) {
return CustomSingleChildLayout(
delegate: _OffSetDelegate(offset: offset, direction: direction),
child: child,
);
}
}
enum Direction { topLeft, topRight, bottomLeft, bottomRight }
class _OffSetDelegate extends SingleChildLayoutDelegate {
final Offset offset;
final Direction direction;
_OffSetDelegate(
{this.offset = Offset.zero, this.direction = Direction.topLeft});
@override
bool shouldRelayout(_OffSetDelegate oldDelegate) =>
offset != oldDelegate.offset;
@override
Offset getPositionForChild(Size size, Size childSize) {
var w = size.width;
var h = size.height;
var wc = childSize.width;
var hc = childSize.height;
switch (direction) {
case Direction.topLeft:
return offset;
case Direction.topRight:
return offset.translate(w - wc - offset.dx * 2, 0);
case Direction.bottomLeft:
return offset.translate(0, h - hc - offset.dy * 2);
case Direction.bottomRight:
return offset.translate(w - wc - offset.dx * 2, h - hc - offset.dy * 2);
}
return offset;
}
}
複製代碼
CustomSingleChildLayout
組件的用法仍是比較簡單的。上面代碼只是簡單演示一下使用方式,也許並非太實用。Positioned組件
能夠實現定位,SizedOverflowBox組件
能夠實現溢出。 不過當你遇到對某一個組件約束或定位困難時,CustomSingleChildLayout
也許能夠幫到你。
歡迎Star和關注FlutterUnit 的發展,讓咱們一塊兒攜手,成爲Unit一員。
另外本人有一個Flutter微信交流羣,歡迎小夥伴加入,共同分享Flutter的知識,期待與你的交流與切磋。
@張風捷特烈 2020.05.26 未允禁轉
個人公衆號:編程之王
聯繫我--郵箱:1981462002@qq.com --微信:zdl1994328
~ END ~