InkWell ripple over top of image in GridTile in Flutter
FlutterFlutter Problem Overview
I'm trying to use InkWell
to get a ripple effect on top of an image inside of a GridTile
when the user taps on the tile.
I believe the image itself is obscuring the ripple because when I remove the image, I see the ripple.
Below is the code for a single 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,
),
),
);
I've tried moving the InkWell to different levels of the hierarchy, using DecorationImage
inside a Container
, but none of these seem to work to reveal the ripple.
How can I get the ripple to appear on top of the tile/image?
Flutter Solutions
Solution 1 - Flutter
I was able to get a ripple to appear over the image by using a Stack and wrapping the InkWell in a Material widget.
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),
))),
]);
Solution 2 - Flutter
I think this would be a better way to show ripple effect over image.
Ink.image(
image: AssetImage('sample.jpg'),
fit: BoxFit.cover,
child: InkWell(
onTap: () {},
),
),
The root cause is that Flutter renders views in descending order. when we put our image as the child of InkWell, the effect is covered by that image.
Find out more references here:
Solution 3 - Flutter
Using Stack
we can bring Material
and InkWell
over the image. To stretch Material we are going to use Positioned.fill
widget.
Stack(
children: <Widget>[
Image( ... ),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () { ... },
),
),
),
],
);
Screenshot
This screenshot is taken from given dartpad link.
Solution 4 - Flutter
We have created this simple Widget to paint an ink reaction on top of any given child.
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,
),
),
),
],
);
}
}
Solution 5 - Flutter
Screenshot:
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),
),
),
)
Solution 6 - Flutter
Here is how I solved it :
Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15)),
child: Stack(
children: [
Center(child: Image.asset("images/1.png")),
Container(
height: 200,
width: 200,
child: FlatButton(
onPressed: () {
},
child: Text(""),
),
),
],
),
),
Solution 7 - Flutter
wrap InkWell
inside Material
Widget
Material(
child : InkWell(
child : YourWidget
)
)