InkWell没有显示涟漪效果。

243

点击容器会触发 onTap() 处理程序,但不会显示任何墨水飞溅效果。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new InkWell(
          onTap: (){print("tapped");},
          child: new Container(
            width: 100.0,
            height: 100.0,
            color: Colors.orange,
          ),
        ),
      ),
    );
  }
}

我尝试将 InkWell 放在 Container 中,但是没有成功。

28个回答

366
我认为将颜色添加到容器中会掩盖墨水效果。

https://api.flutter.dev/flutter/material/InkWell/InkWell.html

这段代码似乎可以正常工作

  body: new Center(
    child: new Container(
      child: new Material(
        child: new InkWell(
          onTap: (){print("tapped");},
          child: new Container(
            width: 100.0,
            height: 100.0,
          ),
        ),
        color: Colors.transparent,
      ),
      color: Colors.orange,
    ),
  ),

只需点击中间的正方形。

编辑:我找到了错误报告。https://github.com/flutter/flutter/issues/3782

实际上,这是预期的结果,但我们应该更新文档以使其更清晰。

发生的情况是,Material规范指出,飞溅实际上是墨水在材料上。因此,当我们飞溅时,我们实际上是让Material widget执行飞溅操作。如果您在Material上面有其他东西,我们会在其下飞溅,您看不到它。

我想添加一个“MaterialImage”小部件,将其图像概念地打印到Material中,这样飞溅就可以覆盖图像。我们可以使用类似于装饰的MaterialDecoration来处理装饰。或者我们可以让Material本身采用装饰。现在它采用颜色,但我们可以扩展它以采用整个装饰。不清楚具有渐变的材料是否真正符合材料规范,因此我不确定我们是否应该这样做。

在短期内,如果您只需要解决问题,您可以在容器顶部放置一个Material,将材料设置为使用“透明”类型,然后将墨水井放在其中。

- hixie

更新:Hixie在去年合并了新的Ink解决方案。 Ink提供了一种方便的方法来覆盖图像。

  testWidgets('Does the Ink widget render anything', (WidgetTester tester) async {
    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Ink(
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: new InkWell(
              splashColor: Colors.green,
              onTap: () { },
            ),
          ),
        ),
      ),
    );


Material(
  color: Colors.grey[800],
  child: Center(
    child: Ink.image(
      image: AssetImage('cat.jpeg'),
      fit: BoxFit.cover,
      width: 300.0,
      height: 200.0,
      child: InkWell(
        onTap: () { /* ... */ },
        child: Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Text('KITTEN', style: TextStyle(fontWeight: FontWeight.w900, color: Colors.white)),
          ),
        )
      ),
    ),
  ),
)

请注意:我没有测试过新的Ink Widget。我从ink_paint_test.dart和Ink类文档中复制了代码。

https://github.com/Hixie/flutter/blob/1f6531984984f52328e66c0cd500a8d517964564/packages/flutter/test/material/ink_paint_test.dart

https://github.com/flutter/flutter/pull/13900

https://api.flutter.dev/flutter/material/Ink-class.html


4
你可以直接将颜色添加到“Material”上,不需要使用“Container”。 - Herohtar
1
我有点想到了CopsOnRoad发布他的答案。 - user1462442
1
@KoenVanLooveren 试试CopsOnRoad的答案。我没有编辑我的解决方案,因为CopsOnRoad的解决方案非常优雅。 - user1462442
那是我在一些重构后使用的:D 谢谢 - vanlooverenkoen
在我的情况下,它是容器形状。感谢解决方案。 - Mohammad Ersan

223

截图:

输入图像描述


使用包裹在InkWell中的Ink小部件。

InkWell(
  onTap: () {}, // Handle your onTap 
  child: Ink(
    width: 200,
    height: 200,
    color: Colors.blue,
  ),
)

源代码确认第三步骤:https://github.com/flutter/flutter/blob/79b5e5bc8af7d9df3374dfe6141653848d1c03ac/packages/flutter/lib/src/material/ink_well.dart#L504 在每个处理程序中,它们都会检查回调是否可用,否则不会发生任何事情。 - Nightking
@CopsOnRoad,我可以请您在这里提出一个与Flutter相关的问题吗:https://dev59.com/Arnoa4cB1Zd3GeqPUKLY? - Istiaque Ahmed
如果您所说的完整代码是指您提供的示例,那么是的。我已经找到了解决方案> https://dev59.com/AlcO5IYBdhLWcg3wrTcs#58556613 - Chris
1
@Chris 我觉得你可能遇到了一些主题Material的干扰,因为这段代码整天都能正常工作。 - CopsOnRoad

