Stack/Positioned是用来做页面布局定位的组件,需要结合使用
Stack
children
:一个数组,里面可放多个Widgetalignment
:Alignment.topCenter//对齐方式,会对所有的子组件统一设置对齐,不灵活,一般不用Positioned
child
:一个子组件left,top,right,bottom,width,heigh
://设置这些值会改变子组件的大小,位置(相对于最外层组件)
Stack
Stack组件可以将子组件叠加显示,根据子组件的顺利依次向上叠加,用法如下:
Stack(children: <Widget>[Container(height: 200,width: 200,color: Colors.red,),Container(height: 170,width: 170,color: Colors.blue,),Container(height: 140,width: 140,color: Colors.yellow,),ElevatedButton(onPressed: (){}, child: Text('这个视图按钮好'))],)
从效果可以看出视图一次从左上方开始堆叠,子视图最下方的视图展示再最外层。
Stack未定位的子组件大小由fit
参数决定,默认值是StackFit.loose
,表示子组件自己决定,StackFit.expand
表示尽可能的大,用法如下:
Stack(fit: StackFit.expand,...
)
Stack未定位的子组件的默认左上角对齐,通过alignment
参数控制,用法如下:
Stack(alignment: Alignment.center,...
)
有没有注意到fit
和alignment
参数控制的都是未定位的子组件,那什么样的组件叫做定位的子组件?使用Positioned包裹的子组件就是定位的子组件,用法如下:
Stack(fit: StackFit.loose,alignment: Alignment.center,children: <Widget>[Container(height: 200,width: 200,color: Colors.red,),Container(height: 170,width: 170,color: Colors.blue,),Container(height: 140,width: 140,color: Colors.yellow,),Positioned(bottom: 0,right: 0,child: ElevatedButton(onPressed: (){}, child: Text('这个视图按钮好')))],)
如果子组件超过Stack边界由clipBehavior
控制,默认是裁剪,下面设置总是显示的用法:
Stack(clipBehavior: Clip.none,children: <Widget>[Container(height: 200,width: 200,color: Colors.red,),Positioned(left: 100,top: 100,height: 150,width: 150,child: Container(color: Colors.green,),)],)
IndexedStack
IndexedStack是Stack的子类,Stack是将所有的子组件叠加显示,而IndexedStack只显示指定的子组件,用法如下:
Column(children: [_buildView3(),Row(children: [ElevatedButton(onPressed: (){setState(() {_index=0;});}, child: Icon(Icons.fastfood)),ElevatedButton(onPressed: (){setState(() {_index=1;});}, child: Icon(Icons.cake)),ElevatedButton(onPressed: (){setState(() {_index=2;});}, child: Icon(Icons.local_cafe))],)],)_buildView3(){return IndexedStack(index: _index,children: [Center(child: Container(height: 300,width: 300,color: Colors.yellow,child: Icon(Icons.fastfood,color: Colors.blue,),),),Center(child: Container(height: 300,width: 300,color: Colors.red,child: Icon(Icons.cake,color: Colors.blue,),),),Center(child: Container(height: 300,width: 300,color: Colors.blueGrey,child: Icon(Icons.local_cafe,color: Colors.blue,),),),],);}
效果(点击切换_inex,只显示第index层视图):
Positioned
Positioned用于定位Stack子组件,Positioned必须是Stack的子组件,基本用法如下:
Container(height: 300,width: 300,color: Colors.amberAccent,child: Stack(children: <Widget>[Positioned(left: 10,right: 10,top: 10,bottom: 10,child: Container(color: Colors.red),),],),)
相关说明:
-
提供
top
、bottom
、left
、right
四种定位属性,分别表示距离上下左右的距离。 -
只能用于Stack组件中。
-
left
、right
和width
3个参数只能设置其中2个,因为设置了其中2个,第三个已经确定了,同理top
、bottom
和height
也只能设置其中2个。
Positioned提供便捷的构建方式,比如Positioned.fromRect
、Positioned.fill
等,这些便捷的构建方式万变不离其宗,只不过换了一种方式设置top
、bottom
、left
、right
四种定位属性。