Can't I write braces in an if statement in List? - flutter

The following without braces worked fine:
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
const isFlag = true;
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
if (isFlag)
Text(
"Demo true",
)
else
Text(
"Demo flase",
)
],
),
),
);
}
}
I prefer to add braces even if there is only one expression.
I did the following and it resulted in an error.
The code that causes an error:
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
const isFlag = true;
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
if (isFlag) {
Text(
"Demo true",
)
} else {
Text(
"Demo flase",
)
}
],
),
),
);
}
}
Error:
lib/main.dart:21:25: Error: A value of type 'Set<Text>' can't be assigned to a variable of type 'Widget'.
- 'Set' is from 'dart:core'.
- 'Text' is from 'package:flutter/src/widgets/text.dart'
('../../../flutter-command/flutter/packages/flutter/lib/src/widgets/text.dart').
- 'Widget' is from 'package:flutter/src/widgets/framework.dart'
('../../../flutter-command/flutter/packages/flutter/lib/src/widgets/framework.dart').
if (isFlag) {
^
lib/main.dart:25:20: Error: A value of type 'Set<Text>' can't be assigned to a variable of type 'Widget'.
- 'Set' is from 'dart:core'.
- 'Text' is from 'package:flutter/src/widgets/text.dart'
('../../../flutter-command/flutter/packages/flutter/lib/src/widgets/text.dart').
- 'Widget' is from 'package:flutter/src/widgets/framework.dart'
('../../../flutter-command/flutter/packages/flutter/lib/src/widgets/framework.dart').
} else {
Can't I write braces in an if statement in List?
Referred to the following:
How to use conditional statement within child attribute of a Flutter Widget (Center Widget)
PS:
The question is only about whether or not braces can be applied.
I am asking this question because I am interested in Dart syntax.

You are creating a Set using the curly braces to read more about SET visit set literal. Your build function should be like this,
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
if (isFlag)
Text(
"Demo true",
)
else
Text(
"Demo flase",
)
],
),
),
);
Or you can use the ternary operator, Example code
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
isFlag ? Text("Demo true",) : Text("Demo flase")
],
),
),
);

Do it like this with ternary operator
isFlag?Text("Demo true"):Text("Demo flase")

Using If statements inside the UI page is Not recommended,
You Can Do What you want in tow way:
1- Using Visibility Widget, to Hide One Widget and show another one.
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
Visibility(
visible : isFlag,
child: Text(
"Demo true",
),
)
Visibility(
visible : !(isFlag),
child: Text(
"Demo false",
),
)
],
),
),
);
2- You Can Use Ternary if statement Like this:
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text(
"Demo1",
),
isFlag ? Text("Demo true",) : Text("Demo false"),
],
),
),
);
And as I say, using a lot of code inside UI page is note recommended.
Don't be shy to ask me any thing if any.

[
if(kDebugMode){
Text('Data')
}.first,
]
{} is making it a Set so you can access its Data like here to {}.first gets first object/value from set,
in your case it is treated as a set with undefined number Objects
.
[
if (!kDebugMode) ...{
Text('Data'),
Text('data'),
},
]
or, you can also use the spread operator (...) for widgets that require the same if condition

Related

In Flutter, why Scaffold's body can't directly use Row()?

If I use Row() instead of Center(), it will not be displayed,just blank.
I expect a music player like layout.
Make 2 Row, the 1st Row contain "LeftMenu" and "Expanded Container" for content .
Putting this in scaffold gives you the left menu:
drawer: const Drawer(
child: Text("Left Menu")
),
Putting this inside scaffold body works. Expanded and a row:
Column(
children: [
Expanded(
child: Container(
color: Colors.green,
child: const Center(child: Text("1")),
)
),
Row(
children: const [
Text("1"),
SizedBox(width: 10),
Text("2"),
],
),
],
)
If you replace center with row, it probably displays but in the top left corner and not middle. Try to wrap your Row with Center and it should display in the middle. For the row you need to add a mainAxisAlignment.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center (child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:[ Text('Left menu'),Text('Place container here')]
),),
),
);
}
}
This is actually the wrong question.
The real problem is: if the ListView is nested by Column, Row, it will not be displayed.
You need to use Expanded or Container on the outside and then nest it with Colmn or Row.

Spread operator and toList for Map lazy loading in Flutter

I am trying to better understand Dart data structures to use in Flutter. When using a map() to turn a list into widgets, I have seen that you add toList() at the end because map() uses lazy loading and only iterates when it needs to. However, I have also seen that using a spread operator[...] also does the trick.
Going off this SO post, I wanted to know what the best practice is in these situations.
My code is long so I have produced a similar workable example below. I need to use spread operator to create the ElevatedButton's inside Column, but code works with and without toList().
Do I use toList() or is the only purpose for including it is to achieve the same thing the spread operator is already doing?
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var answers = [
'Answer 1',
'Answer 2',
'Answer 3',
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text('The Question',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
)),
...answers.map(((e) => CustomButton(e)))
// .toList() // should this be included?
],
),
)),
);
}
}
class CustomButton extends StatelessWidget {
final String anAnswer;
CustomButton(this.anAnswer);
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {},
child: Text(anAnswer),
);
}
}
I'd simply replace your final children element as:
children: [
Text('The Question',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
)),
for (final e in answers) CustomButton(e),
],
which uses a list literal for-loop to build the elements. No need for a spread operator as you are inserting the elements directly into the outer list.

Alignment properties doesn't work so I use empty expanded widget

