How can I create a circle outline with a shadow in Flutter? - flutter

I need a circular OutlinedButton with an elevation but that property is not available for that widget. I'm trying to create a circle outline with a shadow and wrap it in a GestureDetector to achieve the same behavior but all options that I have tried have the shadow all the way to the center of the circle or don't have any shadow in the inner part of the circle.
This is the output that I'm looking for:
How can I achieve this?

Try This Code:
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: IconButton(
onPressed: () {},
iconSize: 200,
icon: const Icon(
Icons.circle_outlined,
shadows: [Shadow(blurRadius: 70)],
),
color: Colors.blue,
),
),
);
}

you can use a standard OutlinedButton widget with a modified shape property:
class RingBorder extends CircleBorder {
const RingBorder({
this.thickness = 12,
this.color = Colors.blue,
this.shadowColor = Colors.black,
this.shadowRadius = 6,
this.paintShadowCounter = 1,
});
final double thickness;
final Color color;
final Color shadowColor;
final double shadowRadius;
final int paintShadowCounter;
#override
CircleBorder copyWith({BorderSide? side, double? eccentricity}) => this;
#override
void paint(ui.Canvas canvas, ui.Rect rect, {ui.TextDirection? textDirection}) {
final path = Path()
..fillType = PathFillType.evenOdd
..addOval(Rect.fromCircle(center: rect.center, radius: rect.shortestSide / 2 - shadowRadius))
..addOval(Rect.fromCircle(center: rect.center, radius: rect.shortestSide / 2 - shadowRadius - thickness));
final paint = Paint()..color = color;
canvas.drawPath(path, paint);
paint
..color = shadowColor
..maskFilter = MaskFilter.blur(BlurStyle.outer, shadowRadius);
for (int i = 0; i < paintShadowCounter; i++) {
canvas.drawPath(path, paint);
}
}
}
now you can use it as follows:
OutlinedButton(
style: ButtonStyle(
shape: MaterialStatePropertyAll(RingBorder(
color: Colors.orange,
paintShadowCounter: 4,
shadowRadius: 12,
)),
),
onPressed: () => print('pressed'),
child: Container(),
);
notice that all params are optional and contain some default values

you can take IconButton and take circle_outlined as icon and give shadow as per your need:
IconButton(
onPressed: () {},
iconSize: 50,
icon: const Icon(
Icons.circle_outlined,
shadows: [Shadow(blurRadius: 20)],
),
color: Colors.blue,
),

Try below code hope its help to you. I have try same like as your shared image
Container(
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(20),
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.transparent,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.9),
spreadRadius: 6, //change on your need
blurRadius: 10,
offset: const Offset(0, 3),
)
],
),
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
border: Border.all(color: Colors.blue, width: 5),
boxShadow: const [
BoxShadow(
color: Colors.black26,
),
BoxShadow(
color: Colors.white,
spreadRadius: -10.0, //change on your need
blurRadius: 12.0,
),
],
),
),
),
),
Result->

wrap the OutlinedButton in a Container and apply a BoxShadow to the Container.
GestureDetector(
onTap: () {},
child: Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10.0,
offset: Offset(0, 10),
),
],
),
child: OutlinedButton(
onPressed: () {},
child: Text("Button"),
),
),
)

Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: InkWell(
onTap: () {},
child: Container(
height: 150,
width: 150,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
border: Border.all(
color: Color(0xff00AEEF),
width: 3.w),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.9),
spreadRadius: 4,
blurRadius: 10,
offset: Offset(0, 3),
)
]),
child: OutlinedButton(
onPressed: () {},
child: Text("You can add Text and icon"),
),
),
),
);
}

Related

How to create a custom border for container in Flutter?

