Flutter ripple effect for png or svg images - flutter

I am looking for someway to add ripple effect on the png or svg images in flutter, without covering the transparent parts in image.
I use this code to add ripple effect over an svg image:
Stack(
children: [
SvgPicture.asset(
R_Image.BACK,
width: 45,
height: 45,
fit: BoxFit.fill,
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
),
),
),
],
)
And the result is as follows:
How to remove transparent parts of svg image from ripple effect?
In android, I use #android:id/mask for this purpose, but how to do that in flutter?

Try to wrap Stack with ClipRRect
ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Stack(
clipBehavior: Clip.none,
children: [
SvgPicture.asset(
R_Image.BACK,
width: 45,
height: 45,
fit: BoxFit.fill,
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
),
),
),
],
),
),

Try this
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,
),
),

Related

adding rows and columns together using flutter

i am trying to add two-row and 4 columns, I added rows but couldn't add columns, I want them to take the same size so I used expanded()
here is a picture
here is what iam lokking for
i am done with rows but couldn't adds columns
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text("homepage"),
),
backgroundColor: Colors.yellowAccent[700],
body: SafeArea(
child: Row(
children: [
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(75), // Image radius
child: Image.network('https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(15),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(75), // Image radius
child: Image.network('https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(15),
),
),
],
),
),
),
);
Use GridView.
GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
children: [
...List.generate(
6,
(index) => ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: Container(
color: Colors.yellowAccent[700],
child: SizedBox.fromSize(
size: Size.fromRadius(75), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
),
)
],
),
Using Row and Column, you need to provide fixed height for each Row.
body: SafeArea(
child: LayoutBuilder(
builder: (context, constraints) => Column(
children: [
SizedBox(
height: constraints.maxHeight * .3,
child: Row(
children: [
...List.generate(
2,
(index) => Expanded(
child: Container(
color: Colors.yellowAccent[700],
padding: EdgeInsets.all(12),
child: ClipRRect(
borderRadius:
BorderRadius.circular(20), // Image border
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
),
)
],
),
),
SizedBox(
height: constraints.maxHeight * .3,
child: Row(
children: [
...List.generate(
2,
(index) => Expanded(
child: Container(
color: Colors.yellowAccent[700],
padding: EdgeInsets.all(12),
child: ClipRRect(
borderRadius:
BorderRadius.circular(20), // Image border
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
),
)
],
),
),
],
),
),
),
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text("homepage"),
),
backgroundColor: Colors.yellowAccent[700],
body: SafeArea(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9' ,
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
],
),
Column(
children: [
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://picsum.photos/250?image=9',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
Expanded(
child: Container(
color: Colors.yellowAccent[700],
child: ClipRRect(
borderRadius: BorderRadius.circular(20), // Image border
child: SizedBox.fromSize(
size: Size.fromRadius(size), // Image radius
child: Image.network(
'https://t3.ftcdn.net/jpg/04/33/08/02/360_F_433080252_BWd42il6gVUmQaXIkASbUrHfKMV3fnqg.jpg',
fit: BoxFit.cover),
),
),
margin: EdgeInsets.all(margin),
),
),
],
),
],
),
),
),
);
}
}
this is the answer
I just added a column inside a row with expanded so it take the same size

Inkwell does not appear in custom button

When the sized box tapped, the ripple effect should happen on top of the widget. But it does not appear. The sized box appears, but ripple effect is not.
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
width: widget.width,
height: widget.height,
child: Material(color: Colors.yellow, child: widget.icon
),
),
SizedBox(
width: widget.width,
height: widget.height,
child: InkWell(
borderRadius: BorderRadius.circular(25),
splashColor: Colors.purple,
onTap: () {}),
),
],
),
]);
EDIT: Wrapped the whole stack with the inkwell but still ripple does not appear.
InkWell(
borderRadius: BorderRadius.circular(25),
splashColor: Colors.purple,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
width: widget.width,
height: widget.height,
child: Material(color: Colors.yellow, child: widget.icon
),
Add InkWell above icon that will give a ripple effect
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 48,
width: 48,
child: Material(
color: Colors.yellow,
child: InkWell(
splashColor: Colors.purple,
onTap: () {},
child: const Icon(Icons.add),
),
),
),
],
),
OR
Material(
color: Colors.yellow,
child: InkWell(
splashColor: Colors.purple,
onTap: () {},
child: Container(
color: Colors.transparent,
height: 80,
width: 80,
child: Icon(Icons.add),
),
),
),
Output:
You must put the sized box as child of inkwell (or even move the complete stack into the inkwell child).
Inkwell is applied to its children.
InkWell(
borderRadius: BorderRadius.circular(25),
splashColor: Colors.purple,
onTap: () {
print('HEY');
},
child: SizedBox(
width: widget.width,
height: widget.height,
),
),
add onTap(){} to the inkWell, even if its not used. I think this fixes it, haven't tried it out tho. Also try wrapping the InkWell with a Material widget.

Flutter create youtube player preview template with image and icon

