利用Flutter轻松制作红包界面
岛上码农 人气:0前言
在 Flutter 的开发中,最常见的就是层层的组件嵌套,因此不可避免会遇到子组件如何适配父组件的问题。比如,按钮的可点击区域是否要占满整个父组件?图片是居中还是居左?这些问题可以通过 Flutter 提供的FittedBox
组件来解决。
FittedBox 简介
FittedBox
组件设计的目的就是让其子组件与父级组件进行适配,包括对齐、缩放、裁剪和溢出处理。
const FittedBox({ Key? key, this.fit = BoxFit.contain, this.alignment = Alignment.center, this.clipBehavior = Clip.none, Widget? child, })
如上所示,FittedBox
的定义很简洁,只有下面四个属性:
fit
:子组件和父组件的适配模式,BoxFit 枚举,包括了不处理(none
)、尽量包含(contain
),拉伸填满(fill
),宽度方向填满(fitWidth
),高度方向填满(fitHeight
)和缩小到父组件内(scaleDown
),具体适配的样式可以看官方的文档 不同 BoxFit 样式。alignment
:子组件与父组件的对齐方式,包括居中(center
)、左侧居中(centerLeft
)、右侧居中(centerRight
),顶部居中(topCenter
)、底部居中(bottomCenter
)等。clipBehavior
:超出后的裁剪模式,即子组件溢出父组件后要不要裁剪,不裁剪的话子组件可能会超出父组件的显示范围。child
:要适配的子组件。
使用示例
我们来看一张图片在不同适配参数下的效果,这里我们可以在底部切换不同的适配模式,注意这里我们使用了裁剪来防止溢出,clipBehavior
参数为 Clip.antiAlias
。可以看到图片随着不同的模式显示的区域、对齐也会不同,这就给我们提供了子组件适配很大的灵活性。
上面的示例代码如下。
var _fit = BoxFit.none; var _alignment = Alignment.center; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( title: const Text('FittedBox'), backgroundColor: Colors.red[400]!), body: Center( child: Container( width: MediaQuery.of(context).size.width - 30.0, height: 160.0, color: Colors.blue, child: FittedBox( alignment: _alignment, fit: _fit, clipBehavior: Clip.antiAlias, child: Image.asset('images/girl.jpeg'), ), ), ), bottomSheet: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DropdownButton( items: const [ DropdownMenuItem<BoxFit>( value: BoxFit.none, child: Text('BoxFit.none'), ), DropdownMenuItem<BoxFit>( value: BoxFit.contain, child: Text('BoxFit.contain'), ), DropdownMenuItem<BoxFit>( value: BoxFit.fill, child: Text('BoxFit.fill'), ), DropdownMenuItem<BoxFit>( value: BoxFit.cover, child: Text('BoxFit.cover'), ), DropdownMenuItem<BoxFit>( value: BoxFit.fitHeight, child: Text('BoxFit.fitHeight'), ), DropdownMenuItem<BoxFit>( value: BoxFit.fitWidth, child: Text('BoxFit.fitWidth'), ), DropdownMenuItem<BoxFit>( value: BoxFit.scaleDown, child: Text('BoxFit.scaleDown'), ), ], value: _fit, onChanged: (fit) { setState(() { _fit = fit as BoxFit; }); }, ), DropdownButton( items: const [ DropdownMenuItem<Alignment>( value: Alignment.center, child: Text('Alignment.center'), ), DropdownMenuItem<Alignment>( value: Alignment.centerLeft, child: Text('Alignment.centerLeft'), ), DropdownMenuItem<Alignment>( value: Alignment.centerRight, child: Text('Alignment.centerRight'), ), DropdownMenuItem<Alignment>( value: Alignment.topCenter, child: Text('Alignment.topCenter'), ), DropdownMenuItem<Alignment>( value: Alignment.bottomCenter, child: Text('Alignment.bottomCenter'), ), DropdownMenuItem<Alignment>( value: Alignment.topLeft, child: Text('Alignment.topLeft'), ), ], value: _alignment, alignment: AlignmentDirectional.center, onChanged: (alignment) { setState(() { _alignment = alignment as Alignment; }); }, ), ], ), ); }
红包界面
下面我们来用 FittedBox
做一个红包界面效果,如下图所示。
这里红包顶部的深色部分其实就是用 FittedBox
将一个 Container
贴在了顶部居中位置。具体实现代码如下所示。
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( title: const Text('FittedBox'), backgroundColor: Colors.red[400]!), body: Center( child: Stack( alignment: Alignment.center, children: [ Container( width: 240.0, height: 400.0, color: Colors.red, child: FittedBox( alignment: Alignment.topCenter, fit: BoxFit.fitWidth, clipBehavior: Clip.antiAlias, child: Container( height: 50.0, width: 160.0, decoration: BoxDecoration( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(160.0), bottomRight: Radius.circular(160.0)), color: Colors.red[800], ), ), ), ), ClipOval( child: Container( width: 80, height: 80, alignment: Alignment.center, color: Colors.yellow[700], child: const Text( '開', style: TextStyle( fontSize: 42.0, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), ), ], ), ), ); }
总结
本篇介绍了 Flutter 中的布局组件 FittedBox
的使用。FittedBox
是一个非常简单、但实用的组件,通过它,我们可以将子组件按一定的方式适配到父组件实现所需要的布局,从而简化开发中的布局样式的代码编写。
加载全部内容