Adding Shadows at the bottom of a container in flutter? - flutter

I have a simple screen with a container about 100 in height and with blue color. I want to add a shadow or elevation at the bottom of the container.
This is my code below
import 'package:flutter/material.dart';
import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/dimens.dart';
import 'package:finsec/utils/colors.dart';
void main() {
runApp(new IncomeFragment());
}
class IncomeFragment extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
new Container(
height: margin_100dp,
color: colorPrimary,
),
new Container( //container to overlay on top of blue container
alignment: Alignment.topCenter,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
zero_amount,
style: TextStyle(color: white, fontSize: 40.0, fontWeight: FontWeight.bold)
),
],
),
)
],
);
}
}
can someone help me to add a shadow or elevation at the bottom of my blue container?
see image below. shawdow should be in place in the red circle
thanks in advance

You can reuse the first container that you have in your Stack, the container has a property called decoration and it accept a widget of kind BoxDecoration, as you can see in this link: BoxDecoration
Inside this widget you can use the boxShadow property to give to your container a custom shadow, try the next code:
new Container(
height: margin_100dp,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
blurRadius: 15.0,
offset: Offset(0.0, 0.75)
)
],
color: colorPrimary
),
),

Or you can wrap your Container widget with a Material widget which contains an elevation property to give the shadowy effects.
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Material(
elevation: 15.0,
child: Container(
height: 100,
width: 100,
color: Colors.blue,
child: Center(child: Text("Material",style: TextStyle(color: Colors.white),)),
),
),
SizedBox(width: 100,),
Container(
height: 100,
width: 100,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
blurRadius: 15.0,
offset: Offset(0.0, 0.75)
)
],
color: Colors.blue
),
child: Center(child: Text('Box Shadow',style: TextStyle(color: Colors.white))),
),
],
),
),
Image:
Difference between two widgets is shown above. Hope this helps!!!

Yes, BoxShadow can solve the problem but instead of manually adding the list of BoxShadow, there is a handy map in flutter call kElevationToShadow which map elevation keys to pre-defined list of BoxShadow. It is also defined based on the material design elevation.
Container(
height: 60.0,
decoration: BoxDecoration(
boxShadow: kElevationToShadow[4],
color: Theme.of(context).bottomAppBarColor,
),
child: ...
);

Container(
margin: EdgeInsets.only(bottom: 7),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: kElevationToShadow[2], // Use This kElevationToShadow ***********
),
child: Center(child: Text('With BoxShadow')),
),
Material( // Using Material Widget ***********************
elevation: 5,
borderRadius: BorderRadius.circular(10),
child: Container(
margin: EdgeInsets.only(bottom: 7),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Center(child: Text('With BoxShadow')),
),
),

use the Container Shadow as below:
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black,
offset: Offset(20.0, 10.0),
blurRadius: 20.0,
spreadRadius: 40.0,
),
],
),
Controll the blurRadius and the SpreadRadius depending on your needs

if you want a container to have shadow only top
boxShadow: [
BoxShadow(
color: Color.fromARGB(255, 218, 218, 218),
blurRadius: 10.0, // soften the shadow
spreadRadius: 0.0, //extend the shadow
offset: Offset(
0.0, // Move to right 10 horizontally
-15.0, // Move to bottom 10 Vertically
),
)
],

You can add several BoxShadow to show the shadow you need,
with OffSet propertie you can move the shadow.
boxShadow: [
BoxShadow(
color: Colors.blue,
offset: Offset(0, 8), // hide shadow top
blurRadius: 5),
BoxShadow(
color: Colors.white, // replace with color of container
offset: Offset(-8, 0), // hide shadow right
),
BoxShadow(
color: Colors.white, // replace with color of container
offset: Offset(8, 0), // hide shadow left
),
],

Related

boxshadow in container and column

