Flutter || how to make three conditions in single container - flutter

I am working on a UI where I have 3 checks in the same container.
I am able to achieve only one condition but not able to the second one or third one.
till now I have created a container where I have made a column and included all things and used a bool variable which changes when I click the text and it reverts back when I click the close button.
But now the problem is How can I use 3 conditions in the same column?
my code till now
bool makePayment = false;
makePayment ? Column( crossAxisAlignment:
children: [
const Text('Quick actions'),
const SizedBox(),
Row(),
Row()
]) : Column()

you could use a lot of condition in the same way as you did just the question will be more complicated , example :
A.isNumber ? do1 : A.isAlpha? do2 : A.isSymbol ? do3 : do4

You can use else-if into your column children.
The Syntax is
Column(
children: <Widget>[
if(your condition) ...[
//YOUR CODE
] else if(your condition) ...[
//YOUR CODE
] else ...[
//YOUR CODE
]
]
)

Related

Create Flutter layout of rows and columns from map

How would it be possible to dynamically create rows and columns in flutter using a map element as the schematics?
If I had the following map:
"rows":{
0:{
"cols":{
0:{"text":"ABC"},
1:{"text":"DEF"},
2:{"text":"GHI"},
},
},
1:{
"cols":{
0:{
"rows":{
0:{"text":"JKL"},
1:{"text":"MNO"}
},
},
1:{"text":"PQR"},
2:{"text":"STU"},
},
},
},
how would I make it into a series of flutter widgets:
Row(
children:[
Column(children: <Widget>[Text("ABC"),]),
Column(children: <Widget>[Text("DEF"),]),
Column(children: <Widget>[Text("GHI"),]),
),
Row(
children:[
Column(children:
Row(children: [
<Widget>[Text("JKL"),
<Widget>[Text("MNO"),
],
),
Column(children: <Widget>[Text("PQR"),]),
Column(children: <Widget>[Text("STU"),]),
]
)
I'd like it so that the number of levels deep is dynamic/nested widgets is infinite, that is, it doesn't iterate two levels down and then just stop.
To date, I've tried using for loops inside functions which refer to themselves, but I can't quite get it.
You can try a Map.forEach() Recursion and validate for "cols" and "rows"something like this:
recursiveColsAndRows(Map blob) {
blob.forEach((key, value) => {
if(key == "cols") {
// Do a recursion
recursiveColsAndRows(value)
},
if(key == "rows") {
// Do a recursion
recursiveColsAndRows(value)
},
print(value)
});
}
But with infinite nesting the way you think about, will bring you other big problems very soon, because you cannot display it infinitely without any scrolling features. That means after your third or fourth iteration, you will get an Overflowed Error because your Rows fall out of the Screen.
Infinite nesting the way you try to accomplish is not a good approach for displaying different data. Try to create proper widgets which fit your different types of needs.
PS: Are you maybe searching for a Table feature?

Get image and text side by side flutter

I want to get my AssetImage and Text side by side each other. To achieve that I used a row and it is being displayed like this:
Row(
children: [
Image.asset('assets/images/pfp.png',height: height*0.1,),
Column(children: [Text("we")],)
],
)
I want the image to be displayed in this way:
I want the text to start from the top of the image. How do I achieve that? Below is the current code I have that displayed it as the first image:
Use crossaxisalgnment
Row(
crossAxisAlignment : CrossAxisAlignment.start,
children : [
Image.asset(""),
Text(""),
]
)
Just add a cross axis alignment property to your Row widget
Set it to crossAxisAlignment: CrossAxisAlignment.start
You will have the expected result ✔️

How to display a column when a variable is true in Flutter?

I keep getting this error that res is not defined, so I am trying to figure out how to run the column code after res is defined like in js you can do {res && (code)}.
Column(
children: res['rooms'].map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}'
)),
),
You can check if your res variable is equal to null.
This is the non nullable approach to your problem, but you should check to migrate your project to null safety to avoid all those null checks.
res == null
? Column(
children: res['rooms'].map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}')),
)
: Container(),
It can be hard to read ternary expressions sometimes if you have a large widget within a expression. It also requires you to provide an "else" widget.
I approach this with the spread operator, with a single if statement
Column(
children: <Widget>[
if (res != null)
...res.map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}')),
],
)
Simple use ternary login like this -
Container(
child: res != null
? Column(
children: []
)
: SizedBox() //Use SizedBox instead of Container for better efficiency
)
And update the UI again once "res" is populated.

Why use if and for within a list definition in Dart?

