参考资料: 《Flutter实战·第二版》 10.2 组合现有组件
在Flutter中页面UI通常都是由一些低级别组件组合而成,当我们需要封装一些通用组件时,应该首先考虑是否可以通过组合其他组件来实现,如果可以,则应优先使用组合,因为直接通过现有组件拼装会非常简单、灵活、高效。
10.2.1 实例:自定义渐变按钮
Flutter中自带的按钮组件不支持渐变背景,这里自定义一个GradientButton
组件,具有下面的功能:
- 背景支持渐变色
- 手指按下时有涟漪效果
- 可以支持圆角
自带的按钮组件是下面的效果:
其实除了不是渐变色背景其它都满足了。在Flutter中,ElevatedButton
组件默认不具有圆角。然而,可以通过自定义其形状来为其添加圆角。可以在ElevatedButton
的style
属性中设置shape
属性来实现:
ElevatedButton(
onPressed: () {
print('Button pressed!');
},
child: Text('Press Me'),
style: ElevatedButton.styleFrom(
primary: Colors.blue, // 设置按钮的主色
onPrimary: Colors.white, // 设置按钮上文字的颜色
shape: RoundedRectangleBorder( // 设置按钮的形状为圆角矩形
borderRadius: BorderRadius.circular(20.0), // 设置圆角的大小
),
),
)
想有渐变背景的话,不能通过style
属性设置背景色,因为数据类型是有限制的。可以利用DecoratedBox
和InkWell
组合来实现,前者能够设置圆角和渐变背景色,后者可以提供涟漪效果。下面是实现代码,思路比较简单,主要是UI的绘制逻辑:
class GradientButton extends StatelessWidget {
const GradientButton({
Key? key,
this.colors,
this.width,
this.height,
this.onPressed,
this.borderRadius,
required this.child,
}) : super(key: key);
// 渐变色数组
final List<Color>? colors;
// 按钮宽高
final double? width;
final double? height;
final BorderRadius? borderRadius;
//点击回调
final GestureTapCallback? onPressed;
final Widget child;
Widget build(BuildContext context) {
ThemeData theme = Theme.of(context);
//确保colors数组不空
List<Color> _colors =
colors ?? [theme.primaryColor, theme.primaryColorDark];
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: _colors),
borderRadius