Container(
width: double.infinity,
margin: EdgeInsets.only(top: 20),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 10,
color: Colors.black87,
offset: Offset(0, -10),
),
],
),
child: Column(
children: [
Text("adsds"),
],
),
)
i want to make this shadow but i didnt make it what i want,anyone help me?
You can simply use a Card class to achieve that kind of shadow and by use of elevation and shadowColor, customize it as you want.
More details: Flutter card class
As an example, here's a code:
Card(elevation: 12,child: Container(padding: EdgeInsets.all(24),child: Text('Content!')))

Flutter InkWell on tap is not being detected

I am using inkwell to detect tap. I also use gesturedetector but that didn't work as well. Found a solution that say wrap the child with IgnorePointer, but that didn't work as well.
Here is my code:
Positioned(
bottom: -67,
child: GestureDetector(
onTap: () {
print('Tap');
},
child: Container(
width: 70,
height: 70,
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 5,
),
boxShadow: [
BoxShadow(
color:
Color(0xFF000000).withAlpha(11),
blurRadius: 16,
offset: Offset(0, 3),
),
],
shape: BoxShape.circle,
color: Colors.white,
),
child: CircleAvatar(
radius: 24,
backgroundColor: Colors.green,
child: Icon(
Icons.arrow_forward,
color: Colors.white,
),
),
),
),
),
This is the button on which i want to detect tap.
EDIT: It is detecting the tap but outside the white border of circle avatar. I want the whole White border and circle avatar to be clickable. Removing the positioned makes the whole container clickable but now how i want to position that element in the stack !!!
Remove Positioned widget and wrap the container in Inkwell

In Flutter, whenever I try to put a Cloumn in ScrollView, entire screen gets blank. How to overcome this?

I want my column to be scrollable and I cannot use a Listview as I want the children in Column view to be spaced evenly. Having said that, I want my column to be scrollable. Placing the Column in SingleChildSCrollView, my entire screen becomes blank. Can anyone please suggest me a good option to make my column scrollable without using listview/singlechildscrollview.
The actual code in which I am facing this issue is too big to trace the real problem. I am providing a sample code which highlights the issue that I am facing. Here is my code:
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.red,
title: Text(
"Beverages",
),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150.0,
decoration: BoxDecoration(
color: kWhiteColor,
borderRadius: BorderRadius.circular(3.0),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 3.0,
spreadRadius: 1.0,
offset: Offset(2, 2),
)
],
),
),
),
),
Flexible(
flex: 3,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150.0,
decoration: BoxDecoration(
color: kWhiteColor,
borderRadius: BorderRadius.circular(3.0),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 3.0,
spreadRadius: 1.0,
offset: Offset(2, 2),
)
],
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150.0,
decoration: BoxDecoration(
color: kWhiteColor,
borderRadius: BorderRadius.circular(3.0),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 3.0,
spreadRadius: 1.0,
offset: Offset(2, 2),
)
],
),
),
),
],
)),
Flexible(
flex: 4,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150.0,
decoration: BoxDecoration(
color: kWhiteColor,
borderRadius: BorderRadius.circular(3.0),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 3.0,
spreadRadius: 1.0,
offset: Offset(2, 2),
)
],
),
),
),
),
],
),
),
);
You can’t use MainAxisAlignment.spaceEvenly when you have your Column inside a SingleChildScrollView. Why this? You're trying to scroll, but your height is somehow infinite and how would you space your children evenly in an infinite space? The same applies when using Flexible widgets. The way to have things scrollable would be if you use either a ListView or a Column inside a SingleChildScrollView. There are other widgets too, but they follow the same logic. I would recommend: you keep your Column wrapped in a SingleChildScrollView and place SizedBox widgets between components to have them evenly separated. Another option would be to use a ListView.builder and place a SizedBox after the Widget to be built. In that way you should be able achieve what you're looking for.
So, about your code: I deleted this spaceEvenly enum because of the reason above. After that, I ran your code and I obtained this:
RenderFlex children have non-zero flex but incoming height constraints
are unbounded
That is the thing with the infinite space I told you the Flexibles are trying to take but they can’t. I also deleted them. So how could you give your Widgets desired size? I would use Containers with static height and inside them, there is where I could then use Expanded or Flexible widgets. If you want something scrollable but don’t want it to occupy the whole screen, try using a Container with static height and inside it a ListView.builder.

