I am finding it difficult to add a drawer in the latest version of flutter. My code looks like this
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppbar(),
body: const Body(),
drawer: DrawerSlide(),
);
}
AppBar buildAppbar() {
return AppBar(
elevation: 3,
leading: GestureDetector(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: SvgPicture.asset('assets/icons/menu.svg', width: 10, height: 10, fit: BoxFit.fitWidth,),
),
onTap: () => Scaffold.of(context).openDrawer(),
),
);
}
}
There is an error shown in Scaffold.of(context).openDrawe() that the context is not defined. It was working till I updated my flutter but in new flutter I think it is not working.
The buildAppbar method requires context as a positional argument :
AppBar buildAppbar(BuildContext context) {
return AppBar(
elevation: 3,
leading: GestureDetector(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: SvgPicture.asset('assets/icons/menu.svg', width: 10, height: 10, fit: BoxFit.fitWidth,),
),
onTap: () => Scaffold.of(context).openDrawer(),
),
);
}
use it like :
return Scaffold(
appBar: buildAppbar(context),
body: const Body(),
drawer: DrawerSlide(),
);
Related
import 'package:flutter/material.dart';
class ImagenesPage extends StatelessWidget {
const ImagenesPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Imágenes'),
),
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
Image.asset('assets/images/wallpaper.png'),
const Padding(padding: EdgeInsets.fromLTRB(0, 10, 0, 0)),
Image.network(
'https://previews.123rf.com/images/cc0collection/cc0collection2205/cc0collection220540918/186116605-oranges,-fruits,-citrus,-vitamins,-juicy,-food,-green,-leaf,-harvest,-fram,-wet,-water,-drops.jpg?fj=1'),
],
),
),
),
);
}
}
Try the following code:
CircleAvatar(
backgroundImage: NetworkImage('https://previews.123rf.com/images/cc0collection/cc0collection2205/cc0collection220540918/186116605-oranges,-fruits,-citrus,-vitamins,-juicy,-food,-green,-leaf,-harvest,-fram,-wet,-water,-drops.jpg?fj=1'),
),
This is how you can add an circle avater:
CircleAvatar(
radius: 20,
child: ClipOval(
child: Image.network(
'https://previews.123rf.com/images/cc0collection/cc0collection2205/cc0collection220540918/186116605-oranges,-fruits,-citrus,-vitamins,-juicy,-food,-green,-leaf,-harvest,-fram,-wet,-water,-drops.jpg?fj=1',
),
),
),
This problem only happens inside Drawer
I wanted to shape the ripple effect of my ExpansionTile so I used the Material widget and it works, but when the tile expands, the background color of the tiles below ExpansionTile does not move with them.
When ExpansionTile is collapsed
When ExpansionTile is expanded
I found out that when I remove SingleChildScrollView the problem solves but I need items to scroll. Also when ScrollPhysics has been set to AlwaysScroll, scrolling till the end of the scroll's possible position would rerender items and fix the issue.
Reproducible Example:
void main() {
runApp(
MaterialApp(
title: 'Title',
home: Scaffold(
appBar: AppBar(
title: const Text('Title'),
),
drawer: const MyList(),
body: Container(),
),
),
);
}
class MyList extends StatelessWidget {
const MyList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
items(),
],
),
),
);
}
Widget items() {
return Wrap(
runSpacing: 12,
children: [
menu(),
const ListTile(title: Text('title'), tileColor: Colors.grey),
const ListTile(title: Text('title')),
]
);
}
Widget menu() {
return Material(
clipBehavior: Clip.antiAlias,
type: MaterialType.transparency,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)
),
child: const ExpansionTile(
leading: Icon(Icons.group),
title: Text('title'),
children: [
ListTile(title: Text('title')),
ListTile(title: Text('title')),
],
),
);
}
}
If you want to avoid SingleChildScrollView and still be able to scroll over a list, you can use ListView.builder link: - ListView.builder flutter.dev
Try removing type: MaterialType.transparency,
class MyList extends StatelessWidget {
const MyList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
child: Column(
children: [
for (int i = 0; i < 2; i++) items(),
],
),
),
);
}
Widget items() {
return Wrap(
children: [
menu(),
const ListTile(
title: Text('title'),
tileColor: Colors.grey,
),
const ListTile(title: Text('title')),
],
);
}
Widget menu() {
return Material(
clipBehavior: Clip.antiAlias,
// type: MaterialType.transparency,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
child: const ExpansionTile(
leading: Icon(Icons.group),
title: Text('title'),
children: [
ListTile(title: Text('title')),
ListTile(title: Text('title')),
],
),
);
}
}
I asked for this problem on flutter's Github repo and I got the answer.
Just need to use ListTileTheme widget instead of Material widget.
Github issue link:
https://github.com/flutter/flutter/issues/112372
This is my simple code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyMobileBody(),
);
}
}
class MyMobileBody extends StatelessWidget {
const MyMobileBody({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Scaffold(
backgroundColor: Colors.deepPurple[200],
appBar: AppBar(
title: Text('M O B I L E'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
// video section
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.deepPurple[400],
),
),
),
// comment section & recommended videos
Expanded(
child: ListView.builder(
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
),
)
],
),
),
),
);
}
}
It gets the bottom overflow yellow/black error. I want to make the AspectRatio widget scrollable but using SingleChildScrollView didn't work. I also tried ConstrainedBox like below but it didn't work too:
// comment section & recommended videos
ConstrainedBox(
constraints: BoxConstraints(maxHeight: constraints.maxHeight),
child: Expanded(
child: ListView.builder(
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
),
),
)
Add shrinkWrap : true to the ListView, then remove the Expanded widget that's wrapping the list view. Also add mainAxisSize : MainAxisSize.min. Then add SingleChildScrollView to the body of scaffold and the column inside it.
class MyMobileBody extends StatelessWidget {
const MyMobileBody({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Scaffold(
backgroundColor: Colors.deepPurple[200],
appBar: AppBar(
title: Text('M O B I L E'),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize : MainAxisSize.min,//<--here
children: [
// video section
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.deepPurple[400],
),
),
),
// comment section & recommended videos
//<--here removed expanded
ListView.builder(
shrinkWrap:true,//<--here
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
)
],
),
),
),
),
);
}
}
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
Storycard(),
],
),
),
);
}
}
class Storycard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, int index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
child: Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
child: Column(
children: <Widget>[
ClipRRect(
child: Image.asset(
news[index].image,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(news[index].newsHeadline,
style: GoogleFonts.ubuntu(
fontSize: 17, fontWeight: FontWeight.bold)),
)
],
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewsDetails(news: news[index])));
});
},
itemCount: news.length,
);
}
}
I am trying here to have a list of scrollable cards. I want space above the cards to add some text. SO I tried using column and have a text and Listview Bulider as children. But the emulator is showing blank screen.
When the StoryCard() is alone used as the body the output comes with widgets. I can't add anything above the Listview. Can someone help.
enter image description here
Use Expanded class or Flexible class for the ListView.
ListView requires a finite height for it's content.
With your current code, ListView is having infinite height, hence the error. Expanded or Flexible helps you to have the remaining space to be utilized for your child
Solution
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Expanded(
child: Storycard()
)
]
)
)
);
}
}
Using Flexible
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Flexxible(
fit: FlexFit.loose,
child: Storycard()
)
]
)
)
);
}
}
Due to unavailability of modifying app bar leading property width I'm forced to create my own leading trailing property by using AppBar title property. However I've noticed that title has some default horizontal padding there.
Scaffold(
appBar: AppBar(
centerTitle: true,
title: Container(
height: 36,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(width: 80, child: Text('Cancel')),
Text('Profile'),
Container(width: 80, child: Text('Done'))
],
),
),
),
)
Is there any way to make it smaller?
Use action[] inside the appbar instead of using Row.
appBar: new AppBar(
//title: new Text(Strings.app_name),
actions: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: new RaisedButton(onPressed: (){
},
child: new Text('Cancel'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child:
new RaisedButton(onPressed: (){
},child: new Text('done'),)
),
],
//centerTitle:true,
),
You can use the titleSpacing property of the AppBar to control the horizontal spacing for the title.
For example following snippet will remove all the leading spacing from title-
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatelessWidget(),
);
}
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0.0,
title: const Text('AppBar Demo'),
),
body: const Center(
child: Text(
'This is the home page',
style: TextStyle(fontSize: 24),
),
),
);
}
}
I hope this helps!
Please use titleSpacing: 0.0
appBar: AppBar(
titleSpacing: 0.0,
title: Text('AppBar Example'),
),