I have like this code to build youtube player thumbnail with icon:
Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://img.youtube.com/vi/_uOgXpEHNbc/0.jpg"),
fit: BoxFit.fitHeight),
),
),
Container(
color: Colors.black.withOpacity(0.7),
),
Container(
alignment: Alignment.center,
child: Center(
child: Icon(
Icons.smart_display,
color: Colors.red,
size: 100.0,
),
),
),
],
),
This is result of code:
How to make sure that the transparent background of the picture does not affect the central icon? I just need the icon to stay light.
If you want to keep white color of the Play icon in the center then you can try like this
Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://img.youtube.com/vi/_uOgXpEHNbc/0.jpg"),
fit: BoxFit.fill),
),
),
Container(
color: Colors.black.withOpacity(0.7),
),
Container(
alignment: Alignment.center,
child: Center(
child: Container(
height: 50,
width: 60,
color: Colors.white,
),
),
),
Container(
alignment: Alignment.center,
child: Center(
child: Icon(
Icons.smart_display,
color: Colors.red,
size: 100.0,
),
),
),
],
)
You can use Color(0xFF000000).withOpacity(0.7) inside your parent container so it will affect only your parent. You can try here
return Center(
child: Stack(
children: [
Center(
child: Container(
height: 200,
width: 200,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new NetworkImage(
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRVuX218dvGRwSyGhdr1KeTrN6wocBci6xWWQ&usqp=CAU'),
fit: BoxFit.cover,
),
),
child: Container(
color: Color(0xFF000000).withOpacity(0.7),
),
),
),
Center(
child: Container(
child: IconButton(
onPressed: () {},
icon: Image(
image: NetworkImage(
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTRtN8lufTjm-VwUnxm5uAwsW5dCrZqzFFWxg&usqp=CAU"),
),
iconSize: 80,
splashColor: Colors.red,
),
),
),
],
),
);
I use the worst possible images to showcase the example. Don't mind
Output

Card with image on top and text below

Currently I have a card where the image fills the card because I have fit: BoxFit.fill. However I need text below my image. I've tried a few different ways to introduce the text,,Columns etc.. But to no available. The images are of different sizes loaded from the Internet so the fit property works well with the images.
Here is what I have so far. my build method:
#override
Widget build(BuildContext context) {
return Column(children: [
GestureDetector(
onTap: () {
},
child: Container(
width: 335,
height: 174,
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Image.network(
'https://via.placeholder.com/300?text=DITTO',
fit: BoxFit.fill,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
),
),
),
]);
}
But I want to have text under the image like this design:
The process bar and timer are unnecessary.
You must place the image and text in a Column widget, in addition to specifying the image dimensions like this:
Column(children: [
GestureDetector(
onTap: () {},
child: Container(
width: 335,
height: 174,
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Column(
children: [
SizedBox(
width: 335,
height: 110,
child: Image.network(
'https://via.placeholder.com/300?text=DITTO',
fit: BoxFit.fill,
),
),
SizedBox(height: 16,),
Column(children:[
Text('Title'),
Text('Subtitle')
])
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
),
),
),
]);
This worked for me unless you want the text to be overlay, then u gotta use a Stack() then wrap your text in a Positioned() widget:
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Column(
children: [
Image.network(
'https://via.placeholder.com/300?text=DITTO',
fit: BoxFit.fill,
),
Text('Something'),
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
)
Accepted solution giving render overflow error, Above issue, can be solved using the Stack widget. I recommend using MediaQuery instead of hardcoded values.
SizedBox(
width: 335,
height: 174,
child: Stack(
children: <Widget>[
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Column(
children: [
SizedBox(
width: 335,
height: 110,
child: Image.network(
'https://via.placeholder.com/300?text=DITTO',
fit: BoxFit.fill,
),
),
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
),
Positioned(
bottom: 0,
left: 10,
child: SizedBox(
height: 50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Title'),
Text('Subtitle')
],
),
),
)
],
),
),
Output:

How to add onClick on image.asset in flutter?

I am using three images on clicking which will navigate to other page so how should I use onClick on these images? My code is below:
Row(
children: [
Expanded(
child: Column(
children: <Widget>[
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Image.asset('assets/cat.jpg',
width: 110.0, height: 110.0),
)),
Text(
'Tickets',
style:
TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
)
],
),
),
Expanded(
child: Column(
children: <Widget>[
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset('assets/cat.jpg',
width: 110.0, height: 110.0),
)),
Text(
'Buy Tickets',
style:
TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
)
],
),
),
Expanded(
child: Column(
children: <Widget>[
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset('assets/cat.jpg',
width: 110.0, height: 110.0),
)),
Text(
'Prizes',
style:
TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
)
],
),
),
],
),
Expected : Adding an onClick on images
I used GestureDetector but it is throwing error so I need to know what I should use and how.
I read other answers and found that you were having issues with border, try this solution.
GestureDetector(
onTap: () {}, // Image tapped
child: Image.asset(
'assets/cat.jpg',
fit: BoxFit.cover, // Fixes border issues
width: 110.0,
height: 110.0,
),
)
If you want splash effects, then use Ink.image or Ink with decoration.
InkWell(
onTap: () {}, // Image tapped
splashColor: Colors.white10, // Splash color over image
child: Ink.image(
fit: BoxFit.cover, // Fixes border issues
width: 100,
height: 100,
image: AssetImage(
'assets/cat.jpg,
),
),
)
Material(
child: InkWell(
onTap: () {},
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Image.asset('assets/cat.jpg',
width: 110.0, height: 110.0),
),
),
)
You can use InkWell as show by #Murat Aslan.
And you can also use GestureDetector as shown below.
Material(
child: GestureDetector(
onTap: () {},
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Image.asset('assets/cat.jpg',
width: 110.0, height: 110.0),
),
),
),
)
An alternative is to use a FlatButton with an Image as a child:
FlatButton(
onPressed: () {
print('I got clicked');
},
child: Image.asset('images/ball1.png'),
),
To render a material splash during tap on image, use Ink.image
InkWell(
onTap: () {},
child: Ink.image(
image: AssetImage('assets/cat.jpg'),
// fit: BoxFit.cover,
width: 110,
height: 110,
),
)