Overlap widget inside card widget in Flutter - flutter

I wanted to place two widgets (a text and a picture) inside a card, however the picture should go over the card as the image shows:
But I don't know how to make the picture overlapping the card.
This is my code:
Card(
margin: EdgeInsets.zero,
color: Theme.of(context).colorScheme.primary,
clipBehavior: Clip.antiAlias,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
Container(
alignment: Alignment.bottomLeft,
margin: const EdgeInsets.all(12),
height: 70,
child: Text(
"This is a text widget.",
style: Theme.of(context).textTheme.bodyText1,
),
),
Image.asset(
'images/picture1.png',
scale: 5,
),
],
),
),

You can use stack widget along with positioned widget to achieve the UI
Stack
Card
Container

Card(
margin: EdgeInsets.zero,
color: Theme.of(context).colorScheme.primary,
clipBehavior: Clip.antiAlias,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Stack(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
alignment: Alignment.bottomLeft,
margin: const EdgeInsets.all(12),
height: 70,
child: Text(
"This is a text widget.",
style: Theme.of(context).textTheme.bodyText1,
),
),
Image.asset(
'images/picture1.png',
scale: 5,
),
],
),
],
),
),
you can use stack under card widget

Related

Placing button at the bottom of container in flutter

How can I create button like below,
Try below code hope its helpful to you. used Stack widget here for that
Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: circleRadius / 2.0),
child: Container(
height: 200,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Colors.white,
margin: EdgeInsets.all(
16,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 2,
height: 2,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.transparent,
),
),
],
),
),
),
),
Container(
width: 100,
height: 40,
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(),
color: Colors.transparent,
),
child: Padding(
padding: EdgeInsets.all(1),
child: DecoratedBox(
child: Center(
child: Text(
'Profile',
style:TextStyle(color: Colors.white,),
textAlign: TextAlign.center,
),
),
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.blue,
),
),
),
)
],
),
Your Result screen->
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(20))),
child: TextButton(
child: Text(
"Profile",
style: TextStyle(color: Colors.white),
),
onPressed: () {},
),
),
you can use following code sample...change height according to your need...or use mediaquery for better result:
Container(
height: 275,
child: Stack(
children: [
Container(//container with background color
height: 250,
child: //other widgets
),
Positioned(
bottom: 0,
child: //button here
),
],
),
),

Flutter icon how to fill all the width and height available in the tab

i've a card like this.
Actual card
but i want a card like this
What i want
My code is:
return Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
margin: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0),
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: Container(
padding: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Example text'),
Text("20-06-2021 - 13:00",
style:
TextStyle(fontSize: 15, fontStyle: FontStyle.italic)),
Text("Example text"),
Text("Example text"),
],
),
Column(
children: <Widget>[
Flag(
'FR',
height: 40,
width: 40,
replacement: Text('Error'),
),
],
),
],
),
),
);
Now, i have fixed height and width, i'm not able to obtain what i want because each attempt enlarge the card in height.(I want to keep the same height as the card above).The icons comes from the package flags (Flags package)
Instead of wrapping a Container in a Card. Try to Wrap a Row with Expanded in the Card. (I just changed the Container into padding)
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
margin: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0),
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: Padding(
padding: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Example text'),
Text("20-06-2021 - 13:00",
style: TextStyle(
fontSize: 15, fontStyle: FontStyle.italic)),
Text("Example text"),
Text("Example text"),
],
),
),
Expanded(
flex: 1,
child: Container(
height: 100,
color: Colors.red,
),
)
],
),
),
),
try this
to let it fit the width and the height:
Flag('AD', height: double.infinity, width: double.infinity, fit: BoxFit.fill)
or maybe this:
Flag('AD', height: null, width: null, fit: BoxFit.fill)
I recommend to make this flag Expandable widget inside the row
wrapped your Flag inside SizedBox if you know what fixed size it is like this.
SizedBox(
height: 65,
width: 140,
child: Flag(
'FR',
replacement: Text('Error'),
fit: BoxFit.cover,
),
)
More about SizedBox Here

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:

Create a Card widget and call it multiple times

