How to implement Round Shaped AppBar with Gradient Background in Flutter? - flutter

I want to achieve an AppBar which has a rounded bottom radius and gradient background. Also, I need to place some other content like cards within AppBar using the bottom property.
Here is my code:
import 'package:flutter/material.dart';
void main() => runApp(const Toddly());
class Toddly extends StatelessWidget {
const Toddly({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Toddly',
home: Scaffold(
appBar: AppBar(
leading: GestureDetector(
onTap: () {},
child: Container(
margin: const EdgeInsets.only(left: 10),
padding: const EdgeInsets.all(2),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 158, 77, 130),
shape: BoxShape.circle,
),
child: const CircleAvatar(
backgroundImage: AssetImage('assets/images/profilePicture.png'),
),
),
),
title: const Text(
'Julia',
style: TextStyle(
fontFamily: 'Nunito',
),
),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications_outlined),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.menu),
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(150.0),
child: Container(
height: 100,
width: 100,
color: Colors.white,
alignment: Alignment.center,
child: const Text('Some content'),
),
),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF72326a),
Color(0xFF321c53),
],
),
),
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(30.0),
),
),
),
backgroundColor: const Color(0xFFfef1ee),
),
);
}
}
I used the shape property to implement rounded bottom AppBar.
I did gradient background using flexibleSpace.
And, I used bottom to add my other content under within AppBar.
However when I run all above code. rounded bottom appBar is not working.
image source
And, if I remove flexibleSpace it is showing, but I lost my gradient.
image source
Please, help me to figure it out and is it possible to do that without creating custom AppBars since I saw several approaches.
Thanks

All you just need to add corner radius to gradient container as well attaching you the updated code.
import 'package:flutter/material.dart';
void main() => runApp(const Toddly());
class Toddly extends StatelessWidget {
const Toddly({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Toddly',
home: Scaffold(
appBar: AppBar(
leading: GestureDetector(
onTap: () {},
child: Container(
margin: const EdgeInsets.only(left: 10),
padding: const EdgeInsets.all(2),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 158, 77, 130),
shape: BoxShape.circle,
),
child: const CircleAvatar(
backgroundImage: AssetImage('assets/images/profilePicture.png'),
),
),
),
title: const Text(
'Julia',
style: TextStyle(
fontFamily: 'Nunito',
),
),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications_outlined),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.menu),
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(150.0),
child: Container(
height: 100,
width: 100,
color: Colors.white,
alignment: Alignment.center,
child: const Text('Some content'),
),
),
flexibleSpace: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(30.0),
),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF72326a),
Color(0xFF321c53),
],
),
),
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(30.0),
),
),
),
backgroundColor: const Color(0xFFfef1ee),
),
);
}
}

Related

GridView.count: ListTiles are not disappearing above my List

I'm using the GridView.count widget which works alright. But when I'm scrolling down you can see the tiles going behind my other stuff above my GridView part. You can see it through the little Spaces. I want them to disappear when they go above their starting point.
Also please give me any advice on other parts of my code (3 weeks into Flutter).
enter image description here
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(backgroundColor: Colors.blueGrey[700],
appBar: AppBar(
backgroundColor: Colors.green[200],
foregroundColor: Colors.black,
centerTitle: true,
title: const Text("Stromberg Soundboard"),
),
body: ListView(
children: [
Container(
margin: EdgeInsets.all(3),
height: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: const DecorationImage(
image: AssetImage('assets/bernd.jpeg'), fit: BoxFit.cover),
),
),
const SeasonsAndJokes(),
],
),
),
);
}
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 30,
width: double.infinity,
margin: const EdgeInsets.only(left: 5, right: 5, bottom: 5),
color: Colors.green[100],
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
padding: const EdgeInsets.all(0),
alignment: Alignment.topLeft,
iconSize: 32,
disabledColor: Colors.white,
onPressed: lastSeason,
icon: const Icon(Icons.arrow_left_sharp),
),
Text(
seasonsText[indexische],
style: const TextStyle(fontWeight: FontWeight.bold),
textScaleFactor: 1.3,
),
IconButton(
padding: const EdgeInsets.all(0),
alignment: Alignment.topRight,
iconSize: 32,
onPressed: nextSeason,
icon: const Icon(Icons.arrow_right_sharp),
)
],
),
),
SizedBox(
height: 380,
child: GridView.count(
padding: const EdgeInsets.only(right: 5, left: 5),
crossAxisSpacing: 5,
mainAxisSpacing: 5,
crossAxisCount: 2,
childAspectRatio: 3,
children: [
for (int i = 0; i < titelSeasonOne.length; i++)
ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: const BorderSide(color: Colors.white38),
),
trailing: const Icon(
Icons.volume_up_sharp,
color: Colors.blueGrey,
),
tileColor: Colors.green[200],
textColor: Colors.black87,
title: Text(
titelSeasonOne[i],
textScaleFactor: 1,
),
onTap: () {
final player = AudioCache();
player.play(audioSeasonOne[i]);
},
),
],
),
)
],
);
}
}

