Related
I can't figure out how to change the icon that I already highlighted to the top-right. I already use spceBetween, but still doesn't affect the changes.
class _SidebarState extends State<Sidebar> {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Color.fromARGB(255, 44, 41, 56),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
borderRadius: BorderRadius.only(topRight: const Radius.circular(20))),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(32.0)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
child: Material(
shadowColor: Colors.transparent,
color: Colors.transparent,
child: IconButton(
icon: Icon(Icons.menu,
color: Color.fromARGB(255, 247, 243, 243)),
onPressed: widget.onSideBarPressed,
),
),
),
Container(
color: Colors.amber,
child: Material(
shadowColor: Colors.transparent,
color: Colors.transparent,
child: IconButton(
icon: Icon(Icons.access_time,
color: Color.fromARGB(255, 247, 243, 243)),
onPressed: widget.onSideBarPressed,
),
),
)
],
)),
Expanded(
flex: 2,
child: Text(
widget.title,
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
decoration: TextDecoration.none),
),
)
],
),
Divider(
height: 0,
),
Expanded(
flex: 2,
child: Container(
child: widget.body,
),
)
],
),
);
}
}
To show an icon on the left and right, you should use the AppBar widget on your Scaffold().
To place a widget at the start (left) use the leading property, and to place a widget at the end (right) use the actions property:
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
actions: [Icon(Icons.search)],
),);
Result:
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,
),
),
),
),
),
],
),
),
I'm trying to make a widget to display posts by users on a social media platform, I have certain elements I want to include in the post, one of them being the external links he might have attached while creating the posts.
I want these links to be represented by rounded buttons(which I've managed to achieve through the use of ClipOval) and I want these ovals to be in a row spaced evenly from the center.
So far, the only way I've been able to space them out is by adding SizedBox(s) of a certain width. But this is not efficient for different posts may differ in the number of links and thus the number of Ovals. This would look messy then.
I have overlaid the row on top of the post's image(to which I've applied a linear gradient to make the buttons visible) using a stack.
Here's my code
class postTemplate extends StatelessWidget {
List <String> tags = ['tag1','tag2','tag3','tag4','tag5','tag6','tag7','tag8'];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SizedBox(height: 150,),
Container(
height: 450,
child: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 20,),
Card(
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32)
),
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ListTile(
title: Padding(
padding: const EdgeInsets.only(left : 70.0),
child: Text("Username"),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 10.0,left: 80.0),
child: Text("Hello"),
),
),
Stack(
children: [
Container(
child: Container(
foregroundDecoration:BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.transparent],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
stops: [0, 0.3],
),),
child: Image(image: AssetImage('assets/images/modelPostImage.png'),fit: BoxFit.contain,)),
),
Positioned(
bottom: 10.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 15,),
Container(
width: 56,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
SizedBox(width: 15,),
Container(
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
SizedBox(width: 15,),
Container(
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
],
),
),
],
),
Container(
height: 44,
width: 350,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(22))
),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: tags.length,
itemBuilder: (BuildContext context, int index){
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22),
border: Border.all(color: Colors.black)
),
margin: EdgeInsets.only(right: 13, left: 13),
child: Padding(
padding: const EdgeInsets.only(
top: 10.0, bottom: 5.0, right: 20, left:20
),
child: Text(tags[index],
style: TextStyle(
color: Colors.black
),),
),
);
},
),
),
],
),
)
],
),
CircleAvatar(
radius: 42,
backgroundImage: AssetImage('assets/Icons/profileLogo.jpg')
)
],
),
),
],
),
);
}
}
Any help would be appreciated.
Wrap with a container and give it full width and remove sizing
Positioned(
bottom: 10.0,
child: Container(
width:MediaQuery.of(context).size.width,
child :Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 56,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
Container(
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
Container(
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
)
]
),
child: ClipOval(
child: Material(// button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(width: 56, height: 56, child:Image(
image: new AssetImage("assets/Icons/browser.jpg"),
width: 32,
height:32,
color: null,
fit: BoxFit.scaleDown,
),),
onTap: () {},
),
),
),
),
],
),
),
),
],
),
There is a specialized widget to create even space instead of using SizedBox. Replace SizedBox with Spacer.
In AppBar I have kept an icon. When I click on that icon it should open a popup with pointing arrow. That popup should display below the icon only. Should not overlap on that image. And that dropdown should able to customise according to any UI. Please find the attached image.
I don't want to use any plugin.
You can use the Stack Widget to overlap this bubble, and change dynamically the visibility.
//if the bubble is visible or not
bool isVisible = false;
#override
Widget build(BuildContext context) {
return Material(
child: Stack(
children: [
Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[50],
actions: [
Padding(
padding: const EdgeInsets.only(right: 15),
child: IconButton(
icon: Icon(
Icons.add_alert_rounded,
color: Colors.black,
),
onPressed: () {
setState(() {
isVisible = !isVisible;
});
},
),
),
],
),
body: Container(),
),
Positioned(
top: 72, //considering the app bar and system status bar height
right: 10,
child: Visibility(
visible: isVisible,
child: Stack(
children: [
Positioned( //the diamond behind the content
top: 0,
right: 20,
child: Transform.rotate(
angle: math.pi / 4, //rotating the container to turn it into a diamond
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 5.0,
)
],
),
),
),
),
Container(
height: 40.0,
width: 200,
margin: const EdgeInsets.only(top: 5.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 3.0,
offset: Offset(0, 4.0),
),
],
borderRadius: BorderRadius.circular(5.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//just to represent the content of the bubble
Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(10.0),
),
child: Text(
'number',
style: TextStyle(color: Colors.white),
),
),
Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(10.0),
),
child: Text(
'5000',
style: TextStyle(color: Colors.white),
),
),
],
),
),
],
),
),
),
],
),
);
}
After adding elevation to Material widget, I want to keep only the bottom shadow. Don't want the left and right side shadow. How to achieve this?
Here is my code :
// searchbar
child: Material(
color: Colors.transparent,
elevation: 5.0,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10.0),
color: AppColors.searchBoxColor,
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
// searchfield
Expanded(
child: Container(
alignment: Alignment.center,
height: AppBar().preferredSize.height,
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Hint Text",
),
),
),
),
],
),
),
),
You cannot do that with elevation because that will inevitably cast the shadows as if a piece of paper is elevated in air.
What you can do is to add a custom shadow using a BoxShadow. If you're using a RaisedButton, for example, you can change to use a FlatButton with a Container with a BoxDecoration. Here is an example of that:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
child: Text('Button With Elevation'),
textColor: Colors.white,
color: Colors.red,
onPressed: () {},
elevation: 12.0,
),
SizedBox(
height: 32.0,
),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
offset: Offset(0.0, 6.0),
color: Colors.grey.withOpacity(0.3),
blurRadius: 5.0,
),
]
),
child: FlatButton(
child: Text('Button With Custom Shadow'),
textColor: Colors.white,
color: Colors.red,
onPressed: () {},
),
),
],
),
),
),
);
}
}
And here is the result:
By specifying the values of your Offset you can change the direction to where the shadow will cast.
UPDATE:
I saw your code later. Here is how you implement BoxShadow with your code:
child: Material(
color: Colors.transparent,
elevation: 0.0,
child: Container(
decoration: BoxDecoration(
color: AppColors.searchBoxColor,
boxShadow: [
BoxShadow(
offset: Offset(0.0, 12.0),
color: Colors.grey.withOpacity(0.3),
blurRadius: 5.0,
),
],
),
margin: EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
Expanded(
child: Container(
alignment: Alignment.center,
height: AppBar().preferredSize.height,
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Hint Text",
),
),
),
),
],
),
),
),
You can customize the shadow using the boxShadow property of the Container, here an example:
Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(0, 5),
blurRadius: 5,
color: Colors.grey,
),
],
),
),