Flutter中能否实现Row布局下的斜角ElevatedButton?
实现斜角拼接按钮完全可行
可以通过自定义ShapeBorder来改造ElevatedButton,既实现首尾按钮垂直边缘、中间按钮斜角边缘的效果,又能完全沿用ElevatedButton的原有配置(比如点击事件、样式、子组件支持文本/图标等)。
核心实现思路
- 自定义一个
CustomButtonShape类,继承ShapeBorder,根据按钮在Row中的位置(首、中、尾)生成对应的路径:- 首按钮:左侧边缘垂直,右侧边缘斜角
- 中间按钮:左右两侧都是斜角
- 尾按钮:右侧边缘垂直,左侧边缘斜角
- 封装一个
CustomElevatedButton组件,接收位置参数,将自定义shape传入ElevatedButton的style中。
完整代码示例
import 'package:flutter/material.dart'; enum ButtonPosition { first, middle, last } class CustomButtonShape extends ShapeBorder { final ButtonPosition position; final double skewWidth; // 斜角的宽度 CustomButtonShape({required this.position, this.skewWidth = 16.0}); @override EdgeInsetsGeometry get dimensions => EdgeInsets.zero; @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) => getOuterPath(rect, textDirection: textDirection); @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { final path = Path(); switch (position) { case ButtonPosition.first: // 首按钮:左垂直,右斜角 path.moveTo(rect.left, rect.top); path.lineTo(rect.right - skewWidth, rect.top); path.lineTo(rect.right, rect.bottom); path.lineTo(rect.left, rect.bottom); path.close(); break; case ButtonPosition.middle: // 中间按钮:左右斜角 path.moveTo(rect.left + skewWidth, rect.top); path.lineTo(rect.right - skewWidth, rect.top); path.lineTo(rect.right, rect.bottom); path.lineTo(rect.left, rect.bottom); path.close(); break; case ButtonPosition.last: // 尾按钮:右垂直,左斜角 path.moveTo(rect.left + skewWidth, rect.top); path.lineTo(rect.right, rect.top); path.lineTo(rect.right, rect.bottom); path.lineTo(rect.left, rect.bottom); path.close(); break; } return path; } @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} @override ShapeBorder scale(double t) => this; } // 封装后的自定义ElevatedButton class CustomElevatedButton extends StatelessWidget { final ButtonPosition position; final VoidCallback? onPressed; final Widget child; final ButtonStyle? style; final double skewWidth; const CustomElevatedButton({ super.key, required this.position, required this.onPressed, required this.child, this.style, this.skewWidth = 16.0, }); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: style?.copyWith( shape: MaterialStateProperty.all( CustomButtonShape(position: position, skewWidth: skewWidth), ), ) ?? ElevatedButton.styleFrom( shape: CustomButtonShape(position: position, skewWidth: skewWidth), ), child: child, ); } } // 使用示例 class SkewedButtonRow extends StatelessWidget { const SkewedButtonRow({super.key}); @override Widget build(BuildContext context) { return Row( children: [ Expanded( child: CustomElevatedButton( position: ButtonPosition.first, onPressed: () {}, child: const Text('首页'), style: ElevatedButton.styleFrom(backgroundColor: Colors.blue), ), ), Expanded( child: CustomElevatedButton( position: ButtonPosition.middle, onPressed: () {}, child: const Icon(Icons.search), style: ElevatedButton.styleFrom(backgroundColor: Colors.green), ), ), Expanded( child: CustomElevatedButton( position: ButtonPosition.last, onPressed: () {}, child: const Text('我的'), style: ElevatedButton.styleFrom(backgroundColor: Colors.orange), ), ), ], ); } }
关键说明
- 通过
ButtonPosition枚举控制按钮的形状逻辑,调整skewWidth可以改变斜角的倾斜程度 CustomElevatedButton完全兼容原生ElevatedButton的所有配置项,包括onPressed、style、child等,你可以像使用普通ElevatedButton一样设置文本、图标、背景色、字体样式等- 用
Expanded包裹按钮可以让它们在Row中均分宽度,也可以根据需求设置固定宽度
内容的提问来源于stack exchange,提问作者user2609021
相关产品推荐
相关产品推荐