So im trying to build a page with lots of images in it, right now im using Stack widget to show the images,
this is my code:
import 'image_description.dart';
class Gallery extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white10,
elevation: 0,
leading: Container(
padding: EdgeInsets.fromLTRB(20, 20, 0, 0),
child: InkWell(
child: Hero(
tag: 'back',
child: Image.asset(
'assets/images/wp_back_button_icon.png',
height: 250,
),
),
onTap: () {
Navigator.pop(context);
},
),
),
actions: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(0, 20, 20, 0),
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/wp_logo.png',
height: 250,
),
),
),
],
),
body: SafeArea(
child: Column(
children: <Widget>[
Container(
child: Text(
'AR Gallery',
style: TextStyle(fontSize: 30),
),
),
Container(
child: Text("Let's educate in the fun way"),
),
Expanded(
child: SizedBox(
height: double.infinity,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
crossAxisCount: 3,
children: <Widget>[
InkWell(
child: Stack(
children: <Widget>[
Container(
height: 120,
width: 200,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image1',
child: Image.asset(
"assets/images/gallery/Image1.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImageDescription()));
},
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image2',
child: Image.asset(
"assets/images/gallery/Image2.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image3',
child: Image.asset(
"assets/images/gallery/Image3.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image4',
child: Image.asset(
"assets/images/gallery/Image4.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image5',
child: Image.asset(
"assets/images/gallery/Image5.png",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image6',
child: Image.asset(
"assets/images/gallery/Image6.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image7',
child: Image.asset(
"assets/images/gallery/Image7.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image8',
child: Image.asset(
"assets/images/gallery/Image8.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text('Title',
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
],
),
),
),
],
),
),
);
}
}
As you can see, i'm using a lot of repeated Stack widget manually.
Can I make that automated? like creating a Stack widget or something similar once, and then call it where it should be with different Title.
Regards, Slim
It is indeed possible, this is what we call a reusable widget.
You can create it in the same file or in a separate one. I would suggest creating a widgets folder containing a dart file (whatever you want to name it) that'll contain your reusable widget.
1- If you only want the title to be different each time it should be something like this:
class SpecialStack extends StatelessWidget{
final String title;
SpecialStack({this.title});
#override
Widget build(BuildContext context){
return Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image2',
child: Image.asset(
"assets/images/gallery/Image2.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text(title,
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
}
}
2- If you want the image to be different whenever you use your reusable widget, it should be something like this. (I provided this case because I saw you were using different image for each Stack):
class SpecialStack extends StatelessWidget{
final String title, image;
SpecialStack({this.title, this.image});
#override
Widget build(BuildContext context){
return Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: image,
child: Image.asset(
"assets/images/gallery/$image.jpg",
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text(title,
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
}
}
For the first case (only title is different),
You can just replace wherever you're using the Stack by this:
SpecialStack(title: "Your desired title")
For the second case (image and title are different):
SpecialStack(title: "Your desired title", image: "your_image_name")
I hope this helps. I tried to be as clear as possible.
keep your images in a list then map the list. and inside map define a Stack widget. it will automatically create the stacks of your list of images.
You should write one function return widget type. Every time you want to show image you can call it.
Ex
Widget showImage(String url, String text){
return Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Hero(
tag: 'Image8',
child: Image.asset(
"url,
fit: BoxFit.fitHeight),
),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text(text,
style: TextStyle(
backgroundColor: Colors.deepOrange,
color: Colors.white)),
),
)
],
),
}

Specific position of icon in Container with BoxDecoration and child: Row

I am trying to move the red block to the right of the Container. I have tried many variations but no matter where I move the code, that "red container" bit, I cannot get it to the position on the top right. I will make it a clickable icon when I get the positioning right.
I did move it into the children Widget with the other Text, adjusted the "crossAxisAlignment to stretch in that row, and mainAxisAlignment to spaceBetween,"
The closest I have is the 2nd image which is the code added below.
What am I missing?
items.add(
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [BoxShadow(color: Colors.black12,spreadRadius: 2.0,blurRadius: 5.0),]),
margin: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Image.asset(object["personImage"],
width: 80,height: 80,fit: BoxFit.cover,
),
),
Container(
color: Colors.blue[900],
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(object["personName"]),
Text(object["personPlace"]),
Text(object["personDate"]),
Text(object["personCircle"]),
],
),
),
),
Container(
alignment: Alignment.topRight,
height: 42.0,
width: 42.0,
color: Colors.red,
)
],
),
),
);
},
);
return items;
Edit: So two solutions that worked out great. Adding a widget between blue and red containers. Thanks to you both: :)
T.T Sage » Spacer(),
Viren V Varasadiya » Expanded(child: Container()),
You can use a widget called Spacer() for this.
The Spacer widget takes up space that isn't used by the rest of your widget. Check the code below, it works fine:
items.add(
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [BoxShadow(color: Colors.black12,spreadRadius: 2.0,blurRadius: 5.0),]),
margin: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Image.asset(object["personImage"],
width: 80,height: 80,fit: BoxFit.cover,
),
),
Container(
color: Colors.blue[900],
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(object["personName"]),
Text(object["personPlace"]),
Text(object["personDate"]),
Text(object["personCircle"]),
],
),
),
),
// add your spacer widget here
Spacer(),
Container(
alignment: Alignment.topRight,
height: 42.0,
width: 42.0,
color: Colors.red,
)
],
),
),
);
},
);
return items;
I hope this answers your question.
You need to use Expanded widget to do so.
In following code i show how to add Expanded widget and where yo add.
Container(
color: Colors.blue[900],
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(object["personName"]),
Text(object["personPlace"]),
Text(object["personDate"]),
Text(object["personCircle"]),
],
),
),
),
Expanded(child: Container()), // added widget
Container(
alignment: Alignment.topRight,
height: 42.0,
width: 42.0,
color: Colors.red,
)