如何在 Flutter 中创建圆形图标按钮?
Posted
技术标签:
【中文标题】如何在 Flutter 中创建圆形图标按钮?【英文标题】:How to create a circle icon button in Flutter? 【发布时间】:2018-09-23 08:41:38 【问题描述】:如何创建类似于FloatingActionButton
的内容?
【问题讨论】:
【参考方案1】:我认为 RawMaterialButton 更适合。
RawMaterialButton(
onPressed: () ,
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
【讨论】:
我用这种方法得到了一个很大的水平填充,无论我尝试什么都无法删除它。有什么想法吗? 我使用 RawMaterialButton 约束的约束属性解决了这个问题: BoxConstraints(minWidth: 36.0, maxWidth: 36.0, minHeight: 36.0, maxHeight: 36.0 这可能不是最好的解决方案,但它确实有效。跨度> 要完全删除按钮周围的填充,还可以添加materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
对我来说,要删除我添加的填充:constraints: BoxConstraints.expand(width: 42, height: 42),
对我来说最好的方法是结合 materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
、padding: EdgeInsets.all(8)
和 constraints: BoxConstraints(minWidth: 0)
【参考方案2】:
更新(使用新的ElevatedButton
)
ElevatedButton
(自定义较少)
ElevatedButton(
onPressed: () ,
child: Icon(Icons.menu, color: Colors.white),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(20),
primary: Colors.blue, // <-- Button color
onPrimary: Colors.red, // <-- Splash color
),
)
ElevatedButton
(有更多自定义)
ElevatedButton(
onPressed: () ,
child: Icon(Icons.menu),
style: ButtonStyle(
shape: MaterialStateProperty.all(CircleBorder()),
padding: MaterialStateProperty.all(EdgeInsets.all(20)),
backgroundColor: MaterialStateProperty.all(Colors.blue), // <-- Button color
overlayColor: MaterialStateProperty.resolveWith<Color?>((states)
if (states.contains(MaterialState.pressed)) return Colors.red; // <-- Splash color
),
),
)
使用InkWell
ClipOval(
child: Material(
color: Colors.blue, // Button color
child: InkWell(
splashColor: Colors.red, // Splash color
onTap: () ,
child: SizedBox(width: 56, height: 56, child: Icon(Icons.menu)),
),
),
)
输出(后两个相同):
【讨论】:
【参考方案3】:你只需要使用形状:CircleBorder()
MaterialButton(
onPressed: () ,
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
)
【讨论】:
如果您使用填充,请确保设置 minWidth。【参考方案4】:您可以使用InkWell 来做到这一点:
响应触摸的材质的矩形区域。
以下示例演示如何使用InkWell
。 注意:您不需要StatefulWidget
来执行此操作。我用它来改变计数的状态。
例子:
import 'package:flutter/material.dart';
class SettingPage extends StatefulWidget
@override
_SettingPageState createState() => new _SettingPageState();
class _SettingPageState extends State<SettingPage>
int _count = 0;
@override
Widget build(BuildContext context)
return new Scaffold(
body: new Center(
child: new InkWell(// this is the one you are looking for..........
onTap: () => setState(() => _count++),
child: new Container(
//width: 50.0,
//height: 50.0,
padding: const EdgeInsets.all(20.0),//I used some padding without fixed width and height
decoration: new BoxDecoration(
shape: BoxShape.circle,// You can use like this way or like the below line
//borderRadius: new BorderRadius.circular(30.0),
color: Colors.green,
),
child: new Text(_count.toString(), style: new TextStyle(color: Colors.white, fontSize: 50.0)),// You can add a Icon instead of text also, like below.
//child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
),//............
),
),
);
如果您想获得splashColor
、highlightColor
的好处,请使用带有材质类型圆的Material
小部件包装InkWell
小部件。然后删除 Container
小部件中的 decoration
。
结果:
【讨论】:
布拉桑卡,感谢您提供的信息。我最终改用了 FloatingActionButton。但您的解决方案将在未来的其他场景中派上用场。 此代码不再创建“圆形”按钮。【参考方案5】:如果您需要背景图片,可以使用 CircleAvatar 和 IconButton。设置 backgroundImage 属性。
CircleAvatar(
backgroundImage: NetworkImage(userAvatarUrl),
)
按钮示例:
CircleAvatar(
backgroundColor: Colors.blue,
radius: 20,
child: IconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () ,
),
),
【讨论】:
【参考方案6】:您可以轻松地执行以下操作:
FlatButton(
onPressed: ()
,
child: new Icon(
Icons.arrow_forward,
color: Colors.white,
size: 20.0,
),
shape: new CircleBorder(),
color: Colors.black12,
)
结果是
【讨论】:
仅供参考,FlatButton 已弃用【参考方案7】:RawMaterialButton(
onPressed: () ,
constraints: BoxConstraints(),
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
记下constraints: BoxConstraints()
,这是因为不允许在左侧填充。
快乐飘飘!!
【讨论】:
【参考方案8】:使用 ElevatedButton:
ElevatedButton(
onPressed: () ,
child: Icon(
Icons.add,
color: Colors.white,
size: 60.0,
),
style: ElevatedButton.styleFrom(
shape: CircleBorder(), primary: Colors.green),
)
【讨论】:
【参考方案9】:其实有一个例子,如何创建一个类似于 FloatingActionButton 的圆形 IconButton。
Ink(
decoration: const ShapeDecoration(
color: Colors.lightBlue,
shape: CircleBorder(),
),
child: IconButton(
icon: Icon(Icons.home),
onPressed: () ,
),
)
要使用此代码示例创建本地项目,请运行:
flutter create --sample=material.IconButton.2 mysample
【讨论】:
【参考方案10】:我创建了一个具有正确剪裁、高程和边框的版本。随意定制它。
Material(
elevation: 2.0,
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(50),
color: Colors.white,
child: InkWell(
onTap: () => null,
child: Container(
padding: EdgeInsets.all(9.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue, width: 1.4)),
child: Icon(
Icons.menu,
size: 22,
color: Colors.red,
),
),
),
)),
【讨论】:
【参考方案11】:我的贡献:
import 'package:flutter/material.dart';
///
/// Create a circle button with an icon.
///
/// The [icon] argument must not be null.
///
class CircleButton extends StatelessWidget
const CircleButton(
Key key,
@required this.icon,
this.padding = const EdgeInsets.all(8.0),
this.color,
this.onPressed,
this.splashColor,
) : assert(icon != null),
super(key: key);
/// The [Icon] contained ny the circle button.
final Icon icon;
/// Empty space to inscribe inside the circle button. The [icon] is
/// placed inside this padding.
final EdgeInsetsGeometry padding;
/// The color to fill in the background of the circle button.
///
/// The [color] is drawn under the [icon].
final Color color;
/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this callback is null, then the button will be disabled.
final void Function() onPressed;
/// The splash color of the button's [InkWell].
///
/// The ink splash indicates that the button has been touched. It
/// appears on top of the button's child and spreads in an expanding
/// circle beginning where the touch occurred.
///
/// The default splash color is the current theme's splash color,
/// [ThemeData.splashColor].
final Color splashColor;
@override
Widget build(BuildContext context)
final ThemeData theme = Theme.of(context);
return ClipOval(
child: Material(
type: MaterialType.button,
color: color ?? theme.buttonColor,
child: InkWell(
splashColor: splashColor ?? theme.splashColor,
child: Padding(
padding: padding,
child: icon,
),
onTap: onPressed,
),
),
);
【讨论】:
【参考方案12】:我使用这个是因为我喜欢自定义边框半径和大小。
Material( // pause button (round)
borderRadius: BorderRadius.circular(50), // change radius size
color: Colors.blue, //button colour
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 35,height: 35, //customisable size of 'button'
child: Icon(Icons.pause,color: Colors.white,size: 16,),
),
onTap: () , // or use onPressed: ()
),
),
Material( // eye button (customised radius)
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomLeft: Radius.circular(50.0),),
color: Colors.blue,
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 40, height: 40, //customisable size of 'button'
child: Icon(Icons.remove_red_eye,color: Colors.white,size: 16,),),
onTap: () , // or use onPressed: ()
),
),
【讨论】:
【参考方案13】:RaisedButton 已弃用, 现在您可以通过 ElevatedButton 创建它。
ElevatedButton(
onPressed: () ,
child: Icon(Icons.add, color: Colors.white),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(20),
primary: Colors.blue,
onPrimary: Colors.black,
),
)
【讨论】:
【参考方案14】:此代码将帮助您添加没有任何不需要的填充的按钮,
RawMaterialButton(
elevation: 0.0,
child: Icon(Icons.add),
onPressed: (),
constraints: BoxConstraints.tightFor(
width: 56.0,
height: 56.0,
),
shape: CircleBorder(),
fillColor: Color(0xFF4C4F5E),
),
【讨论】:
【参考方案15】:非物质解决方案:
final double floatingButtonSize = 60;
final IconData floatingButtonIcon;
TouchableOpacity(
onTap: ()
/// Do something...
,
activeOpacity: 0.7,
child: Container(
height: floatingButtonSize,
width: floatingButtonSize,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(floatingButtonSize / 2),
color: Theme.of(context).primaryColor,
boxShadow: [
BoxShadow(
blurRadius: 25,
color: Colors.black.withOpacity(0.2),
offset: Offset(0, 10),
)
],
),
child: Icon(
floatingButtonIcon ?? Icons.add,
color: Colors.white,
),
),
)
您可以使用 GestureDetector 代替 TouchableOpacity 库。
【讨论】:
【参考方案16】:2021
如果您需要它平坦(无高度),因为现在不推荐使用 FlatButton。
TextButton(
onPressed: (),
child: Icon(Icons.arrow_back),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black26),
shape: MaterialStateProperty.all(const CircleBorder())),
);
【讨论】:
【参考方案17】:您也可以像这样使用带有图像的 RaisedButton(例如用于社交登录)(需要使用带有 fittebox 的 sizebox 来将图像限制在指定尺寸上):
FittedBox(
fit: BoxFit.scaleDown,
child: SizedBox(
height: 60,
width: 60,
child: RaisedButton(
child: Image.asset(
'assets/images/google_logo.png'),
shape: StadiumBorder(),
color: Colors.white,
onPressed: () ,
),
),
),
【讨论】:
【参考方案18】:ClipOval(
child: MaterialButton(
color: Colors.purple,
padding: EdgeInsets.all(25.0),
onPressed: () ,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
child: Text(
'1',
style: TextStyle(fontSize: 30.0),
),
),
),
【讨论】:
【参考方案19】:试试这张卡
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0), // half of height and width of Image
),
child: Image.asset(
"assets/images/home.png",
width: 50,
height: 50,
),
)
【讨论】:
【参考方案20】:下面的代码将创建一个半径为 25 的圆,并在其中添加白色图标。如果用户还想要点击方法,可以通过将 Container 小部件包装到 GestureDetector() 或 InkWell() 中来简单地实现。
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(50 / 2),
),
child: Center(
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
【讨论】:
【参考方案21】:只使用圆形
MaterialButton(
onPressed: ()
print("Circle button pressed");
,
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.favorite,
size: 20,
),
padding: EdgeInsets.all(16),
//use this class Circleborder() for circle shape.
shape: CircleBorder(),
)
【讨论】:
以上是关于如何在 Flutter 中创建圆形图标按钮?的主要内容,如果未能解决你的问题,请参考以下文章