Ripple does not cover text - flutter

I figured I can draw ripple over an image by enclosing the image in Ink(decoration: BoxDecoration(image: ...)), but how can I do the same for Text?
This is supposed to be a card with an image on top and a title and some other information at the bottom:
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final post = _postModel.post;
return Material(
color: theme.colorScheme.background,
child: InkWell(
onTap: () {},
splashColor: Colors.red,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (post.imageUri != null)
// This image IS covered by the ripple (what I need)
AspectRatio(
aspectRatio: 5 / 3,
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
image: DecorationImage(
image: NetworkImage('https://picsum.photos/700'),
fit: BoxFit.cover,
),
),
),
),
// This must be underneath the ripple, but isn't.
Text(post.title, style: theme.textTheme.headline5),
Container(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 5),
color: Colors.transparent,
height: 60,
child: Row(
children: <Widget>[
// This is also covered by the ripple
Ink(
height: 35,
width: 35,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage('https://picsum.photos/100'),
),
),
),
SizedBox(width: 5),
// This must be underneath the ripple but isn't
Ink(
// decoration: Decoration,
child: Text(
post.author,
style: theme.textTheme.caption,
),
),
Spacer(),
],
),
),
],
),
),
),
);
}
When I press, the ripple covers both images as expected, however, I can't figure out how to make the ripple cover the text widgets as well. I tried wrapping the text in an Ink widget (the last one), but it doesn't work - the text is still displayed over the ripple.
Unpressed:
Pressed (the text is visible):

Related

How to place all row items in one line equally? Flutter

