Flutter two widgets in body? - flutter

So my flutter app works fine, however I want to make some changes to it.
The 1st change I want to do is create a horizontal scroll widget that has images that are clickable that change stations.
But to do this I first need to join two widgets into one.
In my home_widget.dart file I have this code:
final List<Widget> _children = [TracksWidget(),
NewsWidget(),
AboutWidget()];
The code above changes the body section of the home_widget.dart section. But now what I want to do is add StationsWidget() to the bottom of the TrackWidget() - Note this widget refreshes every 30 seconds. So ideally I need to make sure it does not refresh with it.
So can a body have two widgets?
Full code of test.dart (which is where I am trying to add the widget)
import 'package:flutter/material.dart';
import 'trackswidget.dart';
class TestWidget extends StatelessWidget {
// final Color color;
// PlaceholderWidget(this.color);
#override
Widget build(BuildContext context) {
double c_width = MediaQuery.of(context).size.width;
return new Container (
padding: const EdgeInsets.all(16.0),
margin: const EdgeInsets.only(bottom: 0.0),
width: c_width,
child: new SingleChildScrollView(
child: new Column (
children: <Widget>[
Column(
children: <Widget>[
Child: TracksWidget()
],
),
Column(
children: <Widget>[
new Text('Advertise on ',style: TextStyle(color: Colors.black, fontSize: 20.0),),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
),
],
),
]
),
),
);
}
}
The error I am getting is
'Widget' is from 'package:flutter/src/widgets/framework.dart' ('/C:/src/flutter/packages/flutter/lib/src/widgets/framework.dart').
Try changing the type of the parameter, or casting the argument to 'List'.
children: TracksWidget,
Just so you all know what I am trying to achieve. We redesigned our iOS Swift app and now want our flutter app to match.

Strictly speaking, no, the body takes exactly one Widget. You could say it takes none if you pass null, but you cannot pass more than one.
However, there are widgets that group other widgets. Your one body widget could as well be a Row and that row can have multiple child widgets.
You already did that in your title.
A nice graphical representation can be found in the documentation.

Related

Flutter "CircularProgressIndicator" widgets breaks widgets alignement

I'm currently building a scrapping a scrapping application using flutter.
I encounter a problem when I try to display a loader while scrapping, the apparition of the loader seems to totally break the Cross Axis Alignement of my Columns.
First my application looks like this :
https://i.stack.imgur.com/6Tbz7.png
Then, when I hit "scrap button", I update my state in order to display a loader, and this happens :
https://i.stack.imgur.com/0MIi6.png
Here are the two pieces of code rendering the application :
My main class rendering a Flutter logo & my main widget
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FlutterLogo(
size: 400,
style: FlutterLogoStyle.horizontal,
),
ScrapBody(),
],
),
),
);
}
}
My main Widget containing rendering management logic as follow
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ScrapForm(
scrap: scrap,
exportToCsv: exportToCsv,
isScrapSuccess: isScrapSuccess,
),
isLoading
// ? Container()
? Column(
children: [
CircularProgressIndicator(),
Text(
"Scrapping page ${pageScrapIndex.toString()} on ${totalPages.toString()}",
),
],
)
: Column(
children: [
ScrapResult(
reviewerListResult: reviewerList,
),
],
),
],
);
}
As you can see, I tried to constraint the widgets that composes my Column with " crossAxisAlignment: CrossAxisAlignment.center" in both parts, but it doesn't work, the widgets keeps goes on the left when I render my loader, and only when I render my loader.
After many searches about the Circuler loader and a look in the widget core,I didn't find anything that could explain my case, any help would be so
appreciated, thanks in advance.
try to wrap your base column with Container and give it's width as double.infinity. and also add crossAxisAlignment: CrossAxisAlignment.center for your circular progress dialog's Column if the first solution doesn't work.

Widget flickers and disappears when scrolling

I'm already losing sleep over this.
I'm trying to display a chart inside a ListView (for scrolling). For some reason the contents of the Card flickers when scrolling and randomly completely disappears (the Card itself stays visible though).
Any idea why would that happen?
(...) ListView (...)
children: [Row ( children: [buildChartBox()] )] (...)
Expanded buildChartBox() {
return Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
chartTitles(
title: 'Items',
subtitle: 'by value'),
SizedBox(
height: 300,
child: ValuesChart(data: calculateValues(items)))
],
),
],
),
),
),
);
}
Row chartTitles({String title = '', String subtitle = ''}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: text_charttitle),
Text(subtitle, style: text_chartsubtitle),
],
)
],
);
}
Things tried:
Both of these were originally Stateless Widgets; I changed to simple
methods to simplify but it didn't change the weird behaviour.
Replacing the chartTitles return with an empty Container (i.e. removing the titles) does mitigate the issue. The chart then stays displayed but also flickers slightly.
Replacing the ListView with a SingleChildScrollView doesn't change anything.
EDIT: Code for the ValuesChart:
import 'package:fl_chart/fl_chart.dart';
class ValuesChart extends StatelessWidget {
final Map<String, int> data;
const ValuesChart({required this.data});
#override
Widget build(BuildContext context) {
return Container(
child: PieChart(
_theData(data),
));
}
}
Note I'm using a package called 'fl_chart'. _theData just returns various parameters for the chart, I don't think it's relevant.
Try to replace ListView with SingleChildScrollView
ListViews in flutter by default using what it is called in Android RecyclerView to efficiently use render resources.
If you are interested here an article
https://medium.com/1mgofficial/how-recyclerview-works-internally-71290de5d2c4

