如何去除Flutter IconButton的大间距?

119

我想要一排IconButtons,都挨在一起,但是实际图标和IconButton边界之间有相当大的填充。我已经将按钮上的填充设置为0。

这是我的组件,非常直观:

class ActionButtons extends StatelessWidget {
  @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.lightBlue,
        margin: const EdgeInsets.all(0.0),
        padding: const EdgeInsets.all(0.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            IconButton(
              icon: new Icon(ScanrIcons.reg),
              alignment: Alignment.center,
              padding: new EdgeInsets.all(0.0),
              onPressed: () {},
            ),
            IconButton(
              icon: new Icon(Icons.volume_up),
              alignment: Alignment.center,
              padding: new EdgeInsets.all(0.0),
              onPressed: () {},
            )
          ],
        ),
      );
    }
}

在此输入图片描述

我想要缩小大部分浅蓝色空间,让我的图标开始位置更靠左且彼此更接近,但我找不到调整IconButton本身大小的方法。

我几乎可以确定这个空间被按钮本身占据了,因为如果我将它们的对齐方式更改为 centerRightcenterLeft,它们会变成这样:

在此输入图片描述

实际上使图标更小也没有帮助,按钮仍然很大:

在此输入图片描述

感谢您的帮助。


你尝试过将实际图标放大吗?看起来图标可能是居中的,但在图标字形中没有填满它的空间。 - Deborah
7
使用GestureDetector( onTap: () {}, child: new Icon(Icons.volume_up) )。 (翻译:Use GestureDetector函数,其中onTap参数是一个空函数,child参数为新的音量图标Icon(Icons.volume_up)。) - Shyju M
12个回答

290
只需将空的BoxConstraints传递给constraints属性,并设置零填充即可。
IconButton(
    padding: EdgeInsets.zero,
    constraints: BoxConstraints(),
)

你需要通过空的约束条件,因为默认情况下,IconButton小部件假设最小尺寸为48px。

2
padding: EdgeInsets.zero,它可以工作,但是会出现约束错误:BoxConstraints()。 - s.j
2
我已将填充归零,但“约束”信息更为重要。谢谢。 - Felipe Sales
我更喜欢使用占用一半空间的padding,但足够宽松,不会太紧。padding: const EdgeInsets.all(4.0), - Bhikkhu Subhuti

97

有两种方法可以解决这个问题。

仍然使用IconButton

将IconButton包裹在一个具有宽度的Container内。

例如:

Container(
  padding: const EdgeInsets.all(0.0),
  width: 30.0, // you can adjust the width as you need
  child: IconButton(
  ),
),

使用GestureDetector代替IconButton

你也可以使用GestureDetector代替IconButton,这是Shyju Madathil推荐的方式。

GestureDetector( onTap: () {}, child: Icon(Icons.volume_up) ) 

2
谢谢!这对我来说非常完美 :) - Anoop Thiruonam
完美无缺 - ABHIMANGAL MS
1
如果你想模仿一个FlatButton,可以使用InkWell。 - AlexK
IconButton 的限制真的很棒。 - Dennis Barzanoff
使用IconButton! - Alan Cesar
1
将 IconButton 包装在 Container 中不会去除填充。 - Ovidiu Uşvat

27

问题不是那里有一个填充。IconButton 是一个遵循材料设计规范的小部件,该规范指出可点击的对象需要每边至少 48 像素。您可以从任何 IDE 进入 IconButton 实现。

您也可以相对简单地获取 icon_button.dart 源代码并创建自己的 IconButton,而不必遵循 材料设计 规范,因为整个文件只是由其他小部件组成,仅具有 200 行大多数是注释。


15
IconButton包装在容器中并不能起作用,而是要使用ClipRRect,并添加一个带有Inkwell的材料小部件,只需确保为ClipRRect小部件提供足够的边框半径即可。
ClipRRect(
    borderRadius: BorderRadius.circular(50),
    child : Material(
        child : InkWell(
            child : Padding(
                padding : const EdgeInsets.all(5),
                child : Icon(
                    Icons.favorite_border,
                    ),
                ),
            onTap : () {},
            ),
        ),
    )

不错的解决方案,让我意识到了ClipRRect小部件及其相关组件。 :) - Enrichman

5

如果您想要去除IconButton周围的填充,您可以使用图标并将其包裹在GestureDetector或InkWell中。

GestureDetector(
   ontap:(){}
   child:Icon(...)
);

如果您想要在单击时获得与IconButton提供的涟漪/墨水飞溅效果相同的效果,请将其包装在InkWell中。
InkWell(
   splashColor: Colors.red,
   child:Icon(...)
   ontap:(){}
)

虽然第二种方法中施加在图标上的墨水不会像IconButton那样准确,你可能需要对其进行一些自定义实现。


5
2023解决方案:
IconButton(
  onPressed: () {},
  iconSize: 40.0, // desired size
  padding: EdgeInsets.zero,
  constraints: const BoxConstraints(), // override default min size of 48px
  style: const ButtonStyle(
    tapTargetSize: MaterialTapTargetSize.shrinkWrap, // the '2023' part
  ),
  icon: const Icon(Symbols.arrow_right),
),

3
这是一个解决方案,使用InkWell代替IconButton来消除任何额外的内边距:
Widget backButtonContainer = InkWell(
    child: Container(
      child: const Icon(
        Icons.arrow_upward,
        color: Colors.white,
        size: 35.0,
      ),
    ),
    onTap: () {
      Navigator.of(_context).pop();
    });

1
我遇到了类似的问题,试图在用户触摸屏幕的位置呈现一个图标。不幸的是,Icon 类会用 SizedBox 包装你选择的图标。
通过阅读一些 Icon 类源代码,可以发现每个 Icon 可以被视为文本:
Widget iconWidget = RichText(
      overflow: TextOverflow.visible,
      textDirection: textDirection,
      text: TextSpan(
        text: String.fromCharCode(icon.codePoint),
        style: TextStyle(
          inherit: false,
          color: iconColor,
          fontSize: iconSize,
          fontFamily: icon.fontFamily,
          package: icon.fontPackage,
        ),
      ),
    );

因此,例如,如果我想要渲染Icons.details以指示我的用户刚刚指向的位置,而不带任何边距,我可以这样做:
Widget _pointer = Text(
      String.fromCharCode(Icons.details.codePoint),
      style: TextStyle(
        fontFamily: Icons.details.fontFamily,
        package: Icons.details.fontPackage,
        fontSize: 24.0,
        color: Colors.black
      ),
    );

Dart/Flutter的源代码非常易于理解,我强烈建议您深入了解一下!

0

你可以使用ListTile,它会为文本和图标之间提供默认的间距,以符合你的需求

ListTile(
         leading: Icon(Icons.add), //Here Is The Icon You Want To Use
         title: Text('GFG title',textScaleFactor: 1.5,), //Here Is The Text Also
         trailing: Icon(Icons.done),
         ),

0
更好的解决方案是使用Transform.scale,像这样:
 Transform.scale(
   scale: 0.5, // set your value here
   child: IconButton(icon: Icon(Icons.smartphone), onPressed: () {}),
 )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接