Place an icon on the buttom right of a Container - flutter

I have a Widget to creat a circular container. I want to place an icon on the buttom right, so I tried to use Positioned to place it where I want but its not moving. Its fixed on the center on the container.
Widget buildImage() {
return Center(
child: Container(
child: Material(
child: InkWell(
customBorder: CircleBorder(),
onTap: (){},
child: Container(
width: 150.0,
height: 150.0,
child: Positioned(
bottom: 4,
right: 0,
child: Icon (Icons.account_circle_rounded),
),
),
),
color: Colors.transparent,
),
decoration: BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
),
);
}
What am I doing wrong here?
Your answers are highly appreciated.

Positioned is used only in Stack widget. So if you want to position your icon inside Container, you can use Align widget, withPadding which will create desired behavior specified before in Positioned.
Somehow like this:
...
Container(
width: 150.0,
height: 150.0,
child: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 4.0),
child: Icon(
Icons.account_circle_rounded,
),
),
),
),
...

Container has align property you can use that or instead of Positined you can use Alignment Widget for Aligning your widget

For more control over postioning, just change the padding values.
Center(
child: Container(
child: Material(
child: InkWell(
customBorder: CircleBorder(),
onTap: () {},
child: Container(
width: 150.0,
height: 150.0,
child: Container(
padding: EdgeInsets.only(
right: 20, bottom: 10),
alignment: Alignment.bottomRight,
child: Icon(
Icons.account_circle_rounded),
),
),
),
color: Colors.transparent,
),
decoration: BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
),
),

Related

Flutter how to create circular border around icon and align an image top of the circular border