I tried to put a border to a container like this code:
Container(
padding: EdgeInsets.all(15.sp),
decoration: BoxDecoration(
// color: Colors.yellow,
border: Border.all(
color: kPrimaryColor,
width: 7,
style: BorderStyle.solid,
),
),
child: QrImage(
data: controller.generatedCode,
version: QrVersions.auto,
size: 300.0,
),
),
The code above gives me a complete border
the border of the QR code, I want to implement a border like it
Try this. It will work.
Container(
child: Text(
'This is a Container',
textScaleFactor: 2,
style: TextStyle(color: Colors.black),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.green, spreadRadius: 3),
],
),
height: 50,
),
I found it, using dotted_border package:
Widget get customBorder {
Path customPath = Path()
..moveTo(0, 0)
..lineTo(0, 25)
..moveTo(0,0)
..lineTo(25, 0)
..moveTo(75,0)
..lineTo(100,0)
..lineTo(100,25)
..moveTo(0,75)
..lineTo(0, 100)
..lineTo(25, 100)
..moveTo(100,75)
..lineTo(100, 100)
..lineTo(75,100)
;
return DottedBorder(
customPath: (_) => customPath,
color: Colors.indigo,
dashPattern: [1, 1],
strokeWidth: 2,
child: Container(
height: 100,
width: 100,
color: Colors.green.withAlpha(20),
),
);
}

Flutter - How can I make these Containers to work like a Button?

This is my first App and my first steps in programming. I started with designing the Homepage. Now I want the Containers to act like Buttons, so that I can navigate to other pages. I just can't figure out a way to do so. Maybe u guys got some ideas.
Do i have to delete the 5 Containers and add 5 buttons and redesign them?
I Think there might be a problem since I wrote the buttons as widget?
The Code so far:
//import 'dart:html';
import 'package:apptierpark/Anfahrt.dart';
import 'package:flutter/material.dart';
void main () => runApp(MaterialApp(home: Tierpark()));
class Tierpark extends StatelessWidget {
get assets => null;
get image => null;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(60.0),
child: AppBar(
title: Text('Tierpark Marzahne',
style: TextStyle (
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 45,
fontFamily: 'Amatic',
shadows: [
Shadow(
blurRadius: 10.0,
color: Colors.white,
offset: Offset(5.0, 5.0),
)
]
)),
flexibleSpace: Image(
image: AssetImage('images/urwald4.jpg'),
fit: BoxFit.fill,
),
backgroundColor: Colors.transparent,
),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('images/bamboo.jpg'), fit: BoxFit.fill)),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:
<Widget>[
MenuButton2('Bewohner',),
SizedBox(height: 50),
MenuButton2('Parkplan'),
SizedBox(height: 40),
MenuButton2('Zeiten & Preise'),
SizedBox(height: 40),
MenuButton2('Anfahrt'),
SizedBox(height: 40),
MenuButton2 ('Über Uns')
]
,)
,)
)
);
}
}
//Button Mainpage Neu
class MenuButton2 extends StatelessWidget {
final String title;
const MenuButton2(this.title);
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: const Color(0xFFa9d470),
border: Border.all(
color: const Color(0xFFa9d470)
),
borderRadius: BorderRadius.all(Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.9),
spreadRadius: 10,
blurRadius: 12
)
]
),
width: MediaQuery.of(context).size.height*0.38,
height: MediaQuery.of(context).size.height*0.11,
child: Align(
alignment: Alignment.center,
child: Text (title,
style: TextStyle(
fontSize: 50,
fontFamily: 'Amatic',
fontWeight: FontWeight.bold
),))
);
}
}
Wrap the Container with GestureDetector or InkWell like this and call functions with it's properties,
class MenuButton2 extends StatelessWidget {
final String title;
final int buttonId;
const MenuButton2(this.title,this.buttonId);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
if(buttonId == 1){
// do 1
}
else if(buttonId == 2){
// do 2
}
else if(buttonId == 3){
// do 3
}
else if(buttonId == 4){
// do 4
}
else {
// do 5
}
},
child:Container(
decoration: BoxDecoration(
color: const Color(0xFFa9d470),
border: Border.all(
color: const Color(0xFFa9d470)
),
borderRadius: BorderRadius.all(Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.9),
spreadRadius: 10,
blurRadius: 12
)
]
),
width: MediaQuery.of(context).size.height*0.38,
height: MediaQuery.of(context).size.height*0.11,
child: Align(
alignment: Alignment.center,
child: Text (title,
style: TextStyle(
fontSize: 50,
fontFamily: 'Amatic',
fontWeight: FontWeight.bold
),
),
),
);
}
And in the place where you call the function do this,
...
<Widget>[
MenuButton2('Bewohner', 1),
SizedBox(height: 50),
MenuButton2('Parkplan', 2),
SizedBox(height: 40),
MenuButton2('Zeiten & Preise', 3),
SizedBox(height: 40),
MenuButton2('Anfahrt', 4),
SizedBox(height: 40),
MenuButton2 ('Über Uns', 5)
],
...
Add your Container inside Inkwell or GestureDetector Widgtes refer below code hope its help to you.
Inkwell Widget
GestureDetector Widgets
// GestureDetector( you use GestureDetector also here instead of InkWell Widgets
InkWell(
onTap: () {
print('button Pressed');
// Call your onPressed or onTap function here
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(30),
),
),
height: 50,
width: 200,
child: Text(
'Search',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
Your result screen ->

Change the fill color of the container from left to right in Flutter

I am trying to change the color of a container from say white to red. But I want to do it from left to right that is, from the left of the container the color red starts filling up and expands all the way to the right in some duration. I know animated container will change the color but it seems to change the color of the entire container and not how I want it to
Like the 'Next Episode' of Netflix
You could use the Stack Widget and use an AnimatedContainer in between the background container (grey) and the foreground container (displaying icon & text):
class NetflixCustomButton extends StatefulWidget {
final Duration animationDuration;
final double height;
final double width;
final double borderRadius;
const NetflixCustomButton({
this.animationDuration = const Duration(milliseconds: 800),
this.height = 30,
this.width = 130.0,
this.borderRadius = 10.0,
});
#override
_NetflixCustomButtonState createState() =>
_NetflixCustomButtonState();
}
class _NetflixCustomButtonState
extends State<NetflixCustomButton> {
double _animatedWidth = 0.0;
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
widget.borderRadius,
),
color: Colors.grey,
),
),
AnimatedContainer(
duration: widget.animationDuration,
height: widget.height,
width: _animatedWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
widget.borderRadius,
),
color: Colors.white,
),
),
InkWell(
child: Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
widget.borderRadius,
),
color: Colors.transparent,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
Icons.play_arrow,
color: Colors.black87,
),
Text(
'Next Episode',
style: TextStyle(
color: Colors.black87,
),
),
],
),
),
onTap: () {
setState(() {
_animatedWidth = widget.width;
});
},
),
],
);
}
}

