bottomNavigationBar do what I want only while hot reloading - flutter

I would like to have a static bottom bar for my app.
This bar should content the hour of a device in the middle, and the temperature read by another device on the right side.
My problem is just about the positioning/sizing.
When I start it (with android studio, on real or virtual device), it doesn't work : the preview is not what I excepted, the dimensions I choose seem to have changed.
But when I hot-reload it, it becomes exactly what I want like this :
The problem is that the final app is not the hot-reloaded one ..
I may have identify the problem,
I use a MediaQuery.of(context).size and a builder to obtain the context in order to fit with all the devices considering the size. This solution must be a dirty one but I don't find anything else..
Here is my code, hope the situation is clear...
return new MediaQuery(
data: MediaQueryData.fromWindow(ui.window),
child: Builder(
builder: (context) {
return new Builder(
builder: (
context) {
return
new MaterialApp(
home: new DefaultTabController(
length: 6,
child: Scaffold(
bottomNavigationBar:
new Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height*0.1,
alignment: Alignment.centerRight,
child: new Container(
color: Colors.blue,
width: MediaQuery.of(context).size.width* 2/3,
alignment: Alignment.centerRight,
child: new Row(
children: <Widget>[
new Expanded(child: new Container(
color : Colors.yellow,
child: new Text('22 : 22' ),
alignment: Alignment.center,
)),
new Expanded(child:new Container(
color: Colors.pink,
child: new Text(' 37.8 °C'),
margin: new EdgeInsets.all(MediaQuery.of(context).size.width*0.02),
alignment: Alignment.centerRight,
))
],
),
),
),
Thank you for helping.

You could use a Stack and position one of the widget absolute over the other one:
new Stack(
children: <Widget> [
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget> [
new Text(time),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget> [
new Text(temperature)
],
),
],
),
where time & temperature are variables that were set within the state (Stateful Widgets). Then just include it in bottomNavigationBar.

I eventually added my previous code in a StatelessWidget and call it in the bottomNavigationBar field of the Scaffold : it does the job.
And I call MediaQuery.of(context) within the StatelessWidget created
Thank you.

Related

flutter onboarding - how to keep "proportions"?

I created onboarding in my flutter app:
This is my data model:
class Data {
final String image;
final String title;
final String desc;
Data(this.image, this.title, this.desc); }
final List<Data> items = [
Data('assets/1.png', '1', '1'),
Data('assets/2.png', '2', '2'),
Data('assets/3.png', '3', '3')
];
This is my code:
Scaffold(
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
PageView.builder(
controller: _pageController,
itemBuilder: (BuildContext context, int index) {
var item = items[index];
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(item.image),
fit: BoxFit.cover,
),
),
//bloc1
child: Padding(
padding: const EdgeInsets.only(bottom: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text(item.title), Text(item.desc)],
),
),
);
},
),
//bloc 2
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Padding(
padding: EdgeInsets.only(bottom: 10, top: 10),
child: Text('****dots indicators****'),
),
TextButton(
onPressed: () {},
child: Text('Next'),
)
],
))
],
),
);
This onBoading consists of three parts:
background image
text block - block1
"lower action block" - block2.
I need to have a small fixed distance between blocks 1 and 2 - 10pх.
but also I can't place block1 and block2 together. I need block1 to be "inside" PageView, block2 on the main page.
right now I'm using the bottom padding. but this is not a reliable solution - this size may change on different screens - "overlapping" will occur.
how can I fix this problem? Any advice - I'll be very grateful.
If you want to position your "page indicator dots" at a fixed relative spot, for example, 10% from the bottom of the screen, an easy solution is to use the Align widget.
However in your case, you must also change the Column in your to MainAxisSize.min, so that its height will be as small as possible, leaving you enough freedom to decide where to position the Column vertically. For example:
SafeArea(
child: Align(
alignment: Alignment(0, 0.95), // relative position
child: Column(
mainAxisSize: MainAxisSize.min, // make Column shorter
children: [
Text('****dots indicators****'),
TextButton(
onPressed: () {},
child: Text('Next'),
)
],
),
),
),
For the alignment property of the Align widget, the values are (x, y) ranging from -1 to +1, with 0 being the center. For example, you can use alignment: Alignment(0, -0.5) to make it center horizontally, and 50% towards the top on the vertical axis.

Flutter - How to wrap list of chipsets with a button horizontally together

I'm new to flutter and have been trying to get a list of chipsets wrapped in a Wrap widget with the ability to add more of them through a button shown in the image. However, the button isn't able to wrap along with the chipset horizontally. Below is an image of the design to make it clearer.
Code:
Container(
child: Wrap(
children: [
Container(
child: Wrap(
children: _chipsetList,
),
),
SizedBox(width: 2),
Container(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
heroTag: null,
elevation: 0,
shape: StadiumBorder(
side: BorderSide(width: 2.0)),
onPressed: () {
_getMoreChips(context);
},
child: Icon(Icons.add),
),
))
],
),),
I tried to experiment with SingleChildScrollView property or with Wrap direction but in vain. What could be a way to get this design working?
Seems you want to put chips and the button in the single wrap. To do so, combine them in a single list and use this list as wrap's children
List<Widget> items = List.from(_chipsetList); // copy
Widget button = FloatingActionButton();
items.add(button);
Wrap(
children: items,
)
Or, using spread operator
Wrap(
children: [
..._chipsetList,
FloatingActionButton(),
],
)

Fix minimum width to a Widget which needs to expand in Flutter

