前言
参考:Flutter 实战
由于是初学者,因此只会学习一些基础的东西,对于复杂部分可以自行查看该书。
组合现有组件
这一部分还是比较好理解的,比如基于element提供的组件可以封装一个通用的业务组件,减少代码的耦合同时方便业务的开发。在flutter中也是如此,利用一些基本组件来组合成一个通用的业务组件。
有一点挺讨厌的,拿element来说,有一个组件列表,以及组件的使用文档。但是学习flutter这么久了,一直也不知道这些基本组件的使用文档在哪,只能通过看书、记笔记的方式来学习。
自定义渐变按钮
基本功能
- 背景支持渐变色
- 按下时有涟漪效果
- 支持圆角
对文章中的代码进行了简单修改
import 'package:flutter/material.dart';
// 继承无状态组件
class GradientButton extends StatelessWidget {
// 构造函数
const GradientButton({
Key? key,
this.linearGradient, //渐变
this.width, // 宽度
this.height, // 高度
this.borderRadius, //圆角
required this.onPressed, //点击事件
required this.child, // 子组件
}) : super(key: key);
// 渐变颜色组
final LinearGradient? linearGradient;
// 按钮宽高、圆角
final double? width;
final double? height;
final BorderRadius? borderRadius;
// 点击事件
final GestureTapCallback onPressed;
// 子组件
final Widget child;
Widget build(BuildContext context) {
// 获取上下文主题
ThemeData theme = Theme.of(context);
// 处理渐变保证有一个默认值
LinearGradient? newLinearGradient = linearGradient ??
LinearGradient(colors: [theme.primaryColor, theme.primaryColorDark]);
// DecoratedBox用于装饰其子组件的组件。它可以为子组件添加背景色、边框、圆角等装饰效果。
return DecoratedBox(
decoration: BoxDecoration(
gradient: newLinearGradient, //线性渐变
borderRadius: borderRadius),
child: Material(
type: MaterialType.transparency,
// InkWell可以产生水波的效果
child: InkWell(
highlightColor: Colors.transparent,
borderRadius: borderRadius,
onTap: onPressed,
// 宽高被限制的组件
child: ConstrainedBox(
// 如果height和width为null,会自适应子组件带
constraints: BoxConstraints.tightFor(height: height, width: width),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: DefaultTextStyle(
style: const TextStyle(fontWeight: FontWeight.bold),
child: child,
),
),
),
),
),
),
);
}
}
GradientButton(
onPressed: () {
print("点击了");
},
width: 200,
height: 40,
borderRadius: BorderRadius.circular(5),
child: const Text("渐变按钮"),
),
遇到的问题:
1、就是知识储备不够,好多组件根本就不知道
2、第二个就是flutter对于类型越来越严格,以文章中的代码为例
const GradientButton({
Key? key,
this.colors,
this.width,
this.height,
this.onPressed,
this.borderRadius,
required this.child,
}) : super(key: key);
// 渐变色数组
final List<Color>? colors;
//确保colors数组不空
List<Color> _colors =
colors ?? [theme.primaryColor, theme.primaryColorDark];
虽然颜色数组不为null了,但是如果是[],是会报错的,线性渐变组件最少要有两个颜色值。
最初我的改法是
List<Color>_color = (colors==null || colors.isEmpty) ? [theme.primaryColor, theme.primaryColorDark] :colors;
但是编译器一直提示我改为
List<Color>?_color = (colors==null || colors.isEmpty) ? [theme.primaryColor, theme.primaryColorDark] :colors;
因为前面设置了colors
可以为空,final List<Color>? colors;
当colors
不为空是_color
赋值后的类型就必须是 List<Color>?
;但是LinearGradient
要求参数的类型必须是List<Color>
,所以就导致编译不通过。
这里不是说作者代码写的不好,是感慨flutter越来越完善,越来越严格了。以前可以正常运行的代码,现在在编译器里都会给予提示,就比如编译器会让你在组件前面加一个const