I am trying to add a box shadow over a widget that displays an image. Whenever I include the box-shadow within the parent container, the shadow is only shown on the container which is stacked behind the child image. How can I have the shadow be displayed for the child image?
import 'package:flutter/material.dart';
import 'package:flutter_course_app_4/pages/nft_post.dart';
class NFTIconTemplate extends StatelessWidget {
final String NFTImg;
NFTIconTemplate({required this.NFTImg});
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
child: InkWell(
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black54,
offset: Offset(4.0, 4.0),
blurRadius: 15.0,
spreadRadius: 1.0),
],
color: Colors.grey[800],
),
child: Column(
children: [
Image.network(
NFTImg,
width: 120,
height: 160,
fit: BoxFit.cover,
),
],
),
),
onTap: () {
print('Clicked NFT Icon');
Navigator.push(
context, MaterialPageRoute(builder: (context) => nftPost()));
},
),
),
);
}
}
Try this code to get extra shade to your code,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.6),
spreadRadius: 8,
blurRadius: 6,
offset: Offset(0, 4),
),
],
),
Related
Long story short I have a stack, in which I have an image that is position out of the stack.
body: Column(
children: [
Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
_positionedImage(),
],
),
_bodyContainer(),
],
container:
Widget _bodyContainer() {
return Container(
width: MediaQuery.of(context).size.width,
height: 200,
decoration: BoxDecoration(
color: itsyBackground,
borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
boxShadow: [BoxShadow(offset: Offset(0, 0), color: Colors.green, spreadRadius: 1, blurRadius: 1),],
),
);
}
How can I make so that picture is on top of the container?
the approach that you used is wrong here.. You don't need a column here. You can simply render a stack an the bottom most widget should be placed first in the stack children.
https://medium.com/flutter-community/a-deep-dive-into-stack-in-flutter-3264619b3a77
An Example:
Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20)),
boxShadow: [
BoxShadow(
offset: Offset(0, 0),
color: Colors.green,
spreadRadius: 1,
blurRadius: 1),
],
),
),
Positioned(
top: -10,
child: Image.network(
'https://static.toiimg.com/thumb/msid-31346158,width-748,height-
499,resizemode=4,imgsize-114461/.jpg',
width: 100,
),
),
],
),
I would like to shows a container elements with expansion and collapse effect.
It is not combined with AppBar.
Here is my container code:
InkWell(
onTap: () {
if (_height == 200) {
setState(() {
_height = 100.0;
});
} else {
_updateState();
}
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 550),
height: _height,
width: Get.width,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("0.0"),
Text("0.0"),
//Widget1(),
//Widget2(),
//Widget3(),
],
),
),
);
I want it to show my other Widgets when I click it.
Also I tried ExpansionPanelList and ExpansionTile but they are not working like what I exactly want. Also I don't want to use SliverAppBar .
This example might help you:
class _MyHomePageState extends State<MyHomePage> {
double _height = 100;
void onClick() {
if (_height == 300) {
setState(() {
_height = 100.0;
});
} else {
setState(() {
_height = 300;
});
}
}
#override
Widget build(BuildContext context) {
final List<Widget> _widgets = [
Container(
width: MediaQuery.of(context).size.width,
height: 100,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: Colors.grey,
),
Container(
width: MediaQuery.of(context).size.width,
height: 100,
decoration: const BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.red,
),
],
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
)
];
return Scaffold(
backgroundColor: Colors.blueAccent,
body: Column(
children: [
InkWell(
onTap: () {
onClick();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 550),
height: _height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
children: _widgets,
),
),
),
),
],
),
);
}
}
result:
you can add condition in you column like this
children: [
Text("0.0"),
Text("0.0"),
if(_height == 200)
Widget1(),
if(_height == 200)
Widget2(),
if(_height == 200)
Widget3(),
],
also you can use AnimatedSwitcher
https://api.flutter.dev/flutter/widgets/AnimatedSwitcher-class.html
I want to display a text at the bottom left if the image to be like as the below figure:
and this the below code is related:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/city.dart';
class ProvinceItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
final city = Provider.of<City>(context, listen: false);
// final cart = Provider.of<Cart>(context, listen: false);
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
splashColor: Colors.transparent,
onTap: () => {},
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(2.5, 2.5),
blurRadius: 16,
),
],
),
margin: EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: Image.asset(
city.cityImage,
fit: BoxFit.cover,
),
),
),
),
);
}
}
I have just create a list of Grid widget and as every list of grid item have a grid item just shown like the previous code...
as I need the best suggestion for this Grid item as it only contains just an image and a text with some of shadows..
Stack widget will do the trick for you.
Stack(
children: <Widget>[
InkWell(
splashColor: Colors.transparent,
onTap: () => {},
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(2.5, 2.5),
blurRadius: 16,
),
],
),
margin: EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: Image.asset(
city.cityImage,
fit: BoxFit.cover,
),
),
),
),
Container(
margin: EdgeInsets.only(left: 20, bottom: 20),
child: Align(
alignment: Alignment.bottomLeft,
child: Text(
'Text',,
style: TextStyle(color: Colors.white, fontSize: 20),
)),
),
],
),
I have a simple ClipRRect widget as the below one:
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: GridTile(
child: Image.network(
imageUrl,
fit: BoxFit.cover,
),
footer: GridTileBar(
backgroundColor: Colors.black87,
leading: IconButton(
icon: Icon(Icons.favorite),
color: Theme.of(context).accentColor,
onPressed: () {},
),
title: Text(
title,
textAlign: TextAlign.center,
),
trailing: IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {},
color: Theme.of(context).accentColor,
),
),
),
);
}
I tried to add a shadow by wrapping this widget with another Card widget to add a shadow with an elevation as the below code:
#override
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 5,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: GridTile(
child: Image.network(
imageUrl,
fit: BoxFit.cover,
),
footer: GridTileBar(
backgroundColor: Colors.black87,
leading: IconButton(
icon: Icon(Icons.favorite),
color: Theme.of(context).accentColor,
onPressed: () {},
),
title: Text(
title,
textAlign: TextAlign.center,
),
trailing: IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {},
color: Theme.of(context).accentColor,
),
),
),
),
);
}
but I think it's not logical at all because it shows the grid item a bit smaller, and also I need add a border in this grid..
I hope this would be clear enough..
you can create your widget to take in a shadow and border colors as follows
since ClipRRect cant take in shadow or border color we use a container
clipRRect constructor
ClipRRect({Key key, BorderRadius borderRadius: BorderRadius.zero, CustomClipper<RRect> clipper, Clip clipBehavior: Clip.antiAlias, Widget child})
.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
width: 200,
child: Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
topRight: Radius.circular(10)),
side: BorderSide(width: 2, color: Colors.green)),
child: Center(
child: Icon(
Icons.movie,
size: 150.0,
),
),
),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.white54,
blurRadius: 5.0,
offset: Offset(0, 10),
spreadRadius: 0.5,
),
],
borderRadius: BorderRadius.circular(12),
),
);
}
}
Here's another solution which worked for me.
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SizedBox(
child: ImageWidget(imageUrl),
width: 100,
height: 100,
),
),
width: 100,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.15),
blurRadius: 8,
spreadRadius: 6,
offset: const Offset(0, 0),
),
],
),
)
I implemented it like below
Stack(alignment: Alignment.center, children: [
Container(
width: DeviceUtils.getScaledHeight(context, 0.072),
height: DeviceUtils.getScaledHeight(context, 0.072),
decoration: BoxDecoration(
border: Border.all(color: Colors.green),
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.white54,
blurRadius: 5.0,
offset: Offset(0, 10),
spreadRadius: 0.5,
),
],
),
),
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: ImageFromURL(
url: "https://i.pinimg.com/originals/63/81/a7/6381a77565b51a541d0d85cb145e7d94.jpg",
width: DeviceUtils.getScaledHeight(context, 0.07),
height: DeviceUtils.getScaledHeight(context, 0.07)),
),
])
I've the following code:
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: InkWell(
onTap: () {
....
},
child: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Theme.of(context).primaryColor,
width: 3.0,
)),
//borderRadius: BorderRadius.only(topLeft: const Radius.circular(5.0), topRight: const Radius.circular(5.0)),
),
height: 133,
child: ...,
),
));
}
The problem is that I am trying to set a color on the top border and assign a border radius of 5. As far as I am aware, I can't assign a color to the top border in the card. You have to set it all the way around. But you can do this on the container. The problem is that adding a radius to the Container makes the content inside it disappear.
That's an interesting mechanic... Though not ideal, I suppose you could wrap your child with a Column and make your own custom border element, so it doesn't clash with your content.
Something like this:
class MyTopBorder extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(5.0),
topRight: const Radius.circular(5.0),
),
color: Theme.of(context).primaryColor,
),
height: 3.0,
);
}
}
and then add it to your Card:
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: InkWell(
onTap: () {
// ...
},
child: Column(
children: <Widget>[
MyTopBorder(),
Container(
height: 133,
child: Text("..."),
),
],
),
),
),