I need to fix a minimum width to my Column Widgets. Inside each of them, I have Text Widgets which can be very short or very long. I need to fix a minimum width to them in order to have an acceptable size of Column even if the text is short. The other Column need obviously to adapt himself.
Row(children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child: RichText(
text: TextSpan(
text:"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
],
),
],
)
There's probably a dozen ways to do what you want. And likely none of them straightforward or easy to understand. (The subject of constraints & sizes is quite complicated. See this constraints page for more examples & explanations.)
Here's one potential solution.
This will set a minimum width for the blue column (based on stepWidth), but will expand/grow if the text (child) inside wants to.
The yellow column will resize to accommodate the blue column.
class ExpandedRowPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expanded Row Page'),
),
body: SafeArea(
child: Center(
child: Row(
children: [
IntrinsicWidth(
stepWidth: 100,
// BLUE Column
child: Container(
color: Colors.lightBlueAccent,
child: Column(
children: [
//Text('Short'),
Text('shrt')
],
)
),
),
// YELLOW Column
Flexible(
child: Container(
alignment: Alignment.center,
color: Colors.yellow,
child: Column(
children: [
Text('Very lonnnnnnnnnnnnnnnnnnnnnnnnnnnng texttttttttttttt'),
],
)
),
)
],
)
),
),
);
}
}
You could do the above without a Flexible yellow column, but a very long text child would cause an Overflow warning without a Flexible or Expanded wrapping widget.
A Row widget by itself has an infinite width constraint. So if a child wants to be bigger than screen width, it can, and will cause an overflow. (Try removing Flexible above and rebuild to see.)
Flexible and Expanded, used only inside Row & Column (or Flex, their superclass), checks screen width and other widgets inside a Row, and provides its children with a defined constraint size instead of infinite. Children (inside Flexible/Expanded) can now look up to parent for a constraint and size themselves accordingly.
A Text widget for example, will wrap its text when it's too wide for constraints given by Flexible/Expanded.
use FittedBox();
suppose Example:
Row(
children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child:
FittedBox(
child: RichText(
text: TextSpan(
text:
"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
),
],
),
],
);

Image to take the height and with of parent element

so today i did good with advancing in learning to make an app with flutter , i made a ListView , but the image didnt take the full height and with of the parent element , i tried some solutions but it didnt workout
this is the class
class FlowersItem extends StatelessWidget {
final String imgAssetPath;
FlowersItem({this.imgAssetPath});
#override
Widget build(BuildContext context) {
return Container(
width: 200,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 30),
margin: EdgeInsets.only(right: 16),
decoration: BoxDecoration(
color: Color(0xff29404E),
borderRadius: BorderRadius.circular(12)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(children: <Widget>[
ClipRect(
child: FittedBox(
child: Image.asset(imgAssetPath),
fit: BoxFit.fill,
),
)
],)
],
),
);
}
}
List<FlowersItem> flowers = [
FlowersItem(
imgAssetPath: 'assets/images/flower1.jpeg',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
];
Have you tried BoxFit.cover? I think that's what you are looking for.
It generally works for me when I want to fill out and entire box with an image.
have you tried Expanded class?
So, Expanded class is A widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
you could find the documentation here.

How to dispose/recreate a Widget after an action

I am trying to figure out how to destroy/recreate a Widget based on an action (e.g: onPressed).
The way I thought about this, is to have my Widget rapped within an Opacity object, and control the state of the Opacity object based on user interaction somewhere in my app(i.e: hide/show the widget instead of dispose/recreate ). However, what I am asking here, how to destroy/recreating a Widget after clicking a Button?
I have created the following dummy example to show what I mean.
The red Icon should be disposed when I press the cloud Icon and recreated when I press the RaisedButton.
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Destroy/Recreate Example"),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Stack(fit: StackFit.passthrough,
children: <Widget>[
new IconButton(icon: new Icon(
Icons.cloud_circle, size: 40.0, color: Colors.blue,),
onPressed: null /*_destroyWidget*/),
new Positioned(child: new DecoratedBox(
decoration: new BoxDecoration(shape: BoxShape.circle),
child: new Icon(
Icons.add_circle, size: 20.0, color: Colors.red,),),
top: 3.0,
left: 3.0)
],
),
new RaisedButton(onPressed: null /*_recreateWidget*/,
child: new Text("Recreate!"),
),
])
)
);
}
How to start on this idea?
Update
The following code achieves the same thing but by manipulating the Opacity of the red Icon (show/hide).
var _myOpacity = 0.0;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Destroy/Recreate Example"),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Stack(fit: StackFit.passthrough,
children: <Widget>[
new IconButton(icon: new Icon(
Icons.cloud_circle, size: 40.0, color: Colors.blue,),
onPressed: ()=>setState((){
_myOpacity =0.0;
}) /*_destroyWidget*/),
new Positioned(child: new Opacity(
opacity: _myOpacity,
child:
new DecoratedBox(
decoration: new BoxDecoration(shape: BoxShape.circle),
child: new Icon(
Icons.add_circle, size: 20.0, color: Colors.red,),),),
top: 3.0,
left: 3.0)
],
),
new RaisedButton(onPressed: ()=>
setState((){
_myOpacity = 1.0;
})
/*_recreateWidget*/,
child: new Text("Recreate!"),
),
])
)
);
}
You will have to wrap your red icon in a StatefulWidget if you want to be notified when it is initialized and disposed. A StatelessWidget doesn't have these callbacks.
You can replace the StatefulWidget with null in a setState and its State will be disposed. You can set it back to normal in a second setState callback, and a new State will be created and its initState will be called.
If you want to dispose and initState without going through the intermediate step of having a widget be replaced with null, try giving your StatefulWidget a new UniqueKey when the recreate button is pressed. This will prevent Flutter from associating the old State with the new StatefulWidget.
It seems like you're mostly doing this out of curiosity rather than a genuine use case. The shopping card example you've described probably doesn't need to use initState and dispose at all and you should just use a StatelessWidget.