I found some topics about calculating height in flutter, but noone of them answered my question. I am trying to calculate 100% of device height in flutter. I assume, I have to subtract from MediaQuery.of().size.height two things. First is AppBar height, so I calculated it by creating variable appBar and get property preferredSize.height. Second is the bar above appBar (which contains things like battery status, notifications etc.).
This is the simplest example:
#override
Widget build(BuildContext context) {
var appBar = AppBar(
title: Text(widget.title),
);
return Scaffold(
appBar: appBar,
body: Center(
child: Builder(
builder: (ctx) => Column(
children: <Widget>[
Container(
height: MediaQuery.of(ctx).size.height -
MediaQuery.of(ctx).padding.top -
appBar.preferredSize.height,
color: Colors.red,
)
],
),
),
),
);
}
This is my main Widget so I had to create context with Builder. However, it is not still equal to 100% of device height. It is 24px too much. I don't want to subtract 24px because It might be more/less on another device. What is wrong with this example?
You don't need to do anything special to the child of the Scaffold. Unless the child widget manages its own sizing, it will fill the entire remainder of the area inside of the Scaffold by default. In the case of Container, its behavior is to shrink wrap to the size of its child, but if it doesn't have a child, it will fill all available space. So you can just do this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello World'),
),
body: Container(
color: Colors.red,
),
);
}
Depending on the child widget, you may need to manually configure a size, but most layout widgets either you won't need to worry about it or it just takes a bit of configuration. With Column, for example, if you set mainAxisSize: MainAxisSize.max and crossAxisAlignment: CrossAxisAlignment.stretch, then it will also automatically stretch to fill all available space. You can then make use of Expanded to size its children based on available space as well.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello World'),
),
body: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(color: Colors.red),
),
Expanded(
child: Container(color: Colors.green),
),
Expanded(
flex: 2,
child: Container(color: Colors.yellow),
),
],
),
);
}
However, on the seldom occasion you need the exact numbers of the space available, you don't usually want to use MediaQuery as that will get you the size of the entire screen, not just the available space, and you usually will have to perform additional calculations to boil it down to the size you are actually looking for (which usually leads to incorrect results, as you have discovered).
Instead, you can use a LayoutBuilder. A word of caution here, you don't want to abuse LayoutBuilder as it adds an additional layout step to its children, so having a lot of them in your code can easily slow down your app.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello World'),
),
body: LayoutBuilder(
builder: (context, constraints) {
final width = constraints.biggest.width;
final height = constraints.biggest.height;
return Center(
child: Text('Width: $width, Height: $height'),
);
},
),
);
}
Related
I want to remove the strange padding on top of the status bar. I am simply using an image and want to put that image on top of the screen that is behind the status bar. So that the status bar icons should be overlayed on the image.
Simply using Scaffold as a parent widget and then simple an Image. Screen shot is here!
The icons are not properly overlapping the image, and there is a white padding on top head!
I am using an Android Emulator right now, can somebody please figure out what I am missing.
class PreSignInScreen extends StatelessWidget {
final PreSignInController controller = Get.put(PreSignInController());
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 10,
),
getRedCarBox(context),
]
);
)
}
Thanks & Advance
Try below code, I have tried
- Scaffold
- Column
- Container
- Image
Your Widget:
Scaffold(
body: Column(
children: [
Container(
width: double.infinity,
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
'https://cdn.pixabay.com/photo/2022/03/27/11/23/cat-7094808__340.jpg',
),
),
),
),
//Add your other widgets here
],
),
),
Or Using SafeArea, top property false
SafeArea(
top: false,
child: Container(),
),
Result Screen->
Try this:
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return false;
},
child: Scaffold(
body: SafeArea(
top: false,
bottom: false,
child: _buildBody(),
),
),
);
}
Scaffold(
body: SafeArea(
top: false,
bottom: false,
child: _yourBody(),
),
Why to use SafeArea :
SafeArea class Null safety. A widget that insets its child by sufficient padding to avoid intrusions by the operating system. For example, this will indent the child by enough to avoid the status bar at the top of the screen.
I need help. At the moment I'm trying to implement a background on my login page.
My problem is that I use a custom shape painter which shows my background.
To make my login page more dynamic I have added a function resizeToAvoidBottomInset: true, to move the textfield over the keyboard.
But now I have the problem that my background will be smaller if I click on my text field.
Here is my login page:
My code:
class _DebugPage extends State<DebugPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: customSubAppBar('Debug', context),
body: Stack(
children: [
//my custom shape painter
Expanded(
child: CustomeShapePainer(),
),
//my custom widgets
_body(context),
],
),
);
}
}
Is there a way to set the background on fix size?
I think you can try set widget CustomeShapePainer wrap Widget Stack. I don't remember exactly but in some projects I did
child: SingleChildScrollView(
child: Container(
color: AppConstants.bgColor,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: CustomPaint(
painter: CurvePainter(),
child: Stack
I want to make my screen into 3 equal part using container class in flutter. How to do that?
What you want is the Flexible widget
Let's say you want the three equal parts to be stacked vertically
return Column(
children: [
Flexible(child: Container()),
Flexible(child: Container()),
Flexible(child: Container()),
]
);
You can also specify a flex component to signify the relationship between the widgets' sizes
return Column(
children: [
Flexible(child: Container(), flex:1),
Flexible(child: Container(), flex:2),
]
);
which will make the second widget take 2/3 of the available space
I prefer using LayoutBuilder, it constraints that can be used to get body height,maxWidth, also it provides more than this. Also, you can try media query.
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => Column(
children: [
Container(
height: constraints.maxHeight / 3,
width: constraints.maxWidth,
color: Colors.deepPurple,
),
Container(
height:size.height/3,
width: size.width/3,
color: Colors.deepPurple,
)
],
),
));
}
You can remove Column it's just an example. Using LayoutBuilder provide parents' constraints.
When I add a widget to a sliding_up_panel widget dynamically after the initial load, the panel's height does not increase, meaning that the bottom of the panel gets cut off and I get the A RenderFlex overflowed by 27 pixels on the bottom. error.
What can I do to ensure the panel updates its height in this case please?
To Reproduce
Add a widget to the panel dynamically via the condition ? widget : widget logic. For example:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlidingUpPanelExample"),
),
body: Stack(
children: <Widget>[
Center(child: Text("This is the Widget behind the sliding panel"),),
SlidingUpPanel(
panel: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
myFirstVariable ? Text("This is a sliding Widget") : Container(),
mySecondVariable ? Text("This is another sliding Widget") : Container(),
],
),
)
)
],
)
);
}
Thanks so much!
the SlidingUpPanel widget doesn't adjust its height according to its children.
A solution to your problem would be add a SingleChildScrollView to your panel content and use the panelBuilder instead of the panel property.
The panelBuilder takes the burden of managing scrolling and sliding conflicts by providing you a controller that you can feed to your SingleChildScrollView, your code will change to be like the following :
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlidingUpPanelExample"),
),
body: Stack(
children: <Widget>[
Center(child: Text("This is the Widget behind the sliding panel"),),
SlidingUpPanel(
panelBuilder:(sc) => SingleChildScrollView(
controller: sc,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
myFirstVariable ? Text("This is a sliding Widget") : Container(),
mySecondVariable ? Text("This is another sliding Widget") : Container(),
],
),
)
)
],
)
);
}
Like this, you won't have any overflow issues, and when the content of the panel overflows the SingleChildScrollView will become scrollable.
hope this helps:
use a controller,
You can control the height of the panel depending on the items on the list (0.0 to 1.0). Ensure to update the UI once you add a new item.
use a List
This will solve the renderOverflow you mentioned
/// just for the example
List<Widget> items = <Widget>[];
//adding items
addItem() {
items.add(Container(
constraints: BoxConstraints(maxHeight: 200, minHeight: 200),
color: Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0),
));
/// if you know in advance the height of the widgets been rendered: 200
/// if you know in advance the height of the panel: 500, or context.size.height / 2 (which would be 50% of screen) asume 600
///
/// increase panel height panel according to the number of items
///
_pc.panelPosition =
(items.length * 200) / 600 > 1.0 ? 1 : (items.length * 200) / 600;
/// Hey
/// SET State after adding the item
/// to refresh UI
}
Widget _scrollingList(ScrollController sc) {
return ListView.builder(
controller: sc,
itemCount: items.length,
itemBuilder: (context, index) {
return items[index];
},
);
}
PanelController _pc = new PanelController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlidingUpPanelExample"),
),
floatingActionButton: FloatingActionButton(
onPressed: addItem,
),
body: Stack(
children: <Widget>[
Center(
child: Text("This is the Widget behind the sliding panel"),
),
SlidingUpPanel(
controller: _pc,
panelBuilder: (ScrollController sc) => _scrollingList(sc),
),
],
));
Plugin has the methods: minHeight and maxHeight to do the work. I think is not posible change it dynamically without set that attributes.
I want to reuse mobile app code for flutter web. I already coded with AppBar() and body widgets in scaffold in all screens. Now i am taking 400 width and center for web, it is good except appbar.
Scaffold(
appBar: this.getAppBarWidget(),
body: Center(
child: Container(
width: kIsWeb ? 400.0 : MediaQuery.of(context).size.width,
child: this.getBodyWidget(),
),
))
Above code is perfectly working for all screens of mobile and web except appbar in web.
How do i change width of appbar to fit width 400 ?
If i use Size.fromWidth(400) getting error.
Below code is working for mobile and web.
Scaffold(
body: Center(
child: Container(
width: kIsWeb ? 400.0 : MediaQuery.of(context).size.width,
child: Column(
children: [
this.getCustomAppbarWidget(),
this.getBodyWidget(),
],
),
),
))
Please suggest me.
The size this widget would prefer if it were otherwise unconstrained.
In many cases it's only necessary to define one preferred dimension. For example the [Scaffold] only depends on its app bar's preferred height. In that case implementations of this method can just return new Size.fromHeight(myAppBarHeight).
But we can provide customAppBar like
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyAppBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.centerLeft,
child: Container(
alignment: Alignment.center,
color: Colors.pink,
// we can set width here with conditions
width: 200,
height: kToolbarHeight,
child: Text("MY AppBar"),
),
);
}
///width doesnt matter
#override
Size get preferredSize => Size(200, kToolbarHeight);
}
and use
Scaffold(
extendBodyBehindAppBar: true,
appBar: MyAppBar(),
body: ......
if it cover the 1st item of body, and in this case use SizedBox(height: kToolbarHeight) to handle the situation if needed.
Result
As i know, width did not allow in AppBar. Only height is allowed in AppBar
toolbarHeight: 60,
But if you want to apply manually width in your AppBar you can wrap your AppBar in Padding component
return Scaffold(
body: Column(
children: [
Container(
width: kIsWeb? 400 : double.maxFinite,
child: AppBar(
title: Text('hello'),
),
),
Expanded(child: HomePageOne()), // this expanded is you page body
],
),
);