I am trying to create a table from an imported CSV file, that I can latter call upon for data. I followed this tutorial here as a starting point.
So far I have managed to create the table, but it only generates once you press a button. What I would like to do is for the table to be loaded as soon as the app starts.
My code is almost identical to the one in the tutorial, but either way, here it is:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
class TableLayout extends StatefulWidget {
const TableLayout({Key key}) : super(key: key);
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
List<List<dynamic>> data = [];
loadAsset() async {
final myData = await rootBundle.loadString("assets/routes.csv");
List<List<dynamic>> csvTable = const CsvToListConverter().convert(myData);
print(csvTable);
data = csvTable;
setState(() {
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () async {
await loadAsset();
//print(data);
}),
appBar: AppBar(
title: const Text("Bus Routes"),
),
body: SingleChildScrollView(
child: Table(
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color: Colors.blueGrey,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
row.toString(),
style: const TextStyle(fontSize: 20.0),
),
),
);
}).toList());
}).toList(),
),
),
);
}
}
With this code, the following screen is generated (once you push the button):
I'm not worried about the look of the table as the user wont actually be seeing it in the end. Instead it will be used to retrieve data for use in other screens of my app. I understand that it is only generated on the button press because of this line:
onPressed: () async {
await loadAsset();
I am unsure on how to run this when the app starts rather than when the button is pressed.
Solution:
Thanks to rosh-dev's comment I was able to create a initSate to fix my problem.
This tutorial also helped: Flutter Tutorial for Beginners #25 - Asynchronous Code
The new code looks like this:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
class TableLayout extends StatefulWidget {
const TableLayout({Key key}) : super(key: key);
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
List<List<dynamic>> data = [];
void loadAsset() async {
final myData = await rootBundle.loadString("assets/routes.csv");
List<List<dynamic>> csvTable = const CsvToListConverter().convert(myData);
print(csvTable);
data = csvTable;
setState(() {
});
}
#override
void initState() {
super.initState();
loadAsset();
}
Widget build(BuildContext context) {
return Scaffold(
// floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
// floatingActionButton: FloatingActionButton(
// child: const Icon(Icons.refresh),
// onPressed: () async {
// await loadAsset();
// }),
appBar: AppBar(
title: const Text("Bus Routes"),
),
body: SingleChildScrollView(
child: Table(
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color: Colors.blueGrey,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
row.toString(),
style: const TextStyle(fontSize: 20.0),
),
),
);
}).toList());
}).toList(),
),
),
);
}
}
Thanks
Related
ive created a text and icon button, onpressing that icon
modal bottom sheet gets generated, in that
and ive created a separate dart file with text field and a submit button
when giving an input on text field and after clicking on submit button the given input string will be printed below
atlast i called the function in first dart file
but i want the text to be printed on the main scaffold page.
Below is the main code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:practice1/StatefulModalbtn.dart';
void main() {
runApp(Modalbtn());
}
class Modalbtn extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Modal Bottom Test'),
),
body: Column(
children: <Widget>[Mymodal()],
),
),
);
}
}
class Mymodal extends StatelessWidget {
const Mymodal({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'Press the icon to select the Tractor model',
style: TextStyle(fontSize: 15),
),
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: <Widget>[StatefulModalbtn()],
),
);
});
},
icon: Icon(Icons.add),
iconSize: 20,
)
],
),
);
}
}
and below code is for creating a text field and submit button
import 'package:flutter/material.dart';
class StatefulModalbtn extends StatefulWidget {
const StatefulModalbtn({Key? key}) : super(key: key);
#override
_StatefulModalbtnState createState() => _StatefulModalbtnState();
}
class _StatefulModalbtnState extends State<StatefulModalbtn> {
TextEditingController textController = TextEditingController();
String displayText = "";
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: textController,
maxLines: null,
),
ElevatedButton(
onPressed: () {
setState(() {
displayText = textController.text;
});
},
child: Text('Submit')),
Text(
displayText,
style: TextStyle(fontSize: 20),
),
],
);
}
}
and below is the output link
this is the output im achieving but i want the "Hello World" to be printed on top/main screen, right after the + add icon screen
How should i solve this ??
I just slightly edited your code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'main1.dart';
void main() {
runApp(MaterialApp(
home: Modalbtn(),
));
}
class Modalbtn extends StatefulWidget {
#override
_ModalbtnState createState() => _ModalbtnState();
}
class _ModalbtnState extends State<Modalbtn> {
String value = "0";
// Pass this method to the child page.
void _update(String newValue) {
setState(() => value = newValue);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: [StatefulModalbtn(update: _update)],
),
);
});
},
icon: Icon(Icons.add),
iconSize: 20,
),
Text(
value,
style: TextStyle(fontSize: 40),
),
],
),
),
);
}
}
and the child class is
import 'package:flutter/material.dart';
class StatefulModalbtn extends StatelessWidget {
final ValueChanged<String> update;
StatefulModalbtn({required this.update});
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => update("100"), // Passing value to the parent widget.
child: Text('Update (in child)'),
);
}
}
I don't get any issues to get JSON data the button is pressed to get JSON response.body is printed successfully but the JSON response is executed before I give _addressController value the if condition executed so the exception is shown on the print state. so please see my code and help me to overcome the issues
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:core';
import 'dart:convert';
import 'package:http/http.dart'as http;
import 'string.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
var url1 = 'This is my first off url';
var _addressControler = TextEditingController();
late Future<Balance> futureBalance;
#override
void initState() {
super.initState();
futureBalance = fetchBalance();
}
Future<Balance> fetchBalance() async {
http.Response response =
await http.get(Uri.parse(url1+_addressControler.text));
print(response.body);
if (response.statusCode == 200) {
return Balance.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load album');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: _addressControler,
decoration: InputDecoration(
labelText: 'Enter the address...',
labelStyle: TextStyle(color: Colors.blue),
border: new OutlineInputBorder(
borderSide: new BorderSide(color: Colors.black)),),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () async {
await fetchBalance();
},
child: const Text('Submit'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text("${_addressControler.text}"),
),
Container(
//color: Colors.blueAccent,
child: FutureBuilder<Balance>(
future: futureBalance,
builder: (context, index) {
if (index.hasData) {
print(index.data!.height);
var x = (index.data!.result[0].amount);
var y = int.parse(x);
assert(y is int);
var z = (y / 1000000);
print(z);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${z.toString()}',
style: TextStyle(fontSize: 20,),),
]);
} else if (index.hasError) {
return Text("${index.error}");
}
return CircularProgressIndicator();
},
),
),
]
),
),
)
);
}
}
I have an issue on fetchBalance() function. The if the condition is executed before I click the onPressed button but I what to do after given TextField and submit onPressed to execute the condition. so, is any possible way to overcome this issue please help me...
I am not sure I understand your question, but it seems you get an error because fetchBalance is executed before you expect it to.
Well, you call futureBalance = fetchBalance(); within your initState() method, hence the code is executed when your widget is being initialized and not only after you press the button. This means, you try to parse the url without appending _addressControler.text.
also, you can use it like this.
fetchBalance().then((balance) {
setState(() {
_balance = balance; //need to create one variable of type Balance
});
});
Better put the setState() in your async call:
Future<Balance> fetchBalance() async {
http.Response response =
await http.get(Uri.parse(url1+_addressControler.text));
print(response.body);
if (response.statusCode == 200) {
setState(() {
_balance = Balance.fromJson(jsonDecode(response.body));
});
} else {
throw Exception('Failed to load album');
}
}
First up all I remove the initState() and i use setState() for onPressed() to call the API function fetchBalance() on the state it's working good..
child: ElevatedButton(
onPressed: () {
setState(() {
fetchBalance();
});
fetchBalance();
},
child: const Text('Submit'),
),
),
How to turn On/Off vibration on Homepage from Settings page with boolean SwitchListTile?
I want if the SwitchListTile in the Settings page is On, the Homepage will vibrate every time I tap it, and vice versa. basically I don't know how to control certain pages from other pages
this is MySettingPage
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class MySettingPage extends StatefulWidget {
const MySettingPage({Key key}) : super(key: key);
#override
_MySettingPageState createState() => _MySettingPageState();
}
class _MySettingPageState extends State<MySettingPage> {
bool isVibrate = false;
#override
void initState() {
super.initState();
getSwitchValues();
}
getSwitchValues() async {
isVibrate = await getSwitchState();
setState(() {});
}
Future<bool> saveSwitchState(bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("switchState", value);
return prefs.setBool("switchState", value);
}
Future<bool> getSwitchState() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isVibrate = prefs.getBool("switchState");
return isVibrate;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0,
title: Text("Pengaturan"),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
}),
),
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: [
SwitchListTile(
title: Text("Getar"),
value: isVibrate,
onChanged: (bool value) async {
setState(() {
isVibrate = value;
saveSwitchState(value);
});
},
),
//
],
),
),
);
}
}
this is MyHomePage
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'mysettingpage.dart';
class MyHomePage extends StatefulWidget {
final bool isVibrate;
MyHomePage({Key key, this.isVibrate}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
if (widget.isVibrate == true) {
Vibration.vibrate(duration: 70);
}
if (widget.isVibrate == false) {
Vibration.cancel();
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My Homepage"),
titleSpacing: 0,
leading: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => MySettingPage(),
));
},
),
),
body: GestureDetector(
onTap: () {
_incrementCounter();
},
child: Container(
height: double.infinity,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(bottom: 120),
child: Column(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: FittedBox(
child: Text(
'$_counter',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 200,
fontFamily: 'DS-Digital',
color: Color(0xFF24F3E2),
),
),
),
),
],
),
),
],
),
),
),
),
);
}
}
To continue on the response from Allan C with the changes to your code: (untested)
HomePage:
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'mysettingpage.dart';
class MyHomePage extends StatefulWidget {
final bool isVibrate;
MyHomePage({Key key, this.isVibrate}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool _isVibrate;
#override
void initState() {
super.initState();
_isVibrate = widget.isVibrate;
}
void _onVibrateChange(bool value) {
setState(() {
_isVibrate = value;
})
}
void _incrementCounter() {
setState(() {
_counter++;
if (_isVibrate) {
Vibration.vibrate(duration: 70);
}
if (_isVibrate) {
Vibration.cancel();
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My Homepage"),
titleSpacing: 0,
leading: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => MySettingPage(
onChange: _onVibrateChange
),
));
},
),
),
body: GestureDetector(
onTap: () {
_incrementCounter();
},
child: Container(
height: double.infinity,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(bottom: 120),
child: Column(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: FittedBox(
child: Text(
'$_counter',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 200,
fontFamily: 'DS-Digital',
color: Color(0xFF24F3E2),
),
),
),
),
],
),
),
],
),
),
),
),
);
}
}
using the initState() you set a default value of _isVibrate from the passed value from the widget.isVibrate.
The method _onVibrateChange(bool value) (as a callback) will update the local variable within the state. This method needs to be passed to the MySettingsPage also.
MySettingsPage:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class MySettingPage extends StatefulWidget {
const MySettingPage({Key key, this.onChange}) : super(key: key);
final Function(bool value) onChange;
#override
_MySettingPageState createState() => _MySettingPageState();
}
class _MySettingPageState extends State<MySettingPage> {
bool isVibrate = false;
#override
void initState() {
super.initState();
getSwitchValues();
}
getSwitchValues() async {
isVibrate = await getSwitchState();
setState(() {});
}
Future<bool> saveSwitchState(bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("switchState", value);
widget.onChange(value);
return prefs.setBool("switchState", value);
}
Future<bool> getSwitchState() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isVibrate = prefs.getBool("switchState");
return isVibrate;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0,
title: Text("Pengaturan"),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
}),
),
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: [
SwitchListTile(
title: Text("Getar"),
value: isVibrate,
onChanged: (bool value) async {
setState(() {
isVibrate = value;
saveSwitchState(value);
});
},
),
//
],
),
),
);
}
}
I have included a new variable passed to the Statefulwidget (Function(bool value) onChange), this will be the callback for when the switch changes it's value.
In the method Future saveSwitchState(bool value) async there is a call to the passed callback with the updated value from the SwitchListTiles onChange method.
Hope this clarifies what he meant in his answer.
One way to do this is to use a callback function.
So in MySettingPage(), add a constructor such as below:
MySettingPage({this.callback})
final void Function(bool) callback;
In MySettingPage, if you want to update the value of isVibrate in MyHomePage(), you can call widget.callback(true);
In MyHomePage, you can create a method to update the isVibrate variable.
void _updateIsVibrate(bool isVibrate){//...}
When you call MySettingsPage, you can pass in the method you created.
All my problems related to booleans above have been resolved by implementing MultiProvider. Thanks to the above masters who have helped me. have a nice day
I am working on a custom dialog called "Alertbox" where the user inserts a name into a textfield and after he pushes the button a function called "addTeam" created a team out of the string.
This is how I created my dialog "Alertbox":
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:trainings_app/config/palette.dart';
class Alertbox extends StatelessWidget {
final Function addTeamFunction;
const Alertbox(this.addTeamFunction);
#override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: EdgeInsets.all(10),
child: Center(
child: Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(const Radius.circular(20)),
color: Colors.white,
),
width: 350,
height: 200,
child: Row(
children: [
SizedBox(width: 12),
Expanded(
child: TextField(
textAlign: TextAlign.center,
autofocus: true,
),
),
SizedBox(width: 12),
ElevatedButton(
onPressed: () => addTeamFunction(),
child: const Text('✓'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Palette.orange),
),
),
SizedBox(width: 8),
],
),
),
),
);
}
}
And here I am using it:
void newTeam() {
showDialog<AlertDialog>(
context: context,
builder: (BuildContext context) {
return Alertbox(() {
Navigator.of(context).pop();
});
},
);
}
void addTeam(String name) {
setState(() {
teams.add(name);
});
Navigator.of(context).pop();
sharedPreferences.setStringList('teams', teams);
}
But I can't find a way to parse the input from the textfield into the function "addTeam" where it is needed. Can anyone help me please?
You Should try below code hope its helps you:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Testing',
home: MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(myController.text),
);
},
);
},
tooltip: 'Show the value!',
child: const Icon(Icons.add),
),
);
}
}
Your Screen like ->
Use a TextFormField instead of a TexiField widget contained in a Form widget that has a GlobalKey, which will be useful to you during validation!
How to get the value which is already entered on the keyboard?
Uses a TextEditingController or the onSaved method of the TextFormField.
This page is my PhotoPreviewScreen where I send the photo that comes from the camera screen to the home page after clicking the button in the code below.
I am getting some interesting errors, that I have not seen before with very little in the docs, which are in the screenshot.
Has anyone seen these before? How can I rectify?
import 'package:flutter/material.dart';
import 'dart:io';
class PhotoPreviewScreen extends StatelessWidget {
Function setData;
PhotoPreviewScreen({Key key, this.setData}) : super(key: key);
}
class _PhotoPreviewScreenState extends State<PhotoPreviewScreen> {
final String imagePath;
var image;
Future _openGallery() async {}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pop(
context), // Go back to the camera to take the picture again
child: Icon(Icons.camera_alt),
),
appBar: AppBar(title: Text('Photo Preview')),
body: Column(children: [
Expanded(child: Image.file(File(imagePath))),
const SizedBox(height: 16.0),
OutlineButton(
onPressed: () {
_openGallery();
Navigator.pop(context);
},
child: Text('Okay'),
borderSide: BorderSide(
color: Color(
0xff33333D)),
),
]),
);
}
}
errors
class PhotoPreviewScreen extends StatefulWidget {Function setData; PhotoPreviewScreen({Key key, this.setData}) : super(key: key); }
I guess it should be "StatefulWidget" instead of "StatelesWidget".
Try the below code snippets:
import 'package:flutter/material.dart';
import 'dart:io';
class PhotoPreviewScreen extends StatefulWidget {
Function setData;
PhotoPreviewScreen({Key key, this.setData}) : super(key: key);
_PhotoPreviewScreenState createState() => _PhotoPreviewScreenState();
}
class _PhotoPreviewScreenState extends State<PhotoPreviewScreen> {
final String imagePath = ' ';
var image;
Future _openGallery() async {}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pop(
context), // Go back to the camera to take the picture again
child: Icon(Icons.camera_alt),
),
appBar: AppBar(title: Text('Photo Preview')),
body: Column(children: [
Expanded(child: Image.file(File(imagePath))),
const SizedBox(height: 16.0),
OutlineButton(
onPressed: () {
_openGallery();
Navigator.pop(context);
},
child: Text('Okay'),
borderSide: BorderSide(
color: Color(
0xff33333D)),
),
]),
);
}
}