flutter only bottom shadow to container

i have tried many solution but i couldn't get what i want.
https://stackoverflow.com/a/56744034/4862911 i applied in this answer but couldn't get correct response. There is still shadow top of container. How can i achieve it?
and also i have tried to surround my widget with Material . but still can't solve the problem.
Material(
elevation: 5,
child: Container(
height: 50,
child: _buildEloAndLevel(),
),
),
Material(
elevation: 5,
child: Container(
height: 50,
child: _buildEloAndLevel(),
// add boxShadow
decoration: BoxDecoration(
boxShadow: [
color: Colors.black54,
blurRadius: 15.0,
],
),
),
),
This will create a shadow of 15 units arounds the Container. Now, the shadow can be moved with the offset property. Since, we don't want shadow on top, we can move it down by 15 units.
Material(
elevation: 5,
child: Container(
height: 50,
child: _buildEloAndLevel(),
// add boxShadow
decoration: BoxDecoration(
boxShadow: [
color: Colors.black54,
blurRadius: 15.0,
offset: Offset(0, 15), // horizontally move 0, vertically move 15,
],
),
),
),
I don't know if other examples are really setting a shadow for only bottom, but here is a know solution:
Container(
height: 50.0,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
blurRadius: 20.0,
spreadRadius: -20.0,
offset: Offset(0.0, 25.0),
)
],
color: Colors.red,
),
),
Set the blur of the shadow with blurRadius and then set the spreadRadius to negative the blurRadius then use the dy property of the Offset() constructor, you set it to positive values to control the shadow bottom.
All you need to do is playing around with your offset's value. And I think you don't need to wrap it with Material.
Offset is the displacement of the shadow from the box. It requires 2 double-types values, Offset(x, y);
Example:
Container(
height: 50.0,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
offset: Offset(15.0, 20.0),
blurRadius: 20.0,
)
],
color: Colors.red,
),
),
TIPS FROM ME: To make sure the shadow doesn't show up in the top of your container, make sure your blur radius is not bigger than your Offset's y-value.

How to only add a shadow on one specific side of a Container?

I am trying to add a shadow to only the right side of of my container widget using the boxShadow parameter in the BoxDecoration widget.
new Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
boxShadow: [
BoxShadow(
blurRadius: 5.0
),
],
),
),
This code works but adds a shadow to every possible side of the container. I would like to have it only be on the right side.
You can set the offset property of BoxShadow. It is defined as Offset(double dx, double dy). So, for example:
boxShadow: [
BoxShadow(
blurRadius: 5.0,
offset: Offset(3.0, 0),
),
],
This will cast a shadow only at 3 units to the right (dx).
boxShadow property of BoxDecoration takes a list of BoxShadow, so you can pass solid BoxShadow to the rest of the sides and corners with background color. Note that a small shadow remains at the corners, but hey!... Life is not perfect ;)
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('Shadow Test')),
body: Center(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.blueAccent,
boxShadow: [
BoxShadow(blurRadius: 8.0),
BoxShadow(color: Colors.white, offset: Offset(0, -16)),
BoxShadow(color: Colors.white, offset: Offset(0, 16)),
BoxShadow(color: Colors.white, offset: Offset(-16, -16)),
BoxShadow(color: Colors.white, offset: Offset(-16, 16)),
],
),
),
),
);
Screenshot
This is one way:
Container(
width: 230,
height: 200,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(),
child: Container(
margin: EdgeInsets.only(right: 30), // ***
decoration: BoxDecoration(
color: Colors.blue,
boxShadow: [
BoxShadow(
color: Colors.red,
blurRadius: 20,
spreadRadius: 8,
)
],
),
),
)
*** : whichever side you give margin to, that side will show the shadow. Giving margin to multiple sides also works.
A box shadow is actually just a tinted, blurred and shifted version of the parent object which is then rendered underneath it. That's why having a box shadow just on one side isn't trivial.
The most straight forward solution is to cut off the shadow on the sides where you do not need it. In Flutter this can be nicely achieved via the CustomClipper class. The example below clips the entire shadow of the object except on the sides where we define a padding (which should be at least as large as the overlapping shadow).
/// Clips the given object by its size.
/// The clip area can optionally be enlarged by a given padding.
class ClipPad extends CustomClipper<Rect> {
final EdgeInsets padding;
const ClipPad({
this.padding = EdgeInsets.zero
});
#override
Rect getClip(Size size) => padding.inflateRect(Offset.zero & size);
#override
bool shouldReclip(ClipPad oldClipper) => oldClipper.padding != padding;
}
ClipRect(
clipper: const ClipPad(
padding: EdgeInsets.only(left: 30, top:30)
),
child: Container(
width: 200,
height: 200,
decoration: const BoxDecoration(
color: Colors.black,
boxShadow: [
BoxShadow(
color: Colors.red,
blurRadius: 20,
)
]
)
)
);
Note: You might want to use a different Clipper-Widget and CustomClipper for shapes other than rectangles like for example ClipRRect or ClipPath.
Note that MyShadowSize = spreadRadius + x/y Offset.
Example:
If spreadRadius: 1, offset: Offset(0, 0) => 4 sides is MyShadowSize has 1 + 0 = 1.
If you want only bottom shadow = 1, you can add: spreadRadius: 0, offset: Offset(0, 1),
Explain: Current y offset = 1, => MyShadowSize bottom = 1, MyShadowSize top = -1 (because y move down) => MyShadowSize top not show.
To avoid those ugly edges from the other answers here, you can do it this.
final oneSideShadow = Padding(
padding: const EdgeInsets.only(left: 30, right: 30, top: 30),
child: Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: borderRadius,
boxShadow: [
BoxShadow(
color: Colors.red.withOpacity(0.95),
blurRadius: 26,
offset: const Offset(0, 2), // changes position of shadow
),
],
),
),
);
return Container(
width: 200,
height: 200,
child: Stack(
children: [
oneSideShadow,
Container(
decoration: const BoxDecoration(
color: Colors.yellow,
),
),
],
),
);
You can get pretty wild results with this, e.g. if you modify the code above, and put row+expanded childs with different shadows there.
Adding shadow to a single side is very hard since it's a shifted and blurred version of the parent widget. I tried all the other ways but didn't work really well.
for longer shadow.
I also found one other way is by use Stack Widget to cover the other sides. If you don't have anything near that widget. if you have a widget near it, you can use that widget to cover the shadow.
Please refer to the code below.
Stack(alignment: Alignment.topCenter, children: [
Padding(
padding: EdgeInsets.only(top: 14),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color(0xff000000).withOpacity(0.1),
spreadRadius: 0,
blurRadius: 10,
offset: Offset(0.0, 4),
// // changes position of shadow
),
],
),
child: TabBar(
indicatorColor: Color(0xffFF7000),
unselectedLabelColor: Color(0xff818898),
labelColor: Color(0xffFF7000),
tabs: [
Tab(
child: Text(
'Tab 0'
style: TextStyle(
fontSize: UiSizeUtils.getFontSize(14),
fontWeight: FontWeight.w600),
),
),
Tab(
child: Text(
'Tab 1'
style: TextStyle(
color: Color(0xff8D99BB),
fontSize: UiSizeUtils.getFontSize(14),
fontWeight: FontWeight.w600),
),
),
],
controller: _tabController,
indicatorSize: TabBarIndicatorSize.tab,
),
),
),
Container(
width: double.infinity,
height: UiSizeUtils.getHeightSize(16),
color: Colors.white,
)
]),
This is how I added the shadow for the bottom only for the tab view and this works best for my use case when compared with the other method mentioned above.