自定义按钮的要点
Flutter 的按钮(ElevatedButton
、TextButton
、OutlinedButton
等)只是官方帮你封装好的组件,本质上就是一个 可点击的 Widget。
我们完全可以用 GestureDetector
或 InkWell
自己包装一个 自定义按钮。
可点击事件(交互性)
- 按钮必须能响应用户点击。
- 常用方式:
GestureDetector
→ 最原始的手势检测器。InkWell
/InkResponse
→ 带水波纹的点击效果,更符合 Material 风格。
没有点击回调,它只是个普通的 Container
,不能算按钮。
视觉样式(外观)
用 Container
/ DecoratedBox
控制背景、圆角、边框、阴影。
常见属性:
- 颜色(背景/文字)
- 形状(圆角、圆形、矩形)
- 大小(padding、margin、constraints)
- 阴影(
BoxShadow
)
样式决定了按钮的“看起来”的样子。
状态反馈(用户体验)
按钮最好有 按下、禁用、悬浮 等状态。
InkWell
可以提供水波纹反馈。也可以用
AnimatedContainer
做渐变缩放、变色。没有反馈的按钮,用户体验会很差。
可复用性(组件化)
自定义按钮最好封装成一个
StatelessWidget
或StatefulWidget
,便于项目中重复使用。通过构造函数传递参数:
text
、color
、onTap
、icon
等。让它像官方的
ElevatedButton
一样易用。
代码
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String text; // 按钮文字
final VoidCallback onTap; // 点击回调
final Color color; // 背景颜色
const CustomButton({
super.key,
required this.text,
required this.onTap,
this.color = Colors.red, // 默认红色
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap, // 点击事件
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(12), // 圆角
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: const Offset(2, 2),
),
],
),
child: Text(
text,
style: const TextStyle(
color: Colors.white, // 文字白色
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
);
}
}
class MyPage extends StatelessWidget {
const MyPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("自定义按钮示例")),
body: Center(
child: CustomButton(
text: "点我一下",
onTap: () {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text("自定义按钮被点击啦!")));
},
),
),
);
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '自定义按钮示例',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyPage(),
);
}
}