Dart supports using "if" and "for" during creation of a list :
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
and:
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0',
for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');
What is the point of this ? How is it better than creating a list, and appending to it afterwards like in other programming languages:
var nav = [
'Home',
'Furniture',
'Plants',
];
if (promoActive) nav.add('Outlet');
There are multiple factors playing a role:
performance
readability
Readability
The main reason why this feature was implemented is for ListView/Stack and all other widgets with a children parameter.
These widgets do not support null as parameter, which caused a significant amount of frustration (which led to this github issue: Allow null values in child or children[] collections to signal that an element should not be drawn)
In short, the problem is that the declarative nature of widgets means that using add & co isn't really an option.
Without if/for inside collections, we would have to write:
List<Widget> children = [
Foo(),
]
if (condition)
children.add(Bar());
return Scaffold(
body: ListView(
children: children,
),
);
which makes it difficult to understand what is rendered on screen since the build method is now fragmented
Alternatively, we would have to write:
return Scaffold(
body: ListView(
children: [
Foo(),
condition ? Bar() : null,
].where((e) => e != null).toList(),
),
);
This is more readable but significantly lack in flexibility as anything more complex than this example will be difficult to implement
As a solution, we can now write:
return Scaffold(
body: ListView(
children: [
Foo(),
if (condition)
Bar(),
]
),
);
This is both readable, easy to write, and not error-prone.
Performance
An interesting aspect of this feature is, it increases the performance of your Flutter apps.
On thing to consider when writing:
final list = <Widget>[
Foo(),
];
if (condition)
list.add(Bar());
is that by using add, the list size changes over time. This means that any add can potentially cause the List to be re-allocated to support more items, which is expensive.
The same issue applies to:
ListView(
children: [
Foo(),
condition ? Bar() : null,
].where((e) => e != null).toList(),
)
where we are effectively instantiating the List twice and iterating over all of its items twice too (once for the where, another time by ListView)
These performance issues do not happen when using if/for inside collections.
When writing:
ListView(
children: [
Foo(),
if (condition)
Bar(),
],
);
this immediately allocates the List with the correct size, and the allocation if performed once and only once.
The reason is, in reality this syntax is equivalent to:
List<Widget> children;
if (condition)
children = [
Foo(),
Bar(),
];
else
children = [
Foo(),
]
which involves neither add nor where/toList
I read the following proposal to understand this better:
https://github.com/dart-lang/language/blob/master/accepted/2.3/spread-collections/feature-specification.md
A key goal of Flutter's API design is that, as much as possible, the
textual layout of the code reflects the nesting structure of the
resulting user interface.
It seems that the reason is simply for code readability purposes in flutter. For example, the following code:
var command = [
engineDartPath,
frontendServer,
];
for (var root in fileSystemRoots) {
command.add('--filesystem-root=$root');
}
for (var entryPointsJson in entryPointsJsonFiles) {
if (fileExists("$entryPointsJson.json")) {
command.add(entryPointsJson);
}
}
command.add(mainPath);
can instead be written in a more concise form:
var command = [
engineDartPath,
frontendServer,
for (var root in fileSystemRoots) '--filesystem-root=$root',
for (var entryPointsJson in entryPointsJsonFiles)
if (fileExists("$entryPointsJson.json")) entryPointsJson,
mainPath
];
There are many more examples in the document, but the short answer seems to be simply for readability and conciseness of code.

Return a list of widgets in Flutter

Column(
children: <Widget>[
...myObject
.map((data) => Text("Text 1"), Text("Text 2")),
]
);
This block of code will fail because I'm returning 2 widgets instead of one. How could I fix it and return as many widget as I want without creating another column inside the map?
First you cant use an arrow function to return multiple values, you need to change it to a normal function that returns a list of widgets. Second, you need to use the .toList() method since .map is lazy and you need to iterate in order to map execute.
With this 2 steps you are going to end with a List<List<Widget>> and you should flat it before return it to a column that needs a List<Widget>. This can be achieved with the Iterable.expand() with an identity function.
You can try something like this:
Column(
children: <Widget>[
..._generateChildrens(myObjects),
],
),
And the actual implementation to obtain the widgets is:
List<Widget> _generateChildrens(List myObjects) {
var list = myObjects.map<List<Widget>>(
(data) {
var widgetList = <Widget>[];
widgetList.add(Text("Text 1"));
widgetList.add(Text("Text 2"));
return widgetList;
},
).toList();
var flat = list.expand((i) => i).toList();
return flat;
}
Hope it helps!