How to reduce repetitive code for buttons in flutter?

I have more than 10 buttons that I need to display in my flutter. Here's the sample code for my 2 repetitive buttons:
Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
clipBehavior: Clip.antiAlias,
shape: const StadiumBorder(),
child: Ink(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black,
Colors.grey,
Colors.white,
],
),
),
width: double.infinity,
height: 60,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PrivacyRoute()),
);
},
child: ListTile(
leading: Icon(
Icons.menu_book,
color: Colors.white,
),
title: Text('Bahasa Melayu',
style: TextStyle(
color: Colors.white,
fontSize: 20,
)),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
clipBehavior: Clip.antiAlias,
shape: const StadiumBorder(),
child: Ink(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black,
Colors.grey,
Colors.white,
],
),
),
width: double.infinity,
height: 60,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PrivacyRoute()),
);
},
child: ListTile(
leading: Icon(
Icons.menu_book,
color: Colors.white,
),
title: Text('English',
style: TextStyle(
color: Colors.white,
fontSize: 20,
)),
),
),
),
),
),
The non-repetitive is only the colours of linear-gradient, onTap, icon and the text. Any idea how? I tried using the void function but was unable to achieve a usable function. Hope to get some insights from you guys.
Make it a StatelessWidget class
class MyButton extends StatelessWidget {
final VoidCallback onTap;
final List<Color> colors;
final Widget icon;
final String text;
const MyButton({
Key? key,
required this.onTap,
required this.colors,
required this.icon,
required this.text,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
clipBehavior: Clip.antiAlias,
shape: const StadiumBorder(),
child: Ink(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: colors,
),
),
width: double.infinity,
height: 60,
child: InkWell(
onTap: onTap,
child: ListTile(
leading: icon,
title: Text(text,
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
),
),
);
}
}
Now it's up to you if you want those parameters as required or you will have some defaults value in case they are null etc. (for example if you don't pass colors maybe have a cosnt list of colors to use in that case)

How to overlap widgets by respecting their sizes at Flutter?

I just want to overlap 2 Container by respecting first Container's width.
This is what I want to achieve.
Containers not occupying space When I use Stack Widget. So I think stack widget not working for me.
And It is not overlapping when I use Row. So Row is not working either.
In CSS I just give negative margin to the right element and it is done. But I couldn't figure out the way to achieve that in flutter.
I put these Containers in to the Stack. Because I have to overflow a Card widget with that Containers
Try below code hope its help to you
You can use Stack Widget for that
Container(
height: 60,
margin: EdgeInsets.symmetric(
horizontal: 4),
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.only(
topRight: Radius.circular(6),
bottomRight: Radius.circular(6),
),
),
margin: EdgeInsets.symmetric(vertical: 4),
padding: EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerRight,
child: Text('Ends after 1 Hour'),
),
),
Positioned(
top: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.only(
topRight: Radius.circular(6),
bottomRight: Radius.circular(6),
),
),
alignment: Alignment.center,
padding: EdgeInsets.only(right: 8, left: 20),
child: Text('40% Discount'),
),
),
],
),
),
Your result screen ->
Here is my trial.
Using Stack and set 'clipBehavior: Clip.none' parameter.
Added 'addPostFrameCallback' method to get a left container's width.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double firstContainerWidth = 0;
GlobalKey firstContainerKey = GlobalKey();
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
firstContainerWidth = firstContainerKey.currentContext.size.width;
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return Stack(
clipBehavior: Clip.none,
alignment: AlignmentDirectional.bottomStart,
children: <Widget>[
Positioned(
left: firstContainerWidth - 10,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Text(
'Ends after 1 hour',
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
),
),
Container(
key: firstContainerKey,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Text(
'%40 Discount',
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
),
]);
}
}
It can be done in multiple ways. You can use CustomPainter, Stack or even Row to do this. Here is my approach using a Row only.
Result
Code : DartPad
class DiscountBadgeWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
_buildRedSection(),
_buildMiddleSection(),
_buildYellowSection(),
],
);
}
Widget _buildMiddleSection() => Container(
color: Colors.yellow,
child: Align(
alignment: Alignment.bottomCenter,
heightFactor: .5,
child: Container(
height: 80,
width: 10,
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.horizontal(right: Radius.circular(10)),
),
),
),
);
Widget _buildRedSection() => Container(
height: 80,
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.horizontal(left: Radius.circular(10)),
),
padding: const EdgeInsets.only(left: 16, right:6),
alignment: Alignment.centerRight,
child: Text('40% Discount'),
);
Widget _buildYellowSection() => Container(
height: 60,
decoration: const BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.horizontal(right: Radius.circular(10)),
),
padding: const EdgeInsets.only(right: 16, left:6),
alignment: Alignment.centerRight,
child: Text('Ends after 1 Hour'),
);
}