I am trying to use the below code to create a circular border around an image and align an icon on top of the circular border. What I am looking at is as the image below:
And my code is as below but it didn't work out perfectly:
Stack(
children: [
CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
child: Container(
padding: EdgeInsets.all(2),
child: CircleAvatar(
radius: 70,
backgroundImage: AssetImage('assets/person_icon.png'),
backgroundColor: Colors.white,
//
)),
),
Positioned(
bottom: 100,
right: 50,
child: InkWell(
onTap: () {},
child: Container(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(Icons.add_a_photo, color: colorBlue),
),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Colors.white,
),
borderRadius: BorderRadius.all(
Radius.circular(
50,
),
),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(2, 4),
color: Colors.black.withOpacity(
0.3,
),
blurRadius: 3,
),
]),
),
)),
],
),
As you can above I am trying to use stack to lay each widget on top of each other but couldn't achieve that. I don't if anyone can help out where I missed it or give me a good idea of how to come about this.
Thanks in advance.
Default clipBehavior on Stack is hardEdge.
Use clipBehavior: Clip.none on Stack.
And to have circle shape
use customBorder: CircleBorder(), on InkWell.
use shape: BoxShape.circle instead of circular radius on container.
For better alignment use
Positioned(
top: -12,//half of icon size
left: 0,
right: 0,
Also better providing size on Stack like here.
/// fixing top widget size
SizedBox.square(
dimension: squareSize,
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
clipBehavior: Clip.hardEdge,
decoration: const ShapeDecoration(
shape: CircleBorder(),
),
child: Image.asset(
'assets/images/image01.png',
fit: BoxFit.cover,
),
),
),
),
///background circle, you also do it on image widget
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(width: 5, color: Colors.green),
),
),
Positioned(
top: -12, // half of icon size
left: 0,
right: 0,
child: InkWell(
onTap: () {},
customBorder: const CircleBorder(),
child: Container(
width: 24 + 12, //icon size+padding
height: 24 + 12,
alignment: Alignment.center,
decoration: const ShapeDecoration(
shape: CircleBorder(),
color: Colors.green,
),
child: Icon(
Icons.add_a_photo,
color: Colors.white,
),
),
),
),
],
),
)
Play with sizes and decoration
Just add to the Stack Widget the Property clipBehavior: Clip.none,.
The clipBehavior will befine how to handle the Clip of the Stack Widget. Standard is hardEdge and cuts your icon off.
So your finished working Code is
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
child: Container(
padding: EdgeInsets.all(2),
child: CircleAvatar(
radius: 70,
backgroundImage: AssetImage('assets/person_icon.png'),
backgroundColor: Colors.white,
//
),
),
),
Positioned(
bottom: 100,
right: 50,
child: InkWell(
onTap: () {},
child: Container(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(Icons.add_a_photo, color: Colors.blue),
),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Colors.white,
),
borderRadius: BorderRadius.all(
Radius.circular(
50,
),
),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(2, 4),
color: Colors.black.withOpacity(
0.3,
),
blurRadius: 3,
),
],
),
),
),
),
],
),
),
);
}
}
void main() {
runApp(
const MaterialApp(
home: MyApp(),
),
);
}
Try below code
Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 25),
child: Container(
padding: EdgeInsets.all(8),
height: 270,
width: 270,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
child: Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ClipOval(
child: Container(
height: 250,
width: 250,
child: Image.network(
'https://miro.medium.com/max/1400/1*-6WdIcd88w3pfphHOYln3Q.png',
fit: BoxFit.cover,
),
),
),
),
),
),
Positioned(
top: 0,
left: .0,
right: .0,
child: Center(
child: CircleAvatar(
backgroundColor: Colors.green,
radius: 30.0,
child: Icon(
Icons.check,
color: Colors.white,
size: 40,
),
),
),
)
],
),
Result Screen->
user this below code to achieve
Center(
child: Stack(
children: [
Container(
height: 200,
child: CircleAvatar(
radius: 75,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 70,
backgroundColor: Colors.white,
child: Container(
padding: EdgeInsets.all(2),
child: const CircleAvatar(
radius: 60,
backgroundImage: NetworkImage("https://helostatus.com/wp-content/uploads/2021/09/pic-for-WhatsApp-HD.jpg"),
backgroundColor: Colors.white,
//
)),
),
),
),
Positioned(
left: 16,
right: 16,
top: 8,
child: InkWell(
onTap: () {},
child: const CircleAvatar(
backgroundColor: Colors.green,
radius: 16,
child: Icon(
Icons.check,
color: Colors.white,
),
)),
),
],
),
)[enter image description here][1]
Thanks all for the contribution but here is what works perfectly for what I'm looking at. I added clipBehavior and set Clip to noneclipBehavior: Clip.none, added ClipOval in a Container and set it margin and padding respectively to give the space between the green circular border and the profile image. I also, added another Container inside my ClipOval so as to add my image as a child to it. Find below my final code:
Center(
child: Stack(
clipBehavior: Clip.none,
children: [
CircleAvatar(
radius: 60,
backgroundColor: colorGreen,
child:Container(
padding: EdgeInsets.all(4),
margin: EdgeInsets.all(3),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ClipOval(
child: Container(
height: 250,
width: 250,
child: Image.network(
'my image link',
fit: BoxFit.cover,
),
),
)
)),
Positioned(
bottom: 100,
right: 45,
child: InkWell(
onTap: () {},
child: Center(
child: CircleAvatar(
backgroundColor: colorGreen,
radius: 15.0,
child: Icon(
Icons.check,
color: Colors.white,
size: 25,
),
),
),
),
),
],
),
),

making the circular avatar show at the top of the screen

How can I make the circleavatar to be placed at the top of the container
you can use Stack for this. like:
...
return Stack(
children: [
Positioned.filled( child:
Scaffold(
appBar: ...
body: Column([
DecoratedBox(
...
)
]),
)),
Positioned(
top: 24,
child:
CircleAvatar( child:
CachedNetworkImage(
...
),
),
),
],
);
something like that.
Try below code hope its helpful to you.refer Stack class here
Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 21),
child: Container(
height: 200,
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Colors.white,
margin: EdgeInsets.all(
16,
),
),
),
),
Container(
width: 100,
height: 90,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.transparent,
),
child: CircleAvatar(),
)
],
),
Your result screen->

Multiple child in flutter

