如何用Flutter CustomPainter实现指定样式的AppBar?
自定义曲线AppBar实现方案
下面是可直接复用的CustomPainter实现及配套自定义AppBar组件,你可以根据需求调整曲线形状:
1. 实现CustomPainter绘制曲线
class CurvedAppBarPainter extends CustomPainter { final Color color; final double curveHeight; CurvedAppBarPainter({required this.color, required this.curveHeight}); @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = color; final path = Path(); // 构建路径:左上角 → 右上角 → 右下角 → 贝塞尔曲线到左下角 → 闭合 path.moveTo(0, 0); path.lineTo(size.width, 0); path.lineTo(size.width, size.height - curveHeight); // 二次贝塞尔曲线(中间凹入效果),可替换为三次贝塞尔实现更复杂形状 path.quadraticBezierTo( size.width / 2, size.height, 0, size.height - curveHeight, ); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }
2. 封装自定义AppBar组件
继承PreferredSizeWidget让它可以直接替换默认AppBar:
class CustomCurvedAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final Color backgroundColor; final double curveHeight; const CustomCurvedAppBar({ super.key, required this.title, this.backgroundColor = Colors.blue, this.curveHeight = 30, }); @override Widget build(BuildContext context) { final appBarHeight = preferredSize.height; return Stack( children: [ // 绘制曲线背景的容器 SizedBox( height: appBarHeight + curveHeight, child: CustomPaint( painter: CurvedAppBarPainter( color: backgroundColor, curveHeight: curveHeight, ), ), ), // 叠加原生AppBar(透明背景) Positioned( top: MediaQuery.of(context).padding.top, left: 0, right: 0, child: SizedBox( height: appBarHeight, child: AppBar( backgroundColor: Colors.transparent, elevation: 0, title: Text(title), centerTitle: true, // 可添加leading、actions等原生AppBar属性 ), ), ), ], ); } @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); }
3. 使用示例
Scaffold( appBar: CustomCurvedAppBar( title: "我的自定义AppBar", backgroundColor: Colors.deepPurple, curveHeight: 40, // 调整这个值改变曲线幅度 ), body: const Center(child: Text("页面内容")), )
调整曲线形状的技巧
- 如果需要更复杂的曲线,把
quadraticBezierTo换成cubicTo,通过两个控制点微调形状:path.cubicTo( size.width * 0.3, size.height - curveHeight, // 第一个控制点 size.width * 0.7, size.height, // 第二个控制点 0, size.height - curveHeight, // 终点 ); - 改变
curveHeight的数值可以控制曲线的凸起/凹陷程度 - 若要修改曲线位置(比如偏左/偏右),调整贝塞尔曲线的控制点x坐标即可
内容的提问来源于stack exchange,提问作者Sonu Saini
相关产品推荐
相关产品推荐