Is there a way to create a button with corner radius, gradient, and with dynamic shadows?

I'm creating a button with corner radius and gradient, but I also want its shadows to react on user press and release. I'm trying out a Container with decoration but no luck since I can't seem to find an onRelease callback. So I'm thinking that I'm on the wrong direction. So is there any way to do this?
This button has exactly what I need:
A gradient, rounded corners, dynamic shadows, ripple effectPadding(
padding: const EdgeInsets.only(bottom: 50),
child: Transform.scale(
scale: btnScale,
child: GestureDetector(
onTapCancel: () {
setState(() {});
btnHeight = 5;
btnScale = 1.0;
},
onTapDown: (loc) {
btnHeight = 0;
btnScale = 0.99;
setState(() {});
},
onTapUp: (loc) {
setState(() {});
btnHeight = 5;
btnScale = 1.0;
},
child: Container(
width: 190,
height: 62,
decoration: BoxDecoration(
boxShadow: [
new BoxShadow(
blurRadius: 4,
color: Colors.black12,
offset: new Offset(
-btnHeight, btnHeight),
),
new BoxShadow(
blurRadius: 4,
color: Colors.black12,
offset: new Offset(
btnHeight, btnHeight),
)
],
borderRadius: BorderRadius.all(
Radius.circular(100)),
gradient: BtnTeal),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
(BorderRadius.circular(100)),
onTap: () {},
highlightColor:
const Color(0xFF63DCA0),
splashColor: Colors.teal,
child: Center(
child: Text(
"LOG IN",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 21,
),
),
),
),
),
),
),
),
),

