如何在 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.shrinkWrappadding: 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)),
        ),//............
      ),
      ),
    );
  

如果您想获得splashColorhighlightColor 的好处,请使用带有材质类型圆的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 中创建圆形图标按钮?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Qt Designer 中创建圆形按钮

如何在 MFC 中创建圆角矩形按钮

带有文本和图标的圆形按钮

如何在 Flutter for android 中创建这种线性渐变不透明度效果?

为啥我的反应图标不能在按钮中居中?

如何在 Android 中创建圆形 ImageView? [复制]