如何在Flutter中创建如图所示的自定义App Drawer
实现自定义形状的App Drawer
核心方案:用CustomClipper自定义裁剪路径
CustomShapeBorder在处理单侧内凹这类复杂形状时灵活性不足,改用CustomClipper可以精准绘制路径,完美实现目标效果。
完整代码实现
1. 自定义裁剪器类
class CustomDrawerClipper extends CustomClipper<Path> { final double notchRadius; final double topCornerRadius; CustomDrawerClipper({ this.notchRadius = 30.0, this.topCornerRadius = 16.0, }); @override Path getClip(Size size) { final path = Path(); // 绘制左上角圆角 path.moveTo(topCornerRadius, 0); path.arcToPoint( Offset(0, topCornerRadius), radius: Radius.circular(topCornerRadius), clockwise: false, ); // 左侧边延伸至底部 path.lineTo(0, size.height); // 底部延伸至右侧边 path.lineTo(size.width, size.height); // 右侧边向上到缺口起始点 path.lineTo(size.width, notchRadius * 2); // 绘制内凹弧形缺口 path.arcToPoint( Offset(size.width - notchRadius, notchRadius), radius: Radius.circular(notchRadius), clockwise: false, ); // 从缺口回到顶部右侧 path.lineTo(size.width - notchRadius, 0); // 闭合路径 path.close(); return path; } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false; }
2. 在Drawer中应用裁剪器
将Drawer的子组件用ClipPath包裹,指定自定义裁剪器即可:
Drawer( width: MediaQuery.of(context).size.width * 0.85, child: ClipPath( clipper: CustomDrawerClipper(), child: Container( color: Colors.white, child: Column( children: [ // 预留缺口高度,避免顶部内容被裁剪 const SizedBox(height: 60), ListTile( leading: const Icon(Icons.home), title: const Text('首页'), ), ListTile( leading: const Icon(Icons.settings), title: const Text('设置'), ), // 添加更多抽屉列表项 ], ), ), ), )
可调参数说明
notchRadius:控制右侧顶部内凹缺口的大小,数值越大缺口越深topCornerRadius:调整左上角圆角的弧度,按需修改即可- 抽屉宽度通过
width参数设置,这里用屏幕宽度的85%作为示例,可根据需求调整
内容的提问来源于stack exchange,提问作者ETA Dev
相关产品推荐
相关产品推荐