How can I design chip with outside an image in flutter?

How can I design like this in flutter?
The above image u can use as star.
I have tried like the following but it's not correct,
new Container(
child:
ButtonTheme (
buttonColor: buttonColor: Colors.teal,
child: Stack(
children: [
RaisedButton (
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(
color: Colors.transparent,
),
),
child: Text(
'123',
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
fontFamily: 'MuseoSans',
),
),
onPressed: () {
//click actions
},
),
Positioned( // will be positioned in the top right of the container
top: 0,
left: 0,
child: new Image.asset('images/ic_star.png'),
)
]
)
),
)
Try this
Container(
child: ButtonTheme(
buttonColor: Colors.teal,
child: Stack(children: [
Container(
height: 40.0,
child: Padding(
padding: const EdgeInsets.only(left: 25.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(
color: Colors.transparent,
),
),
child: Text(
'123',
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
fontFamily: 'MuseoSans',
),
),
onPressed: () {
//click actions
},
),
),
),
Positioned(
// will be positioned in the top right of the container
top: 0,
left: 0,
child: new Image.asset(
'images/ic_star.png',
width: 50.0,
height: 50.0,
),
)
])),
)
It will look something like this -
Use 'Stack' widget
Here is pseudo code
It very bad code but simple example
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 90,
height: 23,
child: Stack(
children: [
Align(
alignment: Alignment.centerRight,
child: Container(
decoration: BoxDecoration(
color: Colors.teal,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Text(
' 123123',
style: TextStyle(fontSize: 20, color: Colors.white),
),
),
),
Image.network('https://i.stack.imgur.com/SpWmJ.png', height: 23),
],
),
),
);
}
}
You have to change some size (like wrap content)

Add Badge on a hamburger menu icon in flutter

Hi Please help I am trying to add a red Badge on a hamburger menu icon in the flutter app like below
You can achieve this with badges plugin here
Add this to your package's pubspec.yaml file under dependencies:
badges: ^2.0.2
then import,
import 'package:badges/badges.dart';
finally add Badge in AppBar,
AppBar(
leading: Badge(
position: BadgePosition.topEnd(top: 10, end: 10),
badgeContent: null,
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
),
title: Text('Badge Demo', style: TextStyle(color: Colors.black)),
backgroundColor: Colors.white,
)
Using Stack, similar sample code:
class NotificationIcon extends StatelessWidget {
final bool active;
final double marginTopLeft;
const NotificationIcon({Key key, this.active = true, this.marginTopLeft})
: super(key: key);
#override
Widget build(BuildContext context) {
final color = active ? Colors.white : const Color(0xff40a9ff);
final margin = marginTopLeft ?? 17;
return Container(
width: 24,
height: 24,
child: Stack(
children: [
Center(
child: Icon(
Icons.notifications,
color: color,
),
),
Positioned(
right: margin,
top: margin,
child: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
shape: BoxShape.circle,
),
child: Center(
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
),
width: 5,
height: 5,
),
),
),
)
],
),
);
}
}
It can be easily done using the Stack widget. I have given an example of how you can use stack to achieve that. Note that you have to use Scaffold.of(yourContext).openDrawer() to open the attached drawer (as I've done here) since the hamburger icon is manually placed there.
import 'package:flutter/material.dart';
void main() {
runApp(Example());
}
class Example extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Example",
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: InkWell(
splashColor: Colors.lightBlue,
onTap: () => Scaffold.of(context).openDrawer(),
child: Center(
child: Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 25,
child: Stack(
children: [
Icon(
Icons.menu,
color: Colors.grey[850],
),
Positioned(
left: 25,
top: 0,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
width: 10,
height: 10,
),
),
),
)
],
),
),
),
),
title: Text("Hello"),
actions: [
],
),
body: Center(child: Text("Welcome")),
),
);
}
}
Widget build(BuildContext context) {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
return Scaffold(
key: _scaffoldKey,
drawer: Drawer(),
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(
"Some Text",
style: TextStyle(color: Colors.white),
),
leading: InkWell(
splashColor: Colors.lightBlue,
onTap: () {
_scaffoldKey.currentState.openDrawer();
},
child: Center(
child: Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 25,
child: Stack(
children: [
Icon(
Icons.menu,
color: Colors.white,
),
Positioned(
left: 25,
top: 0,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
width: 10,
height: 10,
),
),
),
)
],
),
),
),
),
),
body: SafeArea(
child: Container(
),
),
);
}
Please use this. And if you want to show the number as well, you can use Badge too.