InkWell 未显示涟漪效应
InkWell not showing ripple effect
点击容器会触发 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
中,但没有成功。
我认为给容器上色是遮盖墨水的效果
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
This is actually as expected, though we should update the docs to make it clearer.
What's going on is that the Material spec says that the splashes are actually ink on the Material. So when we splash, what we do is we literally have the Material widget do the splash. If you have something on top of the Material, we splash under it, and you can't see it.
I have wanted to add a "MaterialImage" widget that conceptually prints its image into the Material as well so that then the splashes would be over the image. We could have a MaterialDecoration which does something similar for a Decoration. Or we could have Material itself take a decoration. Right now it takes a color, but we could extend that to taking a whole decoration. It's not clear whether it's really material-spec-compatible to have a material with a gradient, though, so I'm not sure whether we should do that.
In the short run, if you just need a workaround, you can put a Material on top of the container, with the material set to use the "transparency" type, and then put the ink well inside that.
--嘻嘻
更新: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 class 文档
中的代码
在您添加
之前,InkWell() 永远不会显示涟漪效果
onTap : () {}
或任何回调,如 onDoubleTap、onLongPress 等
InkWell 中的参数,因为它仅在您指定此参数时才开始聆听您的敲击声。
我 运行 遇到了同样的问题,试图在 ListView 中创建 InkWell 的交替颜色。在这种特殊情况下,有一个简单的解决方案:将替代项包装在一个主要使用 t运行sparenttint/brightness 更改的容器中——InkWell 触摸动画在其下方仍然可见。不需要 Material。请注意,在尝试使用 Materal 解决此问题时还有其他问题——例如,它将覆盖您使用默认设置的 DefaultTextStyle(它安装了 AnimatedDefaultTextStyle),这是一个巨大的痛苦。
截图:
使用 Ink
小部件包裹在 InkWell
.
中
InkWell(
onTap: () {}, // Handle your onTap
child: Ink(
width: 200,
height: 200,
color: Colors.blue,
),
)
更好的方法是使用 Ink
小部件而不是任何其他小部件。
您可以在 Ink
小部件本身中定义它,而不是在容器内定义 color
。
下面的代码可以工作。
Ink(
color: Colors.orange,
child: InkWell(
child: Container(
width: 100,
height: 100,
),
onTap: () {},
),
)
Do not forget to add a onTap: () {}
in the InkWell
else it will
not show the ripple effect too.
InkWell 小部件必须有一个 Material 小部件作为祖先,否则它无法显示效果。例如:
Material(
child : InkWell(
child : .....
需要添加onTap
方法才能看到实际效果,如
Buttons {RaisedButton,FlatButton etc}.
e.g -> Material(
child : InkWell(
onTap : (){}
child : .....
让我们来看看要点,看看下面的一些例子,试着理解
InkWell 的实际概念。
在下面的示例中,Material 是带有 onTap 的 InkWell 的父级,但它仍然无法正常工作。请尝试理解它的概念。您应该为容器或其他小部件提供一些边距以显示效果。实际上下面的代码工作正常但我们看不到,因为我们没有提供任何边距或对齐所以它没有 space 来显示效果。
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,
),
),
),
);
}
下面的例子只显示向上的 InkWell 效果,因为我们提供了 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,
),
),
),
);
}
低于经验值。在所有页面中显示效果,因为中心从所有侧面创建边距。从上、左、右和下居中对齐它的子窗口小部件。
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,
),
),
),
),
);
}
这是我发现并一直使用的最好方法。你可以试试。
- 用
InkWell
包裹你的Widget
- 用
Material
包裹 InkWell
无论如何设置不透明度为 0%。例如:color: Colors.white.withOpacity(0.0),
Material(
color: Colors.white.withOpacity(0.0),
child: InkWell(
child: Container(width: 100, height: 100),
onTap: (){print("Wow! Ripple");},
),
)
我遇到了类似的问题,将 Inkwell 添加到现有的复杂 Widget 中,其中 Container 包装了带有颜色的 BoxDecoration。通过添加 Material 和 Inkwell 的方式表明 Inkwell 仍然被 BoxDecoration 遮挡,所以我只是让 BoxDecoration 的颜色稍微不透明,这样可以看到 Inkwell
圆形小部件的解决方法,如下:
Material(
color: Colors.transparent,
child: Container(
alignment: Alignment.center,
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
enableFeedback: true,
iconSize: 40,
icon: Icon(
Icons.skip_previous,
color: Colors.white,
size: 40,
),
onPressed: () {}),
IconButton(
iconSize: 100,
enableFeedback: true,
splashColor: Colors.grey,
icon: Icon(Icons.play_circle_filled, color: Colors.white, size: 100),
padding: EdgeInsets.all(0),
onPressed: () {},
),
IconButton(
enableFeedback: true,
iconSize: 40,
icon: Icon(
Icons.skip_next,
color: Colors.white,
size: 40,
),
onPressed: () {}),
],
),
),
)
我找到了适合我的解决方案。我认为它可以帮助你:
Material(
color: Theme.of(context).primaryColor,
child: InkWell(
splashColor: Theme.of(context).primaryColorLight,
child: Container(
height: 100,
),
onTap: () {},
),
)
Color
已提供给 Material 小部件。它是您的小部件的默认颜色。
您可以使用 Inkwell splashColor
属性 调整波纹效果的颜色。
添加 onTap:(){}
侦听器后,连锁反应应该可以正常工作。如果您在 InkWell()
小部件中使用 BoxShadow()
则它不起作用。
这对我有用:
Material(
color: Colors.white.withOpacity(0.0),
child: InkWell(
splashColor: Colors.orange,
child: Text('Hello'), // actually here it's a Container wrapping an image
onTap: () {
print('Click');
},
));
在这里尝试了很多答案后,它是以下组合:
- 设置
splashColor
- 在
Material(color: Colors.white.withOpacity(0.0), ..)
中包装 InkWell
感谢这里的回答让这两点成为可能
对我来说这是另一个问题。当我将 onTap 函数作为我的小部件的参数定义如下时,InkWell 没有显示涟漪效应。
Function(Result) onTapItem;
...
onTap: onTapItem(result),
我不知道有什么区别,但下一个代码运行良好。
onTap: (){ onTapItem(result); },
如果您想在任何小部件上获得 Ripple Effect,只需:
1- 使用 Material 和 Inkwell.
包装小部件
2- 从 Material.
中为小部件设置颜色
3- 从不 将 颜色 设置为您希望其波纹的小部件。
Material (
color: const Color(0xcffFF8906),
child: InkWell(
ontap:() { },
child: Container(
color: Colors.transparent,
height: 80,
width: 80,
)
设置 InkWell 容器的颜色
放置在 Material
小部件内的任何子小部件都采用 Material
小部件中设置的颜色。所以,我们应该从 Material 的颜色 属性 本身设置颜色。您不能从任何父 Container
小部件设置它。
使用 Material
父控件创建 InkWell
时要注意的另一个重要事项是,您应该从 Material 的 属性 本身设置颜色。您不能从 Container
.
中设置它
因此,我们修复 InkWell
效果和容器颜色的代码如下所示:
Container(
margin: EdgeInsets.all(12),
height: 50.0,
width: 100.0,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 4, offset: Offset(0, 2))
]),
child: Material(
color: Colors.blue,
child: InkWell(
child: Center(
child: Text("My Chip",
style: Theme.of(context).textTheme.body1)),
onTap: () {},
),
),
)
我能够通过使用 Stack 来解决我的情况。
Stack(
children: [
MyCustomWidget(), // <--- Put this on bottom
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {},
child: Ink(
width: 100,
height: 100,
),
),
),
],
),
此页面上的其他答案对我不起作用的原因是我的自定义小部件隐藏了墨迹效果并且我没有纯图像(所以我无法使用 Ink.image ).
编辑:
如果您 .
,您仍然可以使用 Ink.image
向 Material 添加透明颜色在我的案例中有效:
child: new Material(
color: Colors.transparent
child: new InkWell(
onTap: (){},
child: new Container(
width: 100.0,
height: 100.0,
color: Colors.amber,
),
),
),
现在使用 MaterialButton,在较新的版本中 flutter
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: MaterialButton(
child: Text(
labelText,
style: TextStyle(fontSize: 22),
),
onPressed: () {},
color: backgroundColor,
height: 45,
minWidth: double.infinity,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(16),
),
),
),
);
}
child: Material(
color: Colors.transparent
child: InkWell(
onTap: (){ print("this Ripple!";},
splashColor: Colors.greenAccent,
child: Container(
height:100.0,
color: Colors.white,
),
),
),
在InkWell
之前添加Material
,并将color
设置为Colors.transparent
。
要处理涟漪效应,您应该使用以下规则:
onTap
不应该是 null
(或空的)。
- InkWell 必须在任何 Material 小部件中
- Create a widget that supports tap.
- Wrap it in an InkWell widget to manage tap callbacks and ripple
animations.
中提到了 2 分
示例:
InkWell(
child: TextButton(
onPressed: () {},
child: Text('Tapped'),
),
),
),
简单易懂的快速解决方案:
此解决方案适用于小部件树的任何位置。
只需在 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
名为“墨水飞溅不可见!”的部分
点击容器会触发 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
中,但没有成功。
我认为给容器上色是遮盖墨水的效果
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
This is actually as expected, though we should update the docs to make it clearer.
What's going on is that the Material spec says that the splashes are actually ink on the Material. So when we splash, what we do is we literally have the Material widget do the splash. If you have something on top of the Material, we splash under it, and you can't see it.
I have wanted to add a "MaterialImage" widget that conceptually prints its image into the Material as well so that then the splashes would be over the image. We could have a MaterialDecoration which does something similar for a Decoration. Or we could have Material itself take a decoration. Right now it takes a color, but we could extend that to taking a whole decoration. It's not clear whether it's really material-spec-compatible to have a material with a gradient, though, so I'm not sure whether we should do that.
In the short run, if you just need a workaround, you can put a Material on top of the container, with the material set to use the "transparency" type, and then put the ink well inside that.
--嘻嘻
更新: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 class 文档
中的代码在您添加
之前,InkWell() 永远不会显示涟漪效果onTap : () {}
或任何回调,如 onDoubleTap、onLongPress 等
InkWell 中的参数,因为它仅在您指定此参数时才开始聆听您的敲击声。
我 运行 遇到了同样的问题,试图在 ListView 中创建 InkWell 的交替颜色。在这种特殊情况下,有一个简单的解决方案:将替代项包装在一个主要使用 t运行sparenttint/brightness 更改的容器中——InkWell 触摸动画在其下方仍然可见。不需要 Material。请注意,在尝试使用 Materal 解决此问题时还有其他问题——例如,它将覆盖您使用默认设置的 DefaultTextStyle(它安装了 AnimatedDefaultTextStyle),这是一个巨大的痛苦。
截图:
使用 Ink
小部件包裹在 InkWell
.
InkWell(
onTap: () {}, // Handle your onTap
child: Ink(
width: 200,
height: 200,
color: Colors.blue,
),
)
更好的方法是使用 Ink
小部件而不是任何其他小部件。
您可以在 Ink
小部件本身中定义它,而不是在容器内定义 color
。
下面的代码可以工作。
Ink(
color: Colors.orange,
child: InkWell(
child: Container(
width: 100,
height: 100,
),
onTap: () {},
),
)
Do not forget to add a
onTap: () {}
in theInkWell
else it will not show the ripple effect too.
InkWell 小部件必须有一个 Material 小部件作为祖先,否则它无法显示效果。例如:
Material( child : InkWell( child : .....
需要添加
onTap
方法才能看到实际效果,如Buttons {RaisedButton,FlatButton etc}. e.g -> Material( child : InkWell( onTap : (){} child : .....
让我们来看看要点,看看下面的一些例子,试着理解 InkWell 的实际概念。
在下面的示例中,Material 是带有 onTap 的 InkWell 的父级,但它仍然无法正常工作。请尝试理解它的概念。您应该为容器或其他小部件提供一些边距以显示效果。实际上下面的代码工作正常但我们看不到,因为我们没有提供任何边距或对齐所以它没有 space 来显示效果。
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, ), ), ), ); }
下面的例子只显示向上的 InkWell 效果,因为我们提供了 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, ), ), ), ); }
低于经验值。在所有页面中显示效果,因为中心从所有侧面创建边距。从上、左、右和下居中对齐它的子窗口小部件。
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, ), ), ), ), ); }
这是我发现并一直使用的最好方法。你可以试试。
- 用
InkWell
包裹你的 - 用
Material
包裹 无论如何设置不透明度为 0%。例如:
color: Colors.white.withOpacity(0.0),
Material( color: Colors.white.withOpacity(0.0), child: InkWell( child: Container(width: 100, height: 100), onTap: (){print("Wow! Ripple");}, ), )
Widget
InkWell
我遇到了类似的问题,将 Inkwell 添加到现有的复杂 Widget 中,其中 Container 包装了带有颜色的 BoxDecoration。通过添加 Material 和 Inkwell 的方式表明 Inkwell 仍然被 BoxDecoration 遮挡,所以我只是让 BoxDecoration 的颜色稍微不透明,这样可以看到 Inkwell
圆形小部件的解决方法,如下:
Material(
color: Colors.transparent,
child: Container(
alignment: Alignment.center,
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
enableFeedback: true,
iconSize: 40,
icon: Icon(
Icons.skip_previous,
color: Colors.white,
size: 40,
),
onPressed: () {}),
IconButton(
iconSize: 100,
enableFeedback: true,
splashColor: Colors.grey,
icon: Icon(Icons.play_circle_filled, color: Colors.white, size: 100),
padding: EdgeInsets.all(0),
onPressed: () {},
),
IconButton(
enableFeedback: true,
iconSize: 40,
icon: Icon(
Icons.skip_next,
color: Colors.white,
size: 40,
),
onPressed: () {}),
],
),
),
)
我找到了适合我的解决方案。我认为它可以帮助你:
Material(
color: Theme.of(context).primaryColor,
child: InkWell(
splashColor: Theme.of(context).primaryColorLight,
child: Container(
height: 100,
),
onTap: () {},
),
)
Color
已提供给 Material 小部件。它是您的小部件的默认颜色。
您可以使用 Inkwell splashColor
属性 调整波纹效果的颜色。
添加 onTap:(){}
侦听器后,连锁反应应该可以正常工作。如果您在 InkWell()
小部件中使用 BoxShadow()
则它不起作用。
这对我有用:
Material(
color: Colors.white.withOpacity(0.0),
child: InkWell(
splashColor: Colors.orange,
child: Text('Hello'), // actually here it's a Container wrapping an image
onTap: () {
print('Click');
},
));
在这里尝试了很多答案后,它是以下组合:
- 设置
splashColor
- 在
Material(color: Colors.white.withOpacity(0.0), ..)
中包装
InkWell
感谢这里的回答让这两点成为可能
对我来说这是另一个问题。当我将 onTap 函数作为我的小部件的参数定义如下时,InkWell 没有显示涟漪效应。
Function(Result) onTapItem;
...
onTap: onTapItem(result),
我不知道有什么区别,但下一个代码运行良好。
onTap: (){ onTapItem(result); },
如果您想在任何小部件上获得 Ripple Effect,只需:
1- 使用 Material 和 Inkwell.
包装小部件2- 从 Material.
中为小部件设置颜色3- 从不 将 颜色 设置为您希望其波纹的小部件。
Material (
color: const Color(0xcffFF8906),
child: InkWell(
ontap:() { },
child: Container(
color: Colors.transparent,
height: 80,
width: 80,
)
设置 InkWell 容器的颜色
放置在 Material
小部件内的任何子小部件都采用 Material
小部件中设置的颜色。所以,我们应该从 Material 的颜色 属性 本身设置颜色。您不能从任何父 Container
小部件设置它。
使用 Material
父控件创建 InkWell
时要注意的另一个重要事项是,您应该从 Material 的 属性 本身设置颜色。您不能从 Container
.
因此,我们修复 InkWell
效果和容器颜色的代码如下所示:
Container(
margin: EdgeInsets.all(12),
height: 50.0,
width: 100.0,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 4, offset: Offset(0, 2))
]),
child: Material(
color: Colors.blue,
child: InkWell(
child: Center(
child: Text("My Chip",
style: Theme.of(context).textTheme.body1)),
onTap: () {},
),
),
)
我能够通过使用 Stack 来解决我的情况。
Stack(
children: [
MyCustomWidget(), // <--- Put this on bottom
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {},
child: Ink(
width: 100,
height: 100,
),
),
),
],
),
此页面上的其他答案对我不起作用的原因是我的自定义小部件隐藏了墨迹效果并且我没有纯图像(所以我无法使用 Ink.image ).
编辑:
如果您
Ink.image
向 Material 添加透明颜色在我的案例中有效:
child: new Material(
color: Colors.transparent
child: new InkWell(
onTap: (){},
child: new Container(
width: 100.0,
height: 100.0,
color: Colors.amber,
),
),
),
现在使用 MaterialButton,在较新的版本中 flutter
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: MaterialButton(
child: Text(
labelText,
style: TextStyle(fontSize: 22),
),
onPressed: () {},
color: backgroundColor,
height: 45,
minWidth: double.infinity,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(16),
),
),
),
);
}
child: Material(
color: Colors.transparent
child: InkWell(
onTap: (){ print("this Ripple!";},
splashColor: Colors.greenAccent,
child: Container(
height:100.0,
color: Colors.white,
),
),
),
在InkWell
之前添加Material
,并将color
设置为Colors.transparent
。
要处理涟漪效应,您应该使用以下规则:
onTap
不应该是null
(或空的)。- InkWell 必须在任何 Material 小部件中
中提到了 2 分
- Create a widget that supports tap.
- Wrap it in an InkWell widget to manage tap callbacks and ripple animations.
示例:
InkWell(
child: TextButton(
onPressed: () {},
child: Text('Tapped'),
),
),
),
简单易懂的快速解决方案:
此解决方案适用于小部件树的任何位置。 只需在 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 名为“墨水飞溅不可见!”的部分