I want to place all row items equally in one line, exactly like what align-Item : center does in html.
My project piece is the image below, but the image is not aligned with the buttons.
And the buttons are a little higher than the picture.
And my codes :
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
const Home({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Row(
children: [
Spacer(),
ElevatedButton(
onPressed: (() {}),
child: Text("Report"),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffffb200),
foregroundColor: Color(0xff00324B)),
),
Spacer(),
ElevatedButton(
onPressed: (() {}),
child: Text("Donate"),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffffb200),
foregroundColor: Color(0xff00324B)),
),
Spacer(),
ElevatedButton(
onPressed: (() {}),
child: Text("Adopt"),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffffb200),
foregroundColor: Color(0xff00324B)),
),
Spacer(),
Container(
margin: EdgeInsets.fromLTRB(0, 30, 0, 10),
height: 60.0,
width: 60.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(95),
image: DecorationImage(
image: AssetImage("assets/images/download.jpg"),
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 14,
)
],
),
],
),
);
}
}
I even tried mainAxisAlignment: MainAxisAlignment.center
and crossAxisAlignment: CrossAxisAlignment.center but it didn't work.
Basically, you can solve your problem by putting the following code
Row(crossAxisAlignment: CrossAxisAlignment.center)
But the problem is with your code.
If you remove the margin of the photo, the problem will be solved
margin: EdgeInsets.fromLTRB(0, 30, 0, 10),
Just remove margin: EdgeInsets.fromLTRB(0, 30, 0, 10), from your last element of Row
Container(
// margin: EdgeInsets.fromLTRB(0, 30, 0, 10),
height: 60.0,
width: 60.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(95),
image: DecorationImage(
image: AssetImage("assets/images/download.jpg"),
fit: BoxFit.cover,
),
),
),
you can just add in the Row`
Row(
crossAxisAlignment: CrossAxisAlignment.center,
)
You should use crossAxisAlignment to align the row. So like this
Row(crossAxisAlignment: CrossAxisAlignment.center)

Screen is reloading every element/api inside when keyboard opens/closes inside a show dialog

I have a screen, which contains a button, when tapping on that button, a showDialog function is been called, which displays a popup with a textfield, whenever the keyboard appears or disappears, the whole screen reloads, even the api calls, as if I'm calling setState ,
the class is a StatefulWidget
Button trigger:
CustomButton(buttonName: defaultLanguage == "en" ? "Settings" : "Ajustes", backgroundColor:
appVioletColor, onPress: () {
PopupScreen().displayDialog(context, isLargeScreen);
}, isLanguage: true, style: Styles.generateWeightFont(Colors.white, isLargeScreen ? 18 : 9, FontWeight.w400),
image: new AssetImage('assets/Settings/setting.png'), isLargeScreen: isLargeScreen ,),
PopupScreen code:
class PopupScreen {
final pinCodeReader = TextEditingController();
Future displayDialog(BuildContext context, bool isLargeScreen) {
return
showDialog(
barrierDismissible: true,
useSafeArea: false,
context: context,
builder: (BuildContext context) =>
Material(
type: MaterialType.transparency,
child: Center(
child:
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child:
Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 2,
width: MediaQuery.of(context).size.width / 1.5,
child:
ListView(
children:[
Column(
children: [
Container(
alignment: Alignment.topCenter,
height: 12,
width: 411,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/WelcomeScreen/purple-top-rec.png"),
)
),
),
const SizedBox(height: 24,),
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/WelcomeScreen/pin_icon.png"),
)
),
),
const SizedBox(height: 17,),
Container(
padding: EdgeInsets.only(left: 25),
alignment: Alignment.topLeft,
child: Text("Please enter security pin", style:
Styles.generateWeightFont(Colors.black, 24, FontWeight.w400),),
),
const SizedBox(height: 15,),
Container(
padding: EdgeInsets.only(left: 25, right: 25),
child: buildCommonTextField("", pinCodeReader, whiteGrey, TextInputType.number),
),
const SizedBox(height: 12,),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: greyColor, width: 1)
),
child: Text("Cancel", style: Styles.generateWeightFont(greyColor, 18, FontWeight.w700),),
),
const SizedBox(width: 10,),
Container(
width: 114,
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: appVioletColor,
border: Border.all(color: greyColor, width: 1)
),
child: Text("Done", style: Styles.generateWeightFont(Colors.white, 18, FontWeight.w700),),
),
],
),
)
],
),
],
),
),
)
)
)
);
}
}
Anyone has an idea what's going on?
thanks
When the keyboard appears or disappears, it is an animation that can last for a little while. During this, the available screen area for your app is constantly changing: on opening the keyboard it shrinks, on closing the keyboard it grows.
Whenever you use MediaQuery.of(context) in your code, Flutter engine will keep notifying your widget about media changes, causing rebuilds. So in your case the widget is rebuilt on every animation frame caused by opening or closing the keyboard.
This is an intended behaviour, for example if the user rotates the screen, the available MediaQuery.of(context).size will change, and it should result in a rebuild. If you'd like to avoid this, organize you code in a way that it calls MediaQuery.of(context) only in those parts where you want to get updates about media parameters constantly.

How to disable Inkwell image button in flutter

I would like to make the inkwell image button to be disabled. I can disable onTap event, but can't make gray like disabled button. I tried with adding this code
decoration: new BoxDecoration(color:Colors.grey.withOpacity(0.6)),
But it doesn't work as I want.
My code:
child: Container(
decoration:
new BoxDecoration(color: Colors.grey.withOpacity(0.6)),
child: Material(
//elevation: 4.0,
clipBehavior: Clip.none,
color: Colors.black,
child: Stack(
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Ink.image(
image: AssetImage(ihaveheard_imagepath),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width / 4 * 3,
height: MediaQuery.of(context).size.width / 6,
child: InkWell(onTap: () {}),
),
Align(
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.all(8.0),
child: InkWell(
child: Text(
LocaleKeys.ihaveheard,
style: TextStyle(
fontSize:
MediaQuery.of(context).size.width / 30,
color: Colors.white),
).tr(),
onTap: () {
ihaveheard_imagepath =
"assets/images/greenbutton.png";
setState(() {});
},
),
),
)
],
),
),
),
child:
IgnorePointer(
ignoring: disableBtn, //true or false
child: Container(
foregroundDecoration: disableBtn
? BoxDecoration( //this can make disabled effect
color: Colors.grey,
backgroundBlendMode: BlendMode.lighten)
: null,
child: ...
You can use IgnorePointer as parent widget to prevent tab event.
IgnorePointer(
ignoring: disableBtn, //true, false
child: yourWidget()
You can pass null to decoration to show default based on tappable state
Container(
decoration: disableBtn? BoxDecoration(...): null,
.....
)

Height adjustment of an Image in a row inside a Card

my idea is to create a card widget that has an image on the left and corresponding text data on the right side. The picture should always take the full height and 1/3 of the width (I used expanded with flex to get this. Not sure if this is the best way). The image should be placed in a stack in order to stack further widgets.
My problem is that I am not able to place the image in the stack without specifying a fixed height. I tried Positoned.fill but this did not work for me.
This is my code so far for the card:
Widget build(BuildContext context) {
return Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Row(
children: [
Expanded(
child: Stack(
children: [
Container(
// child: Positioned.fill(
// child: ClipRRect(
// borderRadius: BorderRadius.circular(15.0),
// child: Image(
// image: AssetImage("assets/eyes.jpg"),
// fit: BoxFit.cover,
// ),
// ),
// ),
),
],
),
),
Expanded(
flex: 2,
child: Container(
color: Colors.grey,
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("This is a test"),
SizedBox(height: 10),
Text("This is a test test"),
SizedBox(height: 10),
Text("This is a test test test"),
SizedBox(height: 10),
Text("This is a test test"),
SizedBox(height: 10),
Text("This is a test"),
],
),
),
),
),
],
),
);
}
Here is a picture of the current state. The image should take up the entire white area on the left side of the card.
Instead of adding a child image widget inside your container, you can add a decoration image to the container itself. Here's how you do it:
Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage("url"),
),
),
),

How to make a container take up the height of the parent widget?

I have a card layout which looks like the following:
The code for it it as follows:
Card(
color: tap ? Colors.green : Colors.white,
margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Container(
child: Row(
children: [
**Container(
height: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
width: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),**
),
SizedBox(
width: 8.0,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
howManyThere() > 0 ? "${howManyThere()} x " : '',
style: addBTNHighlight,
),
Expanded(
child: Text(
widget.menuItem.item_name,
overflow: TextOverflow.ellipsis,
style: tap ? TitleWhite18Bold : Title18bold,
),
),
],
),
Container(
child: Text(
widget.menuItem.description,
//overflow: TextOverflow.ellipsis,
style: tap ? SubTitleWhite13 : SubTitle13,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Text(
"£" + num.parse(widget.menuItem.price).toStringAsFixed(2),
style: tap ? priceHighlightSelected : priceHighlight,
),
),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 6.0),
decoration: BoxDecoration(),
child: Text("ADD", style: tap ? priceHighlightWhite : addBTNHighlight)),
],
),
],
),
),
)
As you can see that I am almost there with my desired layout but with one small issue which can be seen in first and last item. Because of the given width and height of the image container, it leaves a gap on top and bottom.
What I would like to happen is that the width to stay the same but the height to be flexible and adjust with the height of the card itself. Is it possible?
When I remove the height attribute of the container with the image, I get a blank space of the image
UPDATE: I tried LayoutBuilder as well but without any Luck, it throws 'Incorrect use of ParentWidget' Exception. The code I used is as follows:
Row(
children: [
widget.menuItem.image.endsWith('/')
? Container()
: **LayoutBuilder(
builder: (context, constraints){
return Container(
width: 70.0,
height: constraints.minHeight,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),
);
}**
),
Try this :
Column(
children: [
Expanded(
child: Container(
width: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),
),
),
],
),
The problem here is your description text which overflow your desired max height. You can try to constraint your Container with a height: 70.0 or you can add to your Text widget the property maxLines: 1.
LayoutBuilder only give you constraints that parent pass to child, which is something like 100 < width < 200, 300 < height < infinity. At this point the height of all texts on the right are not determined yet, so it is impossible to determined the height of image base on that.
One way to do this is to assign key to each list item, get item heights after everything is layout, the rebuild with those fixed height. This will become a two pass process and is less efficient.
The official solution to this is IntrinsicHeight, which conceptually do the same thing, but in a more optimized way.
Here is a minimum example:
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: App(),
),
);
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
// This is where magic happened
child: IntrinsicHeight(
child: Row(
children: [
Container(
width: 100,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://cataas.com/cat'),
fit: BoxFit.cover,
),
),
),
Expanded(
child: Text(
// just put some random text with dynamic height
'Text\n' * (Random().nextInt(4) + 4),
),
),
],
),
),
);
},
),
);
}
}
Remove height constraints, then
Try replacing fit: BoxFit.cover with BoxFit.fitHeight or BoxFit.fill.
In order to fill the image with card height you can give container required height and wrap the Image widget in AspectRatio widget with ratio 1. This will always helps image widget to fill parent card height. Have a look in below code.
Parent Widget
Container(
margin: EdgeInsets.only(bottom: 12),
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 1,
child: _pictureWidget(widget.menuItem.image),
),
/// Replace `Container` with the needed widget
Expanded(child: Container()),
],
),
)
_pictureWidget
Widget _picture(String url) {
return _pictureWidget(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
child: Image.network(
url != null ? url : "",
fit: BoxFit.cover,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
),
);
}