70
  1. The InkWell widget must have a Material widget as an ancestor otherwise it can't show effects. E.g.:

    Material(
      child : InkWell(
        child : .....
    
  2. you have to add onTap method to see the actual effects as like

     Buttons {RaisedButton,FlatButton etc}.
     e.g -> Material(
                 child : InkWell(
                         onTap : (){}
                         child : .....
    

让我们来看一些示例并尝试理解InkWell的实际概念。

  • In Below example Material is parent of InkWell with onTap but it still not working. Please try to understand the concept of it. You should provide some margin to container or other widget to show the effects. Actually below code working fine but we can't see because we did not provide any margin or align so it has no space to show the effects.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: new Container(
              width: 100.0,
              height: 100.0,
              color: Colors.orange,
            ),  
          ),
        ),
      );
    }
    
  • Below example show InkWell effects only to upwards because we provide space {margin}.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: new Container(
              margin: EdgeInsets.only(top: 100.0),
              width: 100.0,
              height: 100.0,
              color: Colors.orange,
            ),
          ),
        ),
      );
    }
    
  • Below exp. show the effects in all the page because center create margin from all the side. Centre align it's child widget from top, left, right and bottom.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: Center(
              child: new Container(
                width: 100.0,
                height: 100.0,
                color: Colors.orange,
              ),
            ),
          ),
        ),
      );
     }
    

3
谢谢,我没有意识到它必须有“Material”小部件作为父级,添加后问题立即解决了! - chungonion

38

InkWell()不会显示涟漪效果,直到您添加

onTap : () {} 

或者任何类似onDoubleTap、onLongPress等回调函数。

当您指定此参数时,它将在InkWell中启动侦听您的轻敲手势。


没错,我做了,并且是真的。检查来源:https://github.com/flutter/flutter/blob/79b5e5bc8af7d9df3374dfe6141653848d1c03ac/packages/flutter/lib/src/material/ink_well.dart#L504 在每个处理程序中,他们都会检查回调是否可用,否则不会发生任何事情。 - Nightking

21

我已经为自己找到了一个解决方案。我认为它可以帮助你:

Material(
      color: Theme.of(context).primaryColor,
      child: InkWell(
        splashColor: Theme.of(context).primaryColorLight,
        child: Container(
          height: 100,
        ),
        onTap: () {},
      ),
    )

Material小部件设置颜色。这是你的小部件的默认颜色。 你可以使用InkwellsplashColor属性来调整涟漪效果的颜色。


1
是的,它有效。如果你恰好使用了一个Container,那么将其替换为Material,并将其设置为InkWell的父级,然后使用颜色/填充等样式来设置你的Material小部件。 - Michał Dobi Dobrzański

14
更好的方法是使用 Ink 小部件,而不是任何其他小部件。
您可以在 Ink 小部件本身中定义颜色,而不是在容器内部定义 color
以下代码将起作用。
Ink(
  color: Colors.orange,
  child: InkWell(
    child: Container(
      width: 100,
      height: 100,
    ),
    onTap: () {},
  ),
)
不要忘记在InkWell中添加onTap: () {},否则它将不显示涟漪效果。

12
如果想让任何小部件产生水波纹效果,只需按以下步骤操作:
1. 使用MaterialInkwell包装小部件。 2. 从Material设置小部件的颜色。 3. 永远不要为想要产生涟漪的小部件设置color
   Material (
   color: const Color(0xcffFF8906),
   child: InkWell(
   ontap:() { },
   child: Container(
   color: Colors.transparent,
   height: 80,
   width: 80,
 )

9
2023年更新: 非常简单,你必须按照以下顺序进行操作:
容器 -> 材料 -> 水波纹效果。
              Container(
                    width: 114,
                    height: 64,
                    decoration: const BoxDecoration(
                      color: AppColorsLight.surfacePrimary,
                      borderRadius: BorderRadius.all(Radius.circular(8)),
                    ),
                    child: Material(
                      color: Colors.transparent,
                      borderRadius: BorderRadius.all(Radius.circular(8)),
                      child: InkWell(
                        splashColor: Colors.white,
                        borderRadius: 
                        BorderRadius.all(Radius.circular(8)),

7

简单易懂的快速解决方案:

这个解决方案可以在任何小部件树中的任何位置使用。只需在InkWell之前添加额外的Material,就像这样:

return Container(
  .......code.......
  ),
  child: Material(
    type: MaterialType.transparency,
    child: InkWell(
      onTap: () {},
      child: Container(
        .......code.......
      ),
    ),
  ),
);

参考资料: https://api.flutter.dev/flutter/material/InkWell-class.html 名为“墨水飞溅不可见!”的章节。


7

InkWellMaterial包裹并使用所需的颜色:

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: Material(
          color: Colors.orange,
          child: new InkWell(
            onTap: (){ print("tapped"); },
            child: new Container(
              width: 100.0,
              height: 100.0,
            ),
          ),
        ),
      ),
    );
  }
}

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