i want to add another MaterialButton under the first one.
I got the first Button and a want to add multiple ones.
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(top: 15, bottom: 0, left: 5, right: 5),
child: MaterialButton(
onPressed: () {},
child: Container(
height: 180,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(20.0),
),),)
You can create the buttons inside the Expanded widget to allocate space evenly within a Row
body: return SingleChildScrollView (
child: Padding(
padding: EdgeInsets.only(top: 15, bottom: 0, left: 5, right: 5),
child: Row(
children: [
Expanded(
child: MaterialButton(
onPressed: () {},
child: Container(
height: 180,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(20.0),
),
)
),
),
Expanded(
child: MaterialButton(
onPressed: () {},
child: Container(
height: 180,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(20.0),
),
)
),
),
Expanded(
child: MaterialButton(
onPressed: () {},
child: Container(
height: 180,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(20.0),
),
)
),
),
],
),
)
);
If you want to Add Multiple Buttons and if you want to align them horizontally, then enclose the buttons inside a Row Widget. If you want to Align them Vertically, Enclose them inside a Column Widget.
If you want to have both Horizontally and Vertically aligned Make the Parent Widget as Column and have multiple children of Row Widgets and The Row can have Buttons as children

Splash color is not visible while I am using it in my Custom ModalBottomSheet

I am not getting splash effect when my Inkwell is inside showModalBottomsheet while it is customized, I wanted the rounded corners, so I hide the background color to transparent, when the background color is in white, the splash effect works fine. I tried playing with Alpha and Opacity properties, but no luck there.
questionEditAndDelete(BuildContext context) {
return showModalBottomSheet(
context: context,
elevation: 0,
backgroundColor: Colors.transparent,
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height * 0.15,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(25), topLeft: Radius.circular(25)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.only(bottom:20.0),
child: Divider(
indent: 110,
endIndent: 110,
thickness: 4,
color: Colors.grey,
),
),
InkWell(
onTap: (){},
splashColor: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(15)),
child: Container(
height: MediaQuery.of(context).size.height*0.05,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal:4.0),
child: Icon(EvaIcons.editOutline, size: 26,),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal:2.0),
child: Text('Edit', style: TextStyle(fontSize: 18),),
)
],
),
),
),
InkWell(
onTap: (){},
splashColor: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(15)),
child: Container(
height: MediaQuery.of(context).size.height*0.05,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal:4.0),
child: Icon(Icons.delete_outline_outlined, size: 26,),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal:2.0),
child: Text('Delete', style: TextStyle(fontSize: 18),),
)
],
),
),
),
]),
);
});
}```
Yes you are right so available alternate options are
Replace InkWell with Gesture Detector
Remove splash color of InkWell or set splash color to Colors.Transparent

Flutter container width inside MaterialButton

I am trying for hours to set my container width to its parent, which is a MaterialButton. I want the container to fill the entire width of the MaterialButton.
I tried to set the container width to "double.infitiy" or to "MediaQuery.of(context).size.width". Also played with "Expanded" etc. None of it worked. Not sure what I am doing wrong, thanks.
#override
Widget build(BuildContext context) {
return Material(
**child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
onPressed: onPressed,
child: Container(
width: double.infinity,**
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.greenAccent,
borderRadius: BorderRadius.circular(10.0)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(text),
SizedBox(
height: 8.0,
),
SvgPicture.asset(
'images/medaillen.svg',
width: 80,
),
SizedBox(
height: 15.0,
),
Text(
textTopThree,
maxLines: 3,
),
],
),
),
),
);
I recommend you to replace the Material Button with InkWell, you can wrap any widget and get the onTap.
This should work:
InkWell(
onTap: () {},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.greenAccent,
borderRadius: BorderRadius.circular(10.0),
),
child: Column(
children: [
Text('Button Text'),
SizedBox(
height: 8.0,
),
Image.asset(
'images/medaillen.svg',
width: 80,
),
SizedBox(
height: 15.0,
),
Text(
'textTopThree',
maxLines: 3,
),
],
),
),
),
If for some reason you need to use MaterialButton, then you should delete the Container and use the properties of the Material Button, like this:
MaterialButton(
onPressed: () {},
color: Colors.greenAccent,
minWidth: double.infinity,
padding: EdgeInsets.all(8.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
child: Column(
children: [
SizedBox(
height: 8.0,
),
Text('Button Text'),
SizedBox(
height: 8.0,
),
Image.asset(
'images/medaillen.svg',
width: 80,
),
SizedBox(
height: 15.0,
),
Text(
'textTopThree',
maxLines: 3,
),
SizedBox(
height: 8.0,
),
],
),
),