I want make text to the right, what am I doing so far
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _judul = 'Private Chat';
static var _warnaTema = Colors.pink[100];
Widget _dummyExpanded() {
return Expanded(
child: Container(), //contain empty data,
); //just for fill remaining space
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _judul,
theme: ThemeData(
primaryColor: _warnaTema,
),
home: Column(
children: [
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 1'),
],
),
),
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 2'),
],
),
)
],
),
);
}
}
The layout output is what I expected (the text is in right), however there's unneeded code.
As you see I use unnecessary method _dummyExpanded to fill
available space which it's just expanded with empty container. Of course it will be hard to read since there are many nested row and column, how I remove that unneeded method without loss layout output what I expect?
I believe I should have use alignment but I don't know how to
Method 1.
Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.end,
children: [
Text('this is real data 2'),
],
),
)
Method 2.
I prefer this method, You can wrap text with this method.
You can also use Flexible widget instead of Expanded
Container(
child: Row(
children: [
Expanded(child: Text('this is real data 2', textAlign:TextAlign.end )),
],
),
)
Method 3.
If you have only Text widgets as children of Column widget then you can set crossAxisAlignment: CrossAxisAlignment.end, for your parent Column widget.

Why is the function not invoke

I am new to coding and to flutter but am attempting to build an app for scanning, creating database, and inventory. I have been attempting to use flutter_barcode_scanner to achieve this along with several others while looking at multiple videos and blogs but have become unsuccessful and am now I'm coming here for help.
Provided is the code that I'm currently attempting to write for it. At this point I've confused myself since I was recently trying to utilize scan_preview also as my goal is to implement the scanner as a stream in half or 1/3rd of the screen and having the rest of the screen as the result that is pulled from the database or to create a new item if no match.
I am looking for some assistance in how to implement the barcode scanner in the fashion where it streams in part of the screen and why I am getting these issues and how to fix them. I have attempted the fixes that androidstudio is providing me but it creates many more issues.
Am I going about this the correct way?
How do I use flutter_barcode_scanner to stream in only a portion of the screen?
Errors from AndroidStudio:
child: ScanMode.BARCODE( Error: The expression doesn't evaluate to a function, so it can't be invoked
Center(child: Text(barcode)) Error: Undefined name 'barcode'
'#ff6666', 'Cancel', true, ScanMode.BARCODE)! Error: This requires the 'non-nullable' language feature to be enabled
return Scaffold(
appBar: AppBar(
title: Text("Barcode Scanner"),
centerTitle: true,
),
body: Column(
children: [
SizedBox(
width: double.infinity,
height: height / 0.6,
child: ScanMode.BARCODE(
onScanResult: (result) {
debugPrint('scan result: $result');
setState(() {
_data = result;
});
},
),
),
SizedBox(height: 20),
Center(child: Text(barcode))
],
));
}
}
class ScannerHelper extends StatefulWidget {
#override
_ScannerHelperState createState() => _ScannerHelperState();
}
class _ScannerHelperState extends State<ScannerHelper> {
String _scanbarcode = 'Unknown';
#override
void initState() {
super.initState();
}
Future<void> startBarcodeScanStream() async {
FlutterBarcodeScanner.getBarcodeStreamReceiver(
'#ff6666', 'Cancel', true, ScanMode.BARCODE)!
.listen((barcode) => print(barcode));
}
//build - to resolve scanner issue
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Barcode scan')),
body: Builder(builder: (BuildContext context) {
return Container(
alignment: Alignment.center,
child: Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => startBarcodeScanStream(),
child: Text('Start barcode scan stream')),
Text('Scan result : $_scanbarcode\n',
style: TextStyle(fontSize: 20))
]));
})));
}

Cannot localize strings in Flutter TabBarView

When I try to localize a string in a TabBarView I get this error:
NoSuchMethodError: The method 'translate' was called on null. Receiver: null. Tried calling: translate("username).
I use this line of code to translate a key to a localized string:
AppLocalizations.of(context).translate('username')
This works great in all the other screens of my app except this one. Does anyone know why it's not working and how to solve it?
Some things I already tried:
pass the context of the main screen (the screen that holds all the TabBarViews)
wrap every ListTile in a Builder
wrap the ListView in a Builder
Code:
class AccountScreen extends StatelessWidget {
final String username;
final String email;
final int points;
AccountScreen(this.username, this.email, this.points);
#override
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
ListTile(
title: Text(AppLocalizations.of(context).translate('username')),
subtitle: Text(username),
),
ListTile(
title:
Text(AppLocalizations.of(context).translate('email_address')),
subtitle: Text(email),
),
ListTile(
title: Text(AppLocalizations.of(context).translate('points')),
subtitle: Text('$points'),
),
],
),
),
);
}
}
I found same problem. But in my case is using MaterialApp without localizationsDelegates. (I mean all file not only main.dart).
So i add localizationsDelegates on every MaterialApp in all widget.
e.g.
MaterialApp(
localizationsDelegates: [
MainLocalizationsDelegate.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
home: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
brightness: Brightness.light,
bottom: TabBar(
tabs: [
Tab(text: MainLocalizations.of(context).food),
Tab(text: MainLocalizations.of(context).car),
],
),
),
body: TabBarView(
children: [
TabA(),
TabB(),
],
),
),
),
);
The problem was that there were multiple MaterialApp widgets inside the app that were causing some conflicts regarding the localisation process. Removing the Redundant MaterialApp widgets fixed the issue.