I'm trying to display an ad using the admob_flutter package: https://pub.dev/packages/admob_flutter, which basically allows me to display the ad just like any other widget.
Following the documentation, I added a widget within a column layout as below (relevant code only):
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(fileName),
backgroundColor: Colors.teal,
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: (){
},
),
],
),
body: Container(
padding: EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
TextField(
...
),
AdmobBanner(
adUnitId: 'ca-app-pub-39402560999XXXXXX/XXXXXXXXX',
adSize: AdmobBannerSize.BANNER,
),
],
),
),
bottomNavigationBar: BottomAppBar(...)
As per documentation, this is all I have to do, but I get an overflow error as seen in screenshot below:
I tried wrapping these in Expanded() and Flexible() but that did not fix my problem?
What am I doing wrong here?
You should wrap your Widgets in a Scrollable Widget so they can be scrolled when the contents exceeds the device screen's size.
I wrapped your widgets in a SingleChildScrollView, check the demo below:
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(fileName),
backgroundColor: Colors.teal,
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: (){
},
),
],
),
body: SingleChildScrollView( // new line
child: Container(
padding: EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
TextField(
...
),
AdmobBanner(
adUnitId: 'ca-app-pub-39402560999XXXXXX/XXXXXXXXX',
adSize: AdmobBannerSize.BANNER,
),
],
),
),
)
bottomNavigationBar: BottomAppBar(...)
Just change Column to Listview
You can use ListView , SingleChildScrollView or ListView.builder if you want dynamic contents in place of Column
body: Container(
padding: EdgeInsets.all(5.0),
child: Column(..),),
Related
I will explain with simple examble,
class Demo1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
Flexible(
child: ListView(
shrinkWrap: true,
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
])),
Expanded(
child: Container(
color: Colors.green,
)),
],
),
),
);
}
}
Here the green colored container is not filling the remaining space, so how to fill the remaining area?
Thanks in advance
Try below code and just Remove your first Flexible Widget
Column(
children: <Widget>[
ListView(
shrinkWrap: true,
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
],
),
Expanded(
child: Container(
color: Colors.green,
),
),
],
),
You can use SingleChildScrollView instead of using ListView with shrinkWrap: true.
class Demo1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
SingleChildScrollView(
child: Column(
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
],
),
),
Expanded(
child: Container(
color: Colors.green,
)),
],
),
),
);
}
}
You may also like CustomScrollView over SingleChildScrollView and shrinkWrap:true.
Both Flexible and Expanded have flex value 1, so they both request 50% of the available space. So the Container child of Expanded takes fills only half space, while the ListView, a child of Flexible, also requests half the space but needs very little space.
You can make Container fill the available space by removing Flexible, so Expanded that wraps Container will get all the available space.
I have an issue with the whole screen scrolling in Flutter. Only the Expanded widget is able to scroll on-screen in my app but I want to make the whole screen scrollable. How can I do that? Here is my code e.g.
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(
'My App',
style: AppTheme.of(context).title1,
),
elevation: 0,
backgroundColor: Colors.amber,
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(10, 20, 10, 0),
child: Column(
. // Padding repeats two more times
.
.
.
Expanded(
child: MyWidget(
myProp1: value1,
myProp2: value2,
myProp3: value3,
myProp4: value4,
myProp5: value5,
myProp6: value6
) // MyWidget
), // Expanded
],
), // Column
); // Scaffold
}
I've tried to wrap Column with SingleChildScrollview widget but it didn't work for me. I guess I can not use Expanded widget in SingleChildScrollview. I also tried to use Container or etc. instead of Expanded and Column widgets but I couldn't solve this issue. Can anybody help me with it?
There is no need to wrap MyWidget with Expanded. Just Change Column into ListView:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(
'My App',
),
elevation: 0,
backgroundColor: Colors.amber,
),
body: ListView(
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(10, 20, 10, 0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
decoration: BoxDecoration(color: Colors.black),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
decoration: BoxDecoration(color: Colors.black),
),
)
],
))
],
), // Column
); // Scaffold
}
You also can use the SingleChildScroll view as Child of Expanded widget will work fine
I am new to flutter and I need to add the main drawer of the app to a button as you can see in the below picture(This is the upper section of the UI of the app)
Any ideas of having the main drawer apply to a button instead of having it normally assign it to the app bar. (This mobile app doesn't have an app bar)
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return Scaffold(
key: scaffoldKey,
body: Stack(
children: <Widget>[
_buildWidgetAlbumCover(mediaQuery),
getMainContentWidget(mediaQuery),
_buildWidgetMenu(mediaQuery),
_buildWidgetFloatingActionButton(mediaQuery),
Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
},
),
],
),
),
],
),
);
}
Widget _buildWidgetMenu(MediaQueryData mediaQuery) {
return Padding(
padding: EdgeInsets.only(
left: 2.0,
top: mediaQuery.padding.top + 2.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
size: 25,
),
padding: EdgeInsets.all(2.0),
// onPressed: () => scaffoldKey.currentState.openDrawer(),
),
],
),
);
}
enter image description here
This is output which I get after having this code. This drawer can't even change or as it is fixed one. I want the normal drawer which is also attached to the _buildWidgetMenu instead of the app bar drawer.
If youre using a sacffold it has a drawer property that you can make use of eg cookbook
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(child: Text('My Page!')),
drawer: Drawer(...
opening your drawer from button clicks
var scaffoldKey = GlobalKey<ScaffoldState>();
//required key
Scaffold(
key: scaffoldKey,
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,...
body:Center(..
IconButton(
icon: Icon(Icons.menu),
//open drawer
onPressed: () => scaffoldKey.currentState.openDrawer(),
),
I faced some problem. I want make an image, a text and two icons in AppBar but I can't make it work as I want.
I tried to make some fonts in a row after the images and text. The images and the text successful show in my AppBar, but the rest of 2 fonts (Trolley and notifications) show some error.
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.amber,
appBar: new AppBar
(
title: new Row
(
mainAxisAlignment: MainAxisAlignment.start,
children:
[
Image.asset('images/logoapp.png',fit: BoxFit.contain,height: 32,),
Container(padding: const EdgeInsets.all(8.0), child: Text('Solid Shop'))
],
)
),
....
Use leading to set a widget before appBar title & use actions to specify list of widgets in appBar which appears on right side of appBar title.
AppBar(
leading: Image.asset('yourImage'), // you can put Icon as well, it accepts any widget.
title: Text ("Your Title"),
actions: [
Icon(Icons.add),
Icon(Icons.add),
],
);
Read more about it here
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Solid Shop"),
leading: Image.asset("your_image_asset"),
actions: <Widget>[
IconButton(icon: Icon(Icons.shopping_cart), onPressed: () {}),
IconButton(icon: Icon(Icons.message), onPressed: () {}),
],
),
);
}
You need to use actions instead of title
actions: <Widget>[
Image.asset('images/logoapp.png',fit: BoxFit.contain,height: 32,),
Container(padding: const EdgeInsets.all(8.0), child: Text('Solid Shop')),
Image.asset('images/logoapp.png',fit: BoxFit.contain,height: 32,), // here add notification icon
Container(padding: const EdgeInsets.all(8.0), child: Text('Solid Shop')) // here add other icon
],
You can add icon and also a picture on app bar, this code works for me:-
appBar: AppBar(
centerTitle: true,
elevation: 2,
title: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"assets/images/bell.png",
fit: BoxFit.contain,
height: 28,
),
Container(
child: Text(" APP BAR"),
)
],
),
),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Settings();
},
),
);
},
color: Colors.white,
)
],
),
Hope this was helpful.
You can combine it with Spacers :
actions: const [
Spacer(flex: 3),
Icon(Icons.fit_screen),
Spacer(flex: 10),
Icon(Icons.width_normal),
Spacer(flex: 1),
Icon(Icons.aspect_ratio),
Spacer(flex: 1),
Icon(Icons.ad_units),
Spacer(flex: 5),
],
I am making a custom AppBar that has a larger height than the typical AppBar. I would like to resize the leading widget/icon as well, and take advantage of the automaticallyImplyLeading default behaviors (so the menu icons and back icons are automatically implemented).
This is the solution I thought I would implement:
class AppAppBar extends PreferredSize{
AppAppBar(String title) : super(
preferredSize: Size.fromHeight(56.0),
child: AppBar(
centerTitle: true,
title: Text(title, style: textStyle)
)) {
(child as AppBar).leading =
SizedBox(width: 30.0, height: 30.0, child: (child as AppBar).leading);
}
static const textStyle = TextStyle(fontSize: 32.0);
}
But of course this won't work because (child as AppBar).leading is final.
So in the AppBar below (text size made dramatically larger for illustration purposes), I would like to make the automatically added hamburger icon larger in comparison.
What do you think? Are there solutions for this or should I give up on the automatic icons and add them myself?
Edit: Added an image to show what I mean
You cant because it is a predefined widget.
You can work around it with a Row widget:
Scaffold(
key:_scaffoldKey,
drawer: Drawer(),
appBar: AppBar(
automaticallyImplyLeading: false
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 20, // Your Height
width: 20, // Your width
child: IconButton( // Your drawer Icon
onPressed: () => _scaffoldKey.currentState.openDrawer()),
icon: Icon(Icons.arrow_back, color: Colors.white),
),)
// Your widgets here
],
),
),
)
You need the Key to open the drawer with _scaffoldKey.currentState.openDrawer().
automaticallyImplyLeading: false will prevent the default drawer Icon.
A simple example to demonstrate Raffi Jonas answer
AppBar(
automaticallyImplyLeading: false,
title: Row(
children: [
Expanded(
child: Text('One'),
),
Center(
child: Text('Two'),
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('Three'),
),
),
],
),
),
The leading Widget width of AppBar in Flutter can be resized using the leadingWidth property.
For Example :
AppBar(
title: const Text('Title'),
leadingWidth: 50,
leading: Container()
)
What you want is a custom app bar in Flutter. Most people try giving their own widgets in the title argument of an AppBar. But let me show you how to properly do it.
#override
Widget build(BuildContext context) => Scaffold(
appBar: _appBar(),
body: _body(),
);
//Custom AppBar
_appBar() => PreferredSize(
//kToolBarHeight: Default size used by all AppBar widgets in Flutter.
//MediaQuery...: viewPadding.top is StatusBar area. viewPadding.bottom is iPhone bottom bar.
preferredSize: PreferredSize.fromHeight(kToolBarHeight + MediaQuery.of(context).viewPadding.top),
child: Container(
child: Row(
//This will spread Row content evenly across the screen.
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//Leading Widget
Icon(Icons.home),
//Title
Text("Hello World!"),
//Trailing Widget / Actions
Icon(Icons.home),
],
),
),
);
Widget _body() => Container(
color: Colors.blue,
);
You can set a margin for height or width.
AppBar(
leading: Container(
margin: EdgeInsets.symmetric(vertical: 15),
child: IconButton(
icon: Icon(CupertinoIcons.chevron_left),
onPressed: () {},
),
),
To use a custom appBar leading button, here is the code.
appBar: AppBar(
title: Text('hello'),
// automaticallyImplyLeading: false,
elevation: 0,
leadingWidth: 58,
actions: [
ProfileBar(),
],
leading: Container(
width: 14,
//color: Colors.yellow,
child: Row( // <--- Using row to avoid force resizing of leading
children: [
Padding( // <--- Padding to make it look more nicer
padding: const EdgeInsets.only(left: 24.0),
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: SvgPicture.asset( // <-- Using SvgPicture package
'assets/svg/icons/backbtn.svg',
width: 24,
height: 24,
),
),
),
],
),
),
),