Flutter中GridTile中图像上方的InkWell水波纹效果

66

我正在尝试使用InkWellGridTile中的图像上方获得涟漪效果,当用户点击瓷砖时。

我相信图像本身会遮挡涟漪,因为当我移除图像时,我可以看到涟漪。

下面是单个GridTile的代码。

return new InkWell(
  onTap: () => debugPrint(s.displayName),
  highlightColor: Colors.pinkAccent,
  splashColor: Colors.greenAccent,
  child: new GridTile(
    footer: new GridTileBar(
      title: new Text(s.displayName),
      subtitle: new Text(s.gameName),
      backgroundColor: Colors.black45,
      trailing: new Icon(
        Icons.launch,
        color: Colors.white,
      ),
    ),
    child: new Image.network( //this is obscuring the InkWell ripple
      s.imageSrc,
      fit: BoxFit.cover,
    ),
   ),
 );
我尝试将InkWell移动到层次结构的不同级别,使用Container中的DecorationImage,但似乎都无法显示涟漪效果。
我该如何使涟漪效果显示在瓷砖/图片的上方?

这真的很奇怪,尽管层次结构不同,但Image比InkWell具有更高的高度。 - Ihor Klimov
6个回答

84

通过使用 Stack 并将 InkWell 包装在 Material 小部件中,我成功让图像上出现了涟漪效果。

return new Stack(children: <Widget>[
        new Positioned.fill(
          bottom: 0.0,
          child: new GridTile(
              footer: new GridTileBar(
                title: new Text(s.displayName),
                subtitle: new Text(s.gameName),
                backgroundColor: Colors.black45,
                trailing: new Icon(
                  Icons.launch,
                  color: Colors.white,
                ),
              ),
              child: new Image.network(s.imageSrc, fit: BoxFit.cover)),
        ),
        new Positioned.fill(
            child: new Material(
                color: Colors.transparent,
                child: new InkWell(
                  splashColor: Colors.lightGreenAccent,
                  onTap: () => _launchStream(s.displayName),
                ))),
      ]);

我有一个透明的墨水瓶,在材质内部使用它也会使背景图像变得不透明。 - Mangaldeep Pannu

72

我认为这将是展示图片上涟漪效果的更好方式。

Ink.image(
    image: AssetImage('sample.jpg'),
    fit: BoxFit.cover,
    child: InkWell(
        onTap: () {},
    ),
),

问题的根本原因在于Flutter以降序渲染视图。当我们将图片作为InkWell的子项时,效果被该图片覆盖。

在此处查找更多参考:

Ink小部件

在Flutter中创建带有涟漪效果的圆形图标


3
该解决方案不允许为图像创建圆角。 - kashlo
1
我考虑过这种方法,但我认为对于更复杂的小部件(例如包含文本和图像的容器),无法使其正常工作。 - Ben Butterworth

69

使用 Stack,我们可以将MaterialInkWell放在图片上面。为了拉伸 Material 我们将使用Positioned.fill组件。

Stack(
  children: <Widget>[
    Image( ... ),
    Positioned.fill(
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          onTap: () { ... },
        ),
      ),
    ),
  ],
);

DartPad | Gist

屏幕截图

此屏幕截图来自给定的DartPad链接。

InkWell ripple over the Image


2
尝试了这里的所有建议。对我来说,这一个是最好的,因为我有AspectRatioFadeInImage用于主层。 - Schultz9999
@TheMisir 这是唯一一个与缓存网络图像一起工作的解决方案,我很喜欢它! - Rajesh
非常好,与卡片内的FadeInImage一起使用效果很棒。 - Germa Vinsmoke
1
InkWellsplashColor设置为Colors.grey.withOpacity(0.5)可以获得更好的涟漪动画。 - omega_mi

16
我们已经创建了这个简单的小部件,可以在任何给定子元素的顶部绘制墨水反应。
class InkWrapper extends StatelessWidget {
  final Color splashColor;
  final Widget child;
  final VoidCallback onTap;

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

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

子小部件的格式丢失。使用 Positioned.fill(child: child) 进行修复。 - OM KALE

13

截图:

在此输入图片描述

SizedBox(
  height: 200,
  child: Ink(
    decoration: BoxDecoration(
      image: DecorationImage(
        image: ExactAssetImage("chocolate_image"),
        fit: BoxFit.cover,
      ),
    ),
    child: InkWell(
      onTap: () {},
      splashColor: Colors.brown.withOpacity(0.5),
    ),
  ),
)

非常好的方法。甚至可以与AspectRatio一起使用。如果我能使用FadeInImage,那就更好了。 - Schultz9999

-4

InkWell包裹在Material小部件中

Material(   
  child : InkWell(          
      child : YourWidget     
  )      
)  

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