How to create a circle icon button in Flutter?

How can I create something similar to a FloatingActionButton?
RawMaterialButton is better suited I think.
RawMaterialButton(
onPressed: () {},
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
Update (use new ElevatedButton)
ElevatedButton (with less customizations)
ElevatedButton(
onPressed: () {},
child: Icon(Icons.menu, color: Colors.white),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(20),
backgroundColor: Colors.blue, // <-- Button color
foregroundColor: Colors.red, // <-- Splash color
),
)
ElevatedButton (with more customizations)
ElevatedButton(
onPressed: () {},
child: Icon(Icons.menu),
style: ButtonStyle(
shape: MaterialStateProperty.all(CircleBorder()),
padding: MaterialStateProperty.all(EdgeInsets.all(20)),
backgroundColor: MaterialStateProperty.all(Colors.blue), // <-- Button color
overlayColor: MaterialStateProperty.resolveWith<Color?>((states) {
if (states.contains(MaterialState.pressed)) return Colors.red; // <-- Splash color
}),
),
)
Using InkWell
ClipOval(
child: Material(
color: Colors.blue, // Button color
child: InkWell(
splashColor: Colors.red, // Splash color
onTap: () {},
child: SizedBox(width: 56, height: 56, child: Icon(Icons.menu)),
),
),
)
Output (same for the last two):
You just need to use the shape: CircleBorder()
MaterialButton(
onPressed: () {},
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
)
You can use InkWell to do that:
A rectangular area of a Material that responds to touch.
Below example demonstrate how to use InkWell. Notice: you don't need StatefulWidget to do that. I used it to change the state of the count.
Example:
import 'package:flutter/material.dart';
class SettingPage extends StatefulWidget {
#override
_SettingPageState createState() => new _SettingPageState();
}
class _SettingPageState extends State<SettingPage> {
int _count = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new InkWell(// this is the one you are looking for..........
onTap: () => setState(() => _count++),
child: new Container(
//width: 50.0,
//height: 50.0,
padding: const EdgeInsets.all(20.0),//I used some padding without fixed width and height
decoration: new BoxDecoration(
shape: BoxShape.circle,// You can use like this way or like the below line
//borderRadius: new BorderRadius.circular(30.0),
color: Colors.green,
),
child: new Text(_count.toString(), style: new TextStyle(color: Colors.white, fontSize: 50.0)),// You can add a Icon instead of text also, like below.
//child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
),//............
),
),
);
}
}
If you want to get benefit of splashColor, highlightColor, wrap InkWell widget using a Material widget with material type circle. And then remove decoration in Container widget.
Outcome:
If you need a background image, you can use CircleAvatar with IconButton. Set the backgroundImage property.
CircleAvatar(
backgroundImage: NetworkImage(userAvatarUrl),
)
Example with button:
CircleAvatar(
backgroundColor: Colors.blue,
radius: 20,
child: IconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () {},
),
),
You can easily do the following:
FlatButton(
onPressed: () {
},
child: new Icon(
Icons.arrow_forward,
color: Colors.white,
size: 20.0,
),
shape: new CircleBorder(),
color: Colors.black12,
)
The result is
RaisedButton is depricated,
now you can create this by ElevatedButton.
ElevatedButton(
onPressed: () {},
child: Icon(Icons.add, color: Colors.white),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(20),
primary: Colors.blue,
onPrimary: Colors.black,
),
)
RawMaterialButton(
onPressed: () {},
constraints: BoxConstraints(),
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
note down constraints: BoxConstraints(), it's for not allowing padding in left.
Happy fluttering!!
There actually is an example how to create a circle IconButton similar to the FloatingActionButton.
Ink(
decoration: const ShapeDecoration(
color: Colors.lightBlue,
shape: CircleBorder(),
),
child: IconButton(
icon: Icon(Icons.home),
onPressed: () {},
),
)
To create a local project with this code sample, run:
flutter create --sample=material.IconButton.2 mysample
Using ElevatedButton:
ElevatedButton(
onPressed: () {},
child: Icon(
Icons.add,
color: Colors.white,
size: 60.0,
),
style: ElevatedButton.styleFrom(
shape: CircleBorder(), primary: Colors.green),
)
2021
If you need it flat (no elevation) as FlatButton is now deprecated.
TextButton(
onPressed: (){},
child: Icon(Icons.arrow_back),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black26),
shape: MaterialStateProperty.all(const CircleBorder())),
);
I created a version with correct clipping, elevation and border. Feel free to customize it.
Material(
elevation: 2.0,
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(50),
color: Colors.white,
child: InkWell(
onTap: () => null,
child: Container(
padding: EdgeInsets.all(9.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue, width: 1.4)),
child: Icon(
Icons.menu,
size: 22,
color: Colors.red,
),
),
),
)),
I used this one because I like the customisation of the border-radius and size.
Material( // pause button (round)
borderRadius: BorderRadius.circular(50), // change radius size
color: Colors.blue, //button colour
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 35,height: 35, //customisable size of 'button'
child: Icon(Icons.pause,color: Colors.white,size: 16,),
),
onTap: () {}, // or use onPressed: () {}
),
),
Material( // eye button (customised radius)
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomLeft: Radius.circular(50.0),),
color: Colors.blue,
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 40, height: 40, //customisable size of 'button'
child: Icon(Icons.remove_red_eye,color: Colors.white,size: 16,),),
onTap: () {}, // or use onPressed: () {}
),
),
There are many ways to create the circle icon button in Flutter. Each of the examples below will use a different method.
Using ElevatedButton + Icon (recommended)
Using MaterialButton
ClipOval + Material + InkWell + Padding + Icon
IconButton + CircleAvatar
Ink + IconButton
Using ElevatedButton + Icon
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
padding: const EdgeInsets.all(30)
),
child: const Icon(
Icons.add,
size: 50,
),
onPressed: () {},
),
Output:
Using MaterialButton
MaterialButton(
shape: const CircleBorder(),
color: Colors.red,
padding: const EdgeInsets.all(20),
onPressed: () {},
child: const Icon(
Icons.star,
size: 50,
color: Colors.yellow,
),
)
Output:
ClipOval + Material + InkWell + Padding + Icon
ClipOval(
child: Material(
color: Colors.blue,
child: InkWell(
onTap: () {},
child: const Padding(
padding: EdgeInsets.all(20),
child: Icon(
Icons.plus_one,
size: 50,
color: Colors.white,
),
),
),
),
)
Output:
IconButton + CircleAvatar
CircleAvatar(
radius: 50,
backgroundColor: Colors.amber,
child: IconButton(
color: Colors.black,
padding: const EdgeInsets.all(20),
iconSize: 50,
icon: const Icon(Icons.shop),
onPressed: () {
// do something
}),
),
Output:
Ink + IconButton
Ink(
decoration:
const ShapeDecoration(
shape: CircleBorder(),
color: Colors.purple
),
child: IconButton(
icon: const Icon(Icons.arrow_back),
iconSize: 30,
color: Colors.white,
onPressed: () {},
),
)
Output:
My contribution:
import 'package:flutter/material.dart';
///
/// Create a circle button with an icon.
///
/// The [icon] argument must not be null.
///
class CircleButton extends StatelessWidget {
const CircleButton({
Key key,
#required this.icon,
this.padding = const EdgeInsets.all(8.0),
this.color,
this.onPressed,
this.splashColor,
}) : assert(icon != null),
super(key: key);
/// The [Icon] contained ny the circle button.
final Icon icon;
/// Empty space to inscribe inside the circle button. The [icon] is
/// placed inside this padding.
final EdgeInsetsGeometry padding;
/// The color to fill in the background of the circle button.
///
/// The [color] is drawn under the [icon].
final Color color;
/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this callback is null, then the button will be disabled.
final void Function() onPressed;
/// The splash color of the button's [InkWell].
///
/// The ink splash indicates that the button has been touched. It
/// appears on top of the button's child and spreads in an expanding
/// circle beginning where the touch occurred.
///
/// The default splash color is the current theme's splash color,
/// [ThemeData.splashColor].
final Color splashColor;
#override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
return ClipOval(
child: Material(
type: MaterialType.button,
color: color ?? theme.buttonColor,
child: InkWell(
splashColor: splashColor ?? theme.splashColor,
child: Padding(
padding: padding,
child: icon,
),
onTap: onPressed,
),
),
);
}
}
This code will help you to add button without any unwanted padding,
RawMaterialButton(
elevation: 0.0,
child: Icon(Icons.add),
onPressed: (){},
constraints: BoxConstraints.tightFor(
width: 56.0,
height: 56.0,
),
shape: CircleBorder(),
fillColor: Color(0xFF4C4F5E),
),
Not Material solution:
final double floatingButtonSize = 60;
final IconData floatingButtonIcon;
TouchableOpacity(
onTap: () {
/// Do something...
},
activeOpacity: 0.7,
child: Container(
height: floatingButtonSize,
width: floatingButtonSize,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(floatingButtonSize / 2),
color: Theme.of(context).primaryColor,
boxShadow: [
BoxShadow(
blurRadius: 25,
color: Colors.black.withOpacity(0.2),
offset: Offset(0, 10),
)
],
),
child: Icon(
floatingButtonIcon ?? Icons.add,
color: Colors.white,
),
),
)
You can use GestureDetector instead of TouchableOpacity library.
You can also use a RaisedButton with an image inside (for example for social login) like this (sizedbox with fittebox is needed to contraint the image on the specified size):
FittedBox(
fit: BoxFit.scaleDown,
child: SizedBox(
height: 60,
width: 60,
child: RaisedButton(
child: Image.asset(
'assets/images/google_logo.png'),
shape: StadiumBorder(),
color: Colors.white,
onPressed: () {},
),
),
),
ClipOval(
child: MaterialButton(
color: Colors.purple,
padding: EdgeInsets.all(25.0),
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
child: Text(
'1',
style: TextStyle(fontSize: 30.0),
),
),
),
Below code will create a Circle of radius 25 and will have white color add icon in it. and If user also want to have click method that can be simply achieved by wrapping a Container widget into GestureDetector() or InkWell().
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(50 / 2),
),
child: Center(
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
Just use the circle shape
MaterialButton(
onPressed: () {
print("Circle button pressed");
},
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.favorite,
size: 20,
),
padding: EdgeInsets.all(16),
//use this class Circleborder() for circle shape.
shape: const CircleBorder(),
)
Material 3 / Flutter 3.7.0-
Here is a CircleIconButton widget supporting standard, filled, filled tonal and outlined types from Material 3, as described in https://m3.material.io/components/icon-buttons/overview. The widget supports also toggle feature and enabled/disabled states.
import 'package:flutter/material.dart';
enum CircleIconButtonStyle {
standard,
filled,
filledTonal,
outlined,
}
class CircleIconButton extends StatelessWidget {
const CircleIconButton({
super.key,
required this.icon,
this.circleIconButtonStyle = CircleIconButtonStyle.filled,
required this.onPressed,
this.isSelected,
this.selectedIcon,
});
final IconData icon;
final CircleIconButtonStyle circleIconButtonStyle;
final VoidCallback? onPressed;
/// For toggle buttons
final bool? isSelected;
final Widget? selectedIcon;
#override
Widget build(BuildContext context) {
final ColorScheme colors = Theme.of(context).colorScheme;
return IconButton(
onPressed: onPressed,
icon: Icon(icon),
isSelected: isSelected,
selectedIcon: selectedIcon,
style: _CircleIconButtonStyleProvider.getStyle(
circleIconButtonStyle: circleIconButtonStyle,
isEnabled: onPressed != null,
isSelected: isSelected == true,
colors: colors),
);
}
}
// adapted from samples at https://api.flutter.dev/flutter/material/IconButton-class.html
class _CircleIconButtonStyleProvider {
static ButtonStyle? getStyle({
required CircleIconButtonStyle circleIconButtonStyle,
required bool isEnabled,
required bool isSelected,
required ColorScheme colors,
}) {
switch (circleIconButtonStyle) {
case CircleIconButtonStyle.standard:
return null;
case CircleIconButtonStyle.filled:
return isEnabled
? _enabledFilledButtonStyle(isSelected, colors)
: _disabledFilledButtonStyle(isSelected, colors);
case CircleIconButtonStyle.filledTonal:
return isEnabled
? _enabledFilledTonalButtonStyle(isSelected, colors)
: _disabledFilledTonalButtonStyle(isSelected, colors);
case CircleIconButtonStyle.outlined:
return isEnabled
? _enabledOutlinedButtonStyle(isSelected, colors)
: _disabledOutlinedButtonStyle(isSelected, colors);
}
}
static ButtonStyle _enabledFilledButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
foregroundColor: selected ? colors.onPrimary : colors.primary,
backgroundColor: selected ? colors.primary : colors.surfaceVariant,
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
hoverColor: selected
? colors.onPrimary.withOpacity(0.08)
: colors.primary.withOpacity(0.08),
focusColor: selected
? colors.onPrimary.withOpacity(0.12)
: colors.primary.withOpacity(0.12),
highlightColor: selected
? colors.onPrimary.withOpacity(0.12)
: colors.primary.withOpacity(0.12),
);
}
static ButtonStyle _disabledFilledButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}
static ButtonStyle _enabledFilledTonalButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
foregroundColor:
selected ? colors.onSecondaryContainer : colors.onSurfaceVariant,
backgroundColor:
selected ? colors.secondaryContainer : colors.surfaceVariant,
hoverColor: selected
? colors.onSecondaryContainer.withOpacity(0.08)
: colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected
? colors.onSecondaryContainer.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected
? colors.onSecondaryContainer.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
);
}
static ButtonStyle _disabledFilledTonalButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}
static ButtonStyle _enabledOutlinedButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
backgroundColor: selected ? colors.inverseSurface : null,
hoverColor: selected
? colors.onInverseSurface.withOpacity(0.08)
: colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected
? colors.onInverseSurface.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected
? colors.onInverseSurface.withOpacity(0.12)
: colors.onSurface.withOpacity(0.12),
side: BorderSide(color: colors.outline),
).copyWith(
foregroundColor:
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return colors.onInverseSurface;
}
if (states.contains(MaterialState.pressed)) {
return colors.onSurface;
}
return null;
}),
);
}
static ButtonStyle _disabledOutlinedButtonStyle(
bool selected,
ColorScheme colors,
) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor:
selected ? colors.onSurface.withOpacity(0.12) : null,
side:
selected ? null : BorderSide(color: colors.outline.withOpacity(0.12)),
);
}
}
Try out this Card
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0), // half of height and width of Image
),
child: Image.asset(
"assets/images/home.png",
width: 50,
height: 50,
),
)
Card(
elevation: 4.0,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(150),
),
child: InkWell(
onTap: (){},
child: Container(
width: 40,
height: 40,
padding: const EdgeInsets.all(3.0),
decoration: const BoxDecoration(
shape: BoxShape.circle, color: backGroundColor),
child: Image.asset(imageUrl)),
)),
Container(
width: 70.w,
height: 70.h,
alignment: AlignmentDirectional.topCenter,
child: MaterialButton(
onPressed: () {},
color: Color(0xff022C43),
textColor: Colors.white,
child: Icon(
Icons.arrow_forward,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
)
)