为什么 Flutter IconButton 动画显示在行下

Why Flutter IconButton Animation Shows Under the Row

在我的应用程序中,我设置了一个 IconButton 以在具有彩色背景的行上呈现。不幸的是,按下按钮时的涟漪动画呈现在行下(如截屏视频所示)。如何在 Row 上显示涟漪?

class Card extends StatelessWidget {
final Issue issue;
Color _bgColor;

Card({this.issue}) {
  _bgColor = colorSwatch[issue.hashCode % colorSwatch.length];
}

@override
Widget build(BuildContext context) {
  return Container(
    margin: EdgeInsets.only(top: 12, left: 18, right: 18),
    padding: EdgeInsets.only(top: 8, bottom: 8),
    decoration: new BoxDecoration(
      color: _bgColor,
      border: new Border.all(color: _bgColor),
      borderRadius: BorderRadius.all(
          Radius.circular(10.0) 
          ),
    ),
    child: Row(children: [
      IconButton(
        padding: EdgeInsets.only(right: 16),
        icon: Icon(Icons.play_arrow, color: Colors.white, size: 48),
        tooltip: 'Start ${issue.issueName}',
        onPressed: () {},
      ),
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              padding: const EdgeInsets.only(bottom: 8),
              child: Text(
                issue.title,
                style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
                softWrap: true,
              ),
            ),
            Text(
              issue.issueName,
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
    ]));
  }
}

波纹是 Material 效果的一部分。用 Material 包裹你的 IconButton:

Material(
  color: _bgColor,
  child: IconButton(
    padding: EdgeInsets.only(right: 16),
    icon: Icon(Icons.play_arrow, color: Colors.white, size: 48),
    tooltip: 'Start ${issue.issueName}',
    onPressed: () {},
  ),
),

更新

为了更具体地实现您的目标,您可以将 Container 替换为 Material

return Material(
  color: _bgColor,
  borderRadius: BorderRadius.all(Radius.circular(10.0)),
  child: Container(
     margin: EdgeInsets.only(top: 12, left: 18, right: 18),
     padding: EdgeInsets.only(top: 8, bottom: 8),
     backgroundBlendMode: BlendMode.multiply,
     child: Row(
     ...
  ),
);

您可以将 Row 包裹在 InkWell 中,这会给您带来触感涟漪。

我删除了容器的背景颜色,在显示波纹时出现问题,并将文本颜色更改为黑色。

    @override
  Widget build(BuildContext context) {
    return Container(
        height: 100,
        margin: EdgeInsets.only(top: 12, left: 18, right: 18),
        padding: EdgeInsets.only(top: 8, bottom: 8),
        decoration: new BoxDecoration(
          color: Colors.transparent,
          border: new Border.all(color: Colors.orange),
          borderRadius: BorderRadius.all(Radius.circular(10.0)),
        ),
        child: InkWell(
          // added here
          onTap: () {},
          child: Row(children: [
            IconButton(
              padding: EdgeInsets.only(right: 16),
              icon: Icon(Icons.play_arrow, color: Colors.black, size: 48),
              tooltip: 'Start issue',
              onPressed: () {},
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Container(
                    padding: const EdgeInsets.only(bottom: 8),
                    child: Text(
                      'issue.title',
                      style: TextStyle(
                        color: Colors.black,
                        fontWeight: FontWeight.bold,
                      ),
                      softWrap: true,
                    ),
                  ),
                  Text(
                    'issue.issueName',
                    style: TextStyle(
                      color: Colors.black,
                    ),
                  ),
                ],
              ),
            ),
          ]),
        ));
  }

参考文献

Add ripples

Ripple 始终位于 material 小部件之上。因此,如果 material 小部件顶部有任何内容,您会在小部件下方看到涟漪。

只需用 Material 小部件包装 IconButton,并将 material 设置为使用 "transparency" 类型,它应该可以工作。

您可以使用以下通用小部件为您的小部件添加涟漪。

class AddRipple extends StatelessWidget {
  final Widget child;
  final Function onTap;

  AddRipple({@required this.child, @required this.onTap});

 @override
 Widget build(BuildContext context) {
 return Stack(
     children: <Widget>[
     child,
      Positioned.fill(
        child: new Material(
            color: Colors.transparent,
            child: new InkWell(
              onTap: onTap,
            ))),
      ],
    );
  }
}

您还可以在 InkWell 小部件的构造函数和用户 'splashColor' 属性 中输入颜色来设置启动颜色。

这看起来像是 Flutter Framework 中的一个错误。 这仅发生在 IconButton 上,FlatButton 上没有问题。

可能的解决方法是将 BlendMode 设置为相乘 BlendMode.multiply.
试试这个:

Container(
          decoration: BoxDecoration(
              color: Colors.greenAccent[400],
              backgroundBlendMode: BlendMode.multiply),
          child: ListTile(
            leading: IconButton(icon: Icon(Icons.play_arrow), onPressed: () {}),
            title: Text("issue title"),
            subtitle: Text("description"),
          ),
        ),

更新
github

上的问题