Flutter baseline text alignment with Wrap class

Using the Row class, I can make the text baseline aligned with this property:
crossAxisAlignment: CrossAxisAlignment.baseline,
But this property seems not to be available on the Wrap class.
The benefit of using Wrap instead of Row is that it allows having multiline text. While the Row class force the content to stay into one line.
How can I keep the benefit of Wrap, while making the text baseline aligned?
I also had this problem. There is an open issue in the Flutter Repo addressing this. While the built-in solution is not implemented yet, I did come up with a slightly-hacky workaround.
Basically, depending on your font and your needs...
Set your Wrap() to have crossAxisAlignment: WrapCrossAlignment.end,. Then you can make one of the children of your Wrap() a Column() that has a SizedBox() as the lowest child, with the height that you need to make it appear like your texts are using the does-not-exist WrapCrossAlignment.baseLine
Example of the problem:
Example of the solution as outlined above (I did point out that it's kind of hacky):
The Code:
class WrapBaselineHackWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(border: Border.all(color: Colors.red)),
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.end,
spacing: 8,
children: [
Text(
'\$50,000.00',
style: TextStyle(fontSize: 24),
),
Column(
children: [
Text('Is a lot of money'),
//this is needed because Wrap does not have WrapCrossAlignment.baseLine
const SizedBox(height: 3),
],
),
],
),
);
}
}
Keep using Row and simply wrap Text widget with Expanded or Flexible widget.

How to Implement Flutter Functions

With reference to a Stack Ordering solution (Flutter - changing a Stack Order)
Summary - I have a stack of widgets I want to reorder. The solution is to use functions to recreate the correct order of widgets. In the example linked to above works (great!). However, the example widgets were small - no issue to simply repeat the same code to re-order.
My real world example - the stack of widgets is reasonably complex and I have refactored into functions to reuse between the stack order functions:
Let's say the original stack has this as one of the widgets in the stack:
final statusMessage = new Container(
padding: new EdgeInsets.all(3.0),
margin: new EdgeInsets.only(bottom: 0.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Text(
statusText,
style: themeData.textTheme.subhead,
),
],
),
alignment: Alignment.topCenter);
I have been declaring all these widgets in the single Widget build class.
The functions to reorder the stacks are outside of this build function. An example:
void swapStackChildren() {
setState(() {
stackChildren = [
Positioned.fill(
child: statusMessage,
key: GlobalKey(),
),
Positioned.fill(
child: widget2, // a complex widget
key: GlobalKey(),
),
etc....
];
});
}
Ideally, I need a way to (forward) reference the widgets in swapStackChildren that are declared in the build method or a way to reference 'context' outside of the build method so I can reference themeData.
Perhaps it is my lack of understanding of the structure/layout of a page? I have only one Widget build class where I am declaring all my widgets (header, content area, buttons, etc) and these cannot be referenced by functions in the preceding code.

Positioned widgets must be placed directly inside Stack widgets

I am trying to implement gridview with image and a text inside it. where i want text at the bottom of image with black background. Here is my code for ListItem
class ListItem extends StatelessWidget {
String url;
String name;
ListItem(this.url, this.name);
#override
Widget build(BuildContext context) {
return new Container(
child: new Column(
children: <Widget>[
new Image.network('${url}', fit: BoxFit.cover),
new Positioned(
child: new Container(
child: new Text('${name}',
style: new TextStyle(fontSize: 20.0, color: Colors.white)),
decoration: new BoxDecoration(color: Colors.black),
padding: new EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0)),
left: 0.0,
bottom: 108.0,
)
],
));
}
}
With this code it is showing error
Positioned widgets must be placed directly inside Stack widgets.
Positioned(no depth, dirty) has a Stack ancestor, but there are other widgets between them:
- Column(direction: vertical, mainAxisAlignment: start, crossAxisAlignment: center)
Issue was with Column, after changing few lines from here and there i finally found that it was because of Column
Once i change Column to Stack, it works fine.
return new Container(
child: new Stack(
We were just discussing this yesterday. Positioned can actually be used in more than just a Stack, so the docs aren't exactly right about that. It can't be used in anything that renders, and the docs are very specific about RenderObjectWidget:
"A Positioned widget must be a descendant of a Stack, and the path from the Positioned widget to its enclosing Stack must contain only StatelessWidgets or StatefulWidgets (not other kinds of widgets, like RenderObjectWidgets).
Source: https://docs.flutter.io/flutter/widgets/Positioned-class.html
Column is descended from RenderObjectWidget:
... Widget > RenderObjectWidget > MultiChildRenderObjectWidget > Flex > Column
Most people starting out in Flutter are only aware of StatelessWidget and StatefulWidget, but there are others and knowing them can be very important at times.
Widget:
StatefulWidget
StatelessWidget
RenderObjectWidget
ProxyWidget
PreferredSizeWidget
More at:
https://docs.flutter.io/flutter/widgets/Widget-class.html