Flutter - Stack with Scaffold - flutter

I'm currently using Scaffold with BottomNavigationBar in a project and need to display a separated widget on top of all that.
Tried to create a Stack on the build return and put this widget and the Scaffold as the children, but the widget is simply not displayed (not showed at all)! There isn't any error messages either.
What could be wrong? Or there is any other approach? (calling AlertDialog won't work for this purpose).
Defining the Stack on the body of the Scaffold didn't work also, as it need a list for the BottomNavigationBar.
Widget build(BuildContext context) {
var Test = Center(
child: SizedBox(width: 100, height: 100,
child: Container(
color: Colors.blue,
child: Text("Test"),),),);
return Stack(
alignment: Alignment.center,
children: [
Test,
Scaffold(
appBar: ..... (rest of the code)

It is because your Scaffold is drawn over your Test widget. Stack takes multiple children and orders them from bottom to top. So the first item is the bottom-most and the last is the top-most. Try the following:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Scaffold(
appBar: AppBar(title: Text('Hi')),
),
TestWidget(),
],
),
);
}
}
class TestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
color: Colors.blue,
child: Center(
child: Text("Test"),
),
);
}
}

As #HBS mentioned, the problem was caused by the Stack ordering, but the fixing can be achieved just by changing the Widget order:
Widget build(BuildContext context) {
var Test = Center(
child: SizedBox(width: 100, height: 100,
child: Container(
color: Colors.blue,
child: Text("Test"),),),);
return Stack(
alignment: Alignment.center,
children: [
Scaffold(
appBar: ..... (rest of the code),
Test,
],

Related

Display aspect ratio item and image in a row in flutter

Let's say that I want create a Flutter app. In my app I want to create a Row widget with the following children:
AspectRatio(aspectRatio: 1, child: Center(child: Text("I am text!"))
Image.asset("path/to/asset.png") with unknown aspect ratio
I want to display that Row while keeping both aspect ratios intact. How can I do that?
Here is my attempt:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("This is my app")),
body: Container(
child: Row(children: [buildItem1(), buildItem2()]),
),
);
}
Widget buildItem1() {
return AspectRatio(
aspectRatio: 1,
child: Container(
color: Colors.red, child: Center(child: Text("This is my text"))));
}
Widget buildItem2() {
return Image.asset("path/to/my/asset.jpg");
}
}
And this is what being displayed:
I am trying to figure out a way to automatically shrink the row height such that both items would fit the screen.
If I use a fixed hight like that:
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("This is my app")),
body: Container(
height: 300,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [buildItem1(), buildItem2()],
),
),
);
}
...
Than I get the following:
Which is better, but I want to fill the entire width of the screen.
Thanks for anyone who can help!
You can use Expanded on second widget, that will get the avialable space on row. Also for the image use fit: BoxFit.cover(better looks than width).
body: Container(
height: 300,
child: Row(
children: [buildItem1(), Expanded(child: buildItem2())],
),
),
Widget buildItem2() {
return Image.asset(
"assets/images/user.png",
fit: BoxFit.cover,
);
}
Now if you want full screen, I will prefer
Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(
color: Colors.red,
child: Center(
child: Text("This is my text"),
)),
),
Expanded(
child: Image.asset(
"assets/images/user.png",
fit: BoxFit.cover,
)),
],
),
Also LayoutBuilder on scaffold's body provide more options. Also check IntrinsicHeight.

My costume widget is not showing in a Column

So i have created a costume widget and i wanted to show it in a column, but whenever i put it in a column and run the application the widget doesn't show on the screen.
This is my costume Widget
#override
Widget build(BuildContext context) {
return new FractionallySizedBox(
widthFactor: 1,
heightFactor: 0.3,
child: Container(
child: new LineChart(linechartData()),
margin: EdgeInsets.fromLTRB(0, 10, 0, 0),
),
);
}
and this is my main.dart widget
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("hello"),
),
body: new Container(
child: new Column(
children: [
new Container(child: new Text("hello")),
new Chart()],
)),
),
);
}
}
Ive tried to check if the problem is with the column widget by removing my costume widget from the column widget and by putting a text widget but the text widget shows fine the problem is when i add my costume widget inside it that everything desapears
You need to wrap your widget inside the Flexible one, like this:
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("hello"),
),
body: new Container(
child: new Column(
children: [
new Flexible(child: Costume()),
new Chart()],
)),
),
);
}
}
CHeckout FractionallySizedBox (Flutter Widget of the Week) video
You can wrap the FractionallySizedBox with Expanded to get available height and then heightFactor will be used its child
body: Container(
child: Column(
children: [
Container(
child: new Text("hello"),
),
Expanded(
child: FractionallySizedBox(
widthFactor: 1,
heightFactor: 0.3,
child: Container(
),
),
)
],
),
),
Also you might be interested on LayoutBuilder

Which layout structure should I code to match my app design

For my new Flutter project I've done some research on layouts, however it still is a bit vague.
Here is the layout I'd like to create:
After some research and watching some videos, it seems this is the MaterialApp code:
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Color(0xFF0E2E40),
title: Text('City Discovery'),
actions: [
Image.asset(
'assets/images/logoicon.png',
width: 35,
)
],
),
body: ListView(
children: [
introSection,
Image.asset(
'assets/images/barman.png',
width: 600,
height: 240,
fit: BoxFit.cover,
),
crimeSection,
mysterySection,
bottomSection,
],
),
),
);
}
But now defining the layout of the different Sections is quite hard.
From what I can tell, there should be:
ListView to make my page scrollable, which it should be
introSection: Container for XYZ with 2 rows for 2 text sections.
Image
crimeSection: Container for XYZ with 3 rows for 2 text sections and button. First text section divided into 2 colums for icon and text
mysterySection: Container for XYZ with 2 rows for 2 text sections. First text section divided into 2 columns for icon and text
bottomSection: Tabs? Although tabs only seem to be part of the appbar, so not sure what the alternative is
The closest example I could find, however changing the code doesn't get me anywhere:
https://github.com/flutter/website/blob/master/examples/layout/lakes/step6/lib/main.dart
For some reason containers can only have 1 child, so that probably means I need a row in my container which then has children which then has 2 childs for both text sections? Incredibly hard to code some simple UI.
If someone can help me with the code for the introSection and the bottomSection, I can probably work out the rest myself.
I recommend to create components folder for reusable widgets, as buttons, logos, text, etc.
If you have a widget that does not used in other components, you can separate it in the same file but use underscore, to make this widget private (It will be visible only inside this file). All that will make your code more readable.
About bottom tabs.
If you want to use it as bottom tabs, you can put it in bottomNavigationBar parameter of Scaffold widget. If you need to use in inside the ListView, it possible but you need to pass the exact height of the tab, because TabView trying to expand as much as possible, same as ListView.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutExample(),
);
}
}
class LayoutExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _BottomNavigationBar(),
body: ListView(
children: <Widget>[
_IntroSection(),
Placeholder(fallbackHeight: 200),
_CrimeSection(),
_MysterySection()
],
),
);
}
}
class _IntroSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('Intro text1'),
Text('Intro text2')
],
),
);
}
}
class _CrimeSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('CrimeSection'),
);
}
}
class _MysterySection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('MysterySection'),
);
}
}
class _BottomNavigationBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
);
}
}

flutter statfulWidget refresh twice

return MaterialApp(
home: Scaffold(
body: RefreshIndicator(
key: _globalKey,
onRefresh: refresh,
child: Sub(),
),
),
);
there is simple refreshindicator and sub Widget
class Sub extends StatefulWidget {
#override
_SubState createState() => _SubState();
}
class _SubState extends State<Sub> {
#override
Widget build(BuildContext context) {
print('sub');
return Container(
color: Colors.amber,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 300,
color: Colors.blue,
),
Container(
height: 300,
color: Colors.red,
),
Container(
height: 300,
color: Colors.green,
),
],
),
),
);
}
}
Sub Widget print "sub" when it is built
the point is when i touch or just slightly drag page(not enough call refreshindicator) sub widget is rebuilt TWICE. i don't know why and i don't know how can i slove.
(statelesswidget can solve that problem but i need to use statefulwidget)
It depends what you want to achieve without re-building but alternate I used was for flutter charts. Create a object Sub sub1=Sub(); , somewhere outside build() or intiState() , then this widget will not rebuild again and values will be same.

How can i move a widget left and right until the available space is filled?

I'm a beginner and still learning flutter, please forgive me if am getting something wrong here.
So i have a Stack inside of which i have 2 Widgets. Widget1 and Widget2.
I want to center the Widget B right below Widget A.
NOTE: Widget 2 is larger than Widget1.
class MyWidgets extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Widget1,
Positioned(
top: widget1PositionFromTop + widget1Size,
left: widget1PositionFromLeft,
child: FractionalTranslation(
translation: Offset(-0.5, 0.0),
child: Widget2,
),
)
],
);
}
}
The Problem is, if the Widget1's position from left is 0, or less than half the size of Widget2, the Widget2 is overflowed, and only half or a part of the Widget2 can be seen.
I want to know how can i only translate its position as long as there is space left, i mean if there is space left only for 0.3 of Widget2 then it will move only -0.3 not -0.5..
Thank you.
If you want this using Stack then
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Container(width: 200, height: 200, color: Colors.red),
Container(width: 100, height: 100, color: Colors.blue),
],
),
);
}
}
which gives
Maybe you could use Column like
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(width: 200, height: 200, color: Colors.red),
Container(width: 100, height: 100, color: Colors.blue),
],
),
);
}
}
with the end result as