【问题标题】:How to create a circle icon button in Flutter?如何在 Flutter 中创建圆形图标按钮?
【发布时间】:2018-09-23 08:41:38
【问题描述】:

如何创建类似于FloatingActionButton 的内容?

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案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(),
                                    )
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 2019-12-24
                                      • 2021-03-04
                                      • 2015-07-27
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2020-03-03
                                      • 1970-01-01
                                      • 2018-10-04
                                      相关资源
                                      最近更新 更多