I have to create a Card like this:
I had written below code to achieve the desired UI, but it didn't work as expected.
Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
topRight: Radius.circular(10)),
side: BorderSide(width: 5, color: Colors.green)),
child: ListTile(),
)
The code above produced this:
Whereas using the code below:
Card(
elevation: 5,
shape: Border(right: BorderSide(color: Colors.red, width: 5)),
child: ListTile(),
)
generated this output:
How can I create the required UI in flutter?
Use the shape parameter in the Card widget, example:
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container() )
I have used ClipPath to achieve the UI asked in the question, check out the below code.
Card(
elevation: 2,
child: ClipPath(
child: Container(
height: 100,
decoration: BoxDecoration(
border: Border(right: BorderSide(color: Colors.green, width: 5))),
),
clipper: ShapeBorderClipper(shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3))),
),
)
This gives the below output,
If there is a better way to achieve said result kindly do answer.
This solution worked for me. If we remove the shape property from the card, it leaves behind rectangular white corners. No limitation of elevation whatsoever.
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
shadowColor: Colors.blueAccent,
elevation: 15,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Container(
height: 180,
decoration: BoxDecoration(
border: Border(
left: BorderSide(color: Colors.red, width: 15)),
color: Colors.yellowAccent.shade100,
),
padding: EdgeInsets.all(20.0),
alignment: Alignment.centerLeft,
child: Container()),
),
)
You should place your Card inside a ClipRRect widget :
return ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Card(
elevation: 5,
shape: Border(right: BorderSide(color: Colors.red, width: 5)),
child: ListTile(),
),
);
But I advise you to reduce the value of elevation because it is distorting the small circular borders.
For me, all the solutions using clipping cut off some of the shadow. Anyway, I found an easier solution imo:
Wrap the card's child around a Container widget. Specify the rounded rectangle border for the card, then the colored border side for the container.
Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
child: Container(
decoration: BoxDecoration(
border: Border(right: BorderSide(color: Colors.red, width: 8)
),
child: // your card content
)
)
Instead of using a Card you could also use a Container to achieve this, you can use the gradient property on BoxDecoration. The stops property is going to determine the width of your border. Then you can add your colors and have a nice border.
For the rounded edges you can just use the borderRadius property.
Container(
margin: EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 8.0,
),
padding: EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 12.0,
),
child: Text('A "card" with rounded edges and a border'),
decoration: BoxDecoration(
gradient: LinearGradient(
stops: [0.015, 0.015],
colors: [
Colors.blue,
Colors.white,
],
),
borderRadius: BorderRadius.all(
Radius.circular(5.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(0.0, 1.5),
),
],
),
)
Result from the code above
You can use the clipBehavior in the Card and move the BorderSide to a Container.
Card(
clipBehavior: Clip.antiAlias,
child: Container(
height: 100,
decoration: BoxDecoration(
border: Border(
right: BorderSide(color: Colors.green, width: 5))),
),
)
I need to add shadows to some icons in my flutter project. I've checked the icon class constructors but nothing points to that. Any idea on how to implement that?
I got what i wanted eventually using this workaround. I hope it helps whoever might need something similar.
Stack(
children: <Widget>[
Positioned(
left: 1.0,
top: 2.0,
child: Icon(icon, color: Colors.black54),
),
Icon(icon, color: Colors.white),
],
),
The Icon widget has a shadows property with which you can give shadows to an icon.
const Icon(
icon,
shadows: <Shadow>[Shadow(color: Colors.black, blurRadius: 15.0)],
size: 60,
color: Colors.white,
)
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 5.0,
),
]
),
child: Icon(
Icons.fiber_manual_record,
color: Colors.amber,
size:15,
)
),
You can use IconShadowWidget().
How to use:
1. add dependencies to pubspec.yaml:
icon_shadow: ^1.0.1
2. Import your Dart code :
import 'package:icon_shadow/icon_shadow.dart';
3. add icons:
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
),
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
shadowColor: Colors.black,
),
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
shadowColor: Colors.black,
showShadow: false,
),
],
),
),
You can also check my GitHub Repository
Whenever you need elevation/shadow, remember the Card widget. So, you can wrap it with Card and SizedBox:
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(35.0),
),
child: SizedBox(
width: 35,
height: 35,
child: Icon(
Icons.close,
color: Colors.black,
size: 19,
),
),
)
Even better, here is an icon button with material bubble effect + shadow (in below GIF, shadow's quality looks like bad, it is because of GIF itself)
:
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(35.0),
),
child: ClipOval(
child: Material(
color: Colors.transparent, // button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(
width: 35,
height: 35,
child: Icon(
Icons.close,
color: Colors.black,
size: 19,
),
),
onTap: () {},
),
),
),
)
Took the idea from #Dzeri answer (https://stackoverflow.com/a/55668093/414635) and encapsulated it into a Widget so it became reusable.
Widget
class ShadowIcon extends StatelessWidget {
final IconData icon;
final Color color;
ShadowIcon(this.icon, {Key key, this.color: kLight}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
left: 0.5,
top: 0.5,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 1.0,
sigmaY: 1.0,
),
child: FaIcon(this.icon, color: kDark.withOpacity(0.7)),
),
),
FaIcon(this.icon, color: color),
],
);
}
}
The BackdropFilter doesn't seem to be working as expected but anyway all I needed was a subtle drop shadow. I'm also using the package font_awesome_flutter but you can replace the FaIcon by the native Icon widget.
Usage
Your can simply replace the native Icon by the ShadowIcon widget call:
IconButton(
icon: ShadowIcon(FontAwesomeIcons.chevronLeft, color: kLight),
onPressed: () => Get.back(),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: .5,
),
]),
child: Icon(
Icons.clear,
color: Colors.black,
size: 25,
)),
),
result will be like this pic:
:
Right now, it's not possible to directly add shadows to an Icon widget. You can however use the additional information from your IconData icon to display the icon as a styled text.
Text(
String.fromCharCode(Icons.add.codePoint),
style: TextStyle(
fontFamily: Icons.add.fontFamily,
color: Colors.white,
fontSize: 20.0,
shadows: [
BoxShadow(
color: ColorTheme.blackLight,
spreadRadius: 2,
blurRadius: 2,
)
],
height: 1 //if this isn't set, the shadow will be cut off on the top and bottom
)
);
Try this, use the icon font.
GestureDetector(
child: Container(
padding: EdgeInsets.only(right: 10, top: 10),
child: Text('\u{e5d3}',
style: TextStyle(
fontSize: 22,
color: Colors.white,
fontFamily: 'MaterialIcons',
shadows: [
BoxShadow(color: Colors.black, blurRadius: 2)
])),
),
onTap: () {}
)
Icon data from icons.dart
/// <i class="material-icons md-36">more_horiz</i> — material icon named "more horiz".
static const IconData more_horiz = IconData(0xe5d3, fontFamily: 'MaterialIcons');
You can use decorated icon plugin to do shadow on icon
Code here :
Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DecoratedIcon(
Icons.android,
color: Colors.purple,
size: 60.0,
shadows: [
BoxShadow(
blurRadius: 42.0,
color: Colors.purpleAccent,
),
BoxShadow(
blurRadius: 12.0,
color: Colors.white,
),
],
),
DecoratedIcon(
Icons.favorite,
color: Colors.lightBlue.shade50,
size: 60.0,
shadows: [
BoxShadow(
blurRadius: 12.0,
color: Colors.blue,
),
BoxShadow(
blurRadius: 12.0,
color: Colors.green,
offset: Offset(0, 6.0),
),
],
),
DecoratedIcon(
Icons.fingerprint,
color: Colors.orange,
size: 60.0,
shadows: [
BoxShadow(
color: Colors.black,
offset: Offset(3.0, 3.0),
),
],
),
],
),
),
);
I know this is pretty late, but for anyone looking to add a shadow in circular form should wrap the icon with a CircleAvatar widget and set the backgroundColor proprety of CircleAvatar to Colors.grey.withOpacity (0.5) or to any other color for the shadow. Here's the code snippet
CircleAvatar (
bacgroundColor: Colors.grey.withOpacity (0.5),
child: Icon (
Icons.yourIcon
)
Material(
color: Colors.transparent,
elevation: 10,
child: Icon(
icons.add,
),
),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
boxShadow: const [
BoxShadow(color: Colors.grey, blurRadius: 1),
],
),
child: const Icon(
FontAwesomeIcons.checkCircle,
size: 30,
color: Colors.green,
),
),
If the container size is the same as the icon size, then 3 pixels will be always downward, This is because I don't know. but this solution will clear it.
Make sure that the container size will increase by 3 pixels with icons size.
Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
boxShadow: const [
BoxShadow(color: Colors.grey, blurRadius: 1),
]),
child: const Icon(
FontAwesomeIcons.checkCircle,
size: 30,
color: Colors.green,
),
),
base on this answer you can use this code and maybe add some change
import 'package:flutter/material.dart';
class IconShadowView extends Icon {
const IconShadowView(super.icon,
{super.key,
super.color,
super.semanticLabel,
super.shadows,
super.size,
super.textDirection});
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 1.0,
top: 2.0,
child: Icon(
icon,
color: Colors.black,
key: key,
semanticLabel: semanticLabel,
shadows: shadows,
size: size,
textDirection: textDirection,
),
),
super.build(context),
],
);
}
}
The red rectangle center of my widget is too big and is not responsive to width and height arguments.
I have updated flutter, and android studio. I started with a container in the shape of a circle then, I used a flatbutton and gave it a shape. but when it becomes the rectangle it is the same size as the circle it resizes in. _isRecord is a boolean that is toggled when the button is pressed.
return Container(
width: 80.0,
height: 80.0,
child: Container(
child: FlatButton(
onPressed: _press,
),
decoration: new BoxDecoration(
color: Colors.red,
shape: _isRecording ? BoxShape.rectangle : BoxShape.circle,
borderRadius: _isRecording ? BorderRadius.all(Radius.circular(8.0)) : null,
),
),
decoration: new BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
border: Border.all(width: 5.0, color: Colors.white),
),
);
It should look and function like the Voice Memos' record button. It should be a white circle stroke with a red center that when pressed becomes a smaller, rounded rectangle.
You can use your Widget inside Padding
exam:
InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () {
setState(() {
_isRecording = !_isRecording;
});
},
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(width: 5.0, color: Colors.white),
),
child: Padding(
padding: EdgeInsets.all(32.0),
child: Container(
width: 40.0,
height: 40.0,
child: Container(
decoration: new BoxDecoration(
color: Colors.red,
shape:
_isRecording ? BoxShape.rectangle : BoxShape.circle,
borderRadius: _isRecording
? BorderRadius.all(Radius.circular(8.0))
: null,
),
),
),
),
),
)
I have a bottom sheet in my page. I want to dismiss it when I click outside of it, how to achieve this?
I'm doing it like this:
return new Directionality(
textDirection: TextDirection.rtl,
child: new Theme(
data: theme,
child: new Scaffold(
bottomSheet: Container(
height: MediaQuery.of(context).size.height / 3 + 35,
color:
Color(0x00737373), // This line set the transparent background
child: Padding(
padding: EdgeInsets.only(right: 10.0, left: 10.0),
child: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
color: Color(0xcc2BA04F),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0))),
child: ....
)),
),
),
body:
...
If I touched outside the bottom sheet it will not dismiss by default. How to make it disappear when tapping outside of it?
Call showBottomSheet() to display the sheet.
void showBottomSheet() {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height / 3 + 35,
color: Color(0x00737373), // This line set the transparent background
child: Padding(
padding: EdgeInsets.only(right: 10.0, left: 10.0),
child: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(color: Color(0xcc2BA04F), borderRadius: BorderRadius.circular(20)),
),
),
);
},
);
}
I am using Flutter for my app development.
I would like to overlay a poster image view on top of a background image just like in this screenshot below.
The code snippet below does this, but it requires me to also position every other widget including the movie title, release date, etc based on poster's position and background image's position, which is not reliable across several devices and orientation. Is there an example or suggestion to solve this problem?
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new PlatformAdaptiveAppBar(
title: new Text(widget.movie.title),
),
body: new Container(
constraints: new BoxConstraints.expand(),
child: new Stack(
children: <Widget>[
new Container(
child: new Image(
image: new AdvancedNetworkImage(
movieGridUtil.getUrlFromPath(widget.movie.backdrop_path,
MovieGridImageTypes.BACKDROP),
useMemoryCache: false,
useDiskCache: true)),
constraints: new BoxConstraints.expand(height: 250.0),
),
new Positioned(
left: 12.0,
top: 220.0,
child: new Image(
width: 100.0,
height: 150.0,
image: new AdvancedNetworkImage(
movieGridUtil.getUrlFromPath(widget.movie.poster_path,
MovieGridImageTypes.POSTER),
useMemoryCache: false,
useDiskCache: true),
)),
],
)),
);
}
Create Stack
Then inside Stack add Column and make full layout without the poster.
Then as a second Child of Stack, add this combination:
new Stack(
children: [
new Column(
children: _layout()
new Positioned(
top:200,
left:50,
child: _child // or optionaly wrap the child in FractionalTranslation
)]
)
)
Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: 200.0,
),
Padding(
padding: const EdgeInsets.only(left: 20.0,right: 20.0, top:160.0),
child: Container(
color: Colors.pink,
height: 150.0,
width: 110.0,
),
)
],
),
By Creating the Stack,
You can add multiple Container, whichever is last added will be on the top.
Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: 200.0,
),
Padding(
padding: const EdgeInsets.only(left: 20.0,right: 20.0, top:160.0),
child: Container(
color: Colors.pink,
height: 150.0,
width: 110.0,
),
)
],
),