Collect user input data - flutter - flutter

I want to collect input data from the user and record it in a certain page. You will see what my program does (full code down below). But the code below, is having two problems.
first problem: The Data in the HistoryPage class is not getting stored correctly. For example when I press A then type 50, The HistoryPage will store it as 'Subtracted 50 on A (and the date)'. But when I enter a second input, such as 30 on B, the Page will show 'Subtracted 30 on A', 'Subtracted 30 on B'. Thus, the Value of A also changes.
Second problem:
count++;
print(count);
historyList.add(History(data: text.data, dateTime: DateTime.now()));
This part of the code is not working. I tried to make 'text' a global variable. But I cannot change the constructor in the class Tile with a global variable.
full code:
import 'package:flutter/material.dart';
import './globals.dart' as globals;
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HistoryPage()),
);
},
child: Text(value.toString()),
),
FlatButton(
child: Center(child: Text("Spent")),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Type()),
);
},
)
],
));
}
}
class Spent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context)),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Tile(
text: Text(
"A",
style: TextStyle(fontSize: 20.0),
),
),
Tile(
text: Text(
"B",
style: TextStyle(fontSize: 20.0),
),
),
Tile(
text: Text(
"C",
style: TextStyle(fontSize: 20.0),
),
),
]))));
}
}
class Tile extends StatelessWidget {
final Text text;
Tile({this.text});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Type()),
);
},
child: text,
);
}
}
class Type extends StatefulWidget {
#override
TypeState createState() => TypeState();
}
class TypeState extends State<Type> {
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context)),
),
body: Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
TextFormField(
textInputAction: TextInputAction.done,
controller: _controller,
keyboardType: TextInputType.number),
FlatButton(
child: Text("Subract"),
onPressed: () {
if (int.tryParse(_controller.text) == null) return;
globals.enteredValue = int.parse(_controller.text);
setState(() {
value -= globals.enteredValue;
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
count++;
print(count);
historyList.add(History(data: text.data, dateTime: DateTime.now()));
},
),
])),
));
}
}
int value = 0;
int count = 0;
List<History> historyList = [];
class History {
String data;
DateTime dateTime;
History({
this.data,
this.dateTime,
});
}
class HistoryPage extends StatefulWidget {
#override
HistoryPageState createState() => HistoryPageState();
}
class HistoryPageState extends State<HistoryPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
}),
),
body: Container(
child: ListView.builder(
itemCount: historyList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
' Subtracted ${globals.enteredValue} on ${historyList[index].data} ${historyList[index].dateTime.toString()}'),
);
},
),
));
}
}
globals.dart
library numbers.globals;
int enteredValue = 0;

You can copy paste run full code below
Step 1: class History add enteredValue attribute
class History {
int enteredValue;
Step 2: historyList.add need enteredValue
historyList.add(History(
enteredValue: int.parse(_controller.text),
Step 3: class Type need final Text text;
class Type extends StatefulWidget {
final Text text;
Type({this.text});
Step 4: MaterialPageRoute(builder: (context) => Type(text: text)),
working demo
full code
import 'package:flutter/material.dart';
import './globals.dart' as globals;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HistoryPage()),
);
},
child: Text(value.toString()),
),
FlatButton(
child: Center(child: Text("Spent")),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Spent()),
);
},
)
],
));
}
}
class Spent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context)),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Tile(
text: Text(
"A",
style: TextStyle(fontSize: 20.0),
),
),
Tile(
text: Text(
"B",
style: TextStyle(fontSize: 20.0),
),
),
Tile(
text: Text(
"C",
style: TextStyle(fontSize: 20.0),
),
),
]))));
}
}
class Tile extends StatelessWidget {
final Text text;
Tile({this.text});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Type(text: text)),
);
},
child: text,
);
}
}
class Type extends StatefulWidget {
final Text text;
Type({this.text});
#override
TypeState createState() => TypeState();
}
class TypeState extends State<Type> {
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context)),
),
body: Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
TextFormField(
textInputAction: TextInputAction.done,
controller: _controller,
keyboardType: TextInputType.number),
FlatButton(
child: Text("Subract"),
onPressed: () {
if (int.tryParse(_controller.text) == null) return;
globals.enteredValue = int.parse(_controller.text);
setState(() {
value -= globals.enteredValue;
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
count++;
print(count);
historyList.add(History(
enteredValue: int.parse(_controller.text),
data: widget.text.data,
dateTime: DateTime.now()));
},
),
])),
));
}
}
int value = 0;
int count = 0;
List<History> historyList = [];
class History {
int enteredValue;
String data;
DateTime dateTime;
History({
this.enteredValue,
this.data,
this.dateTime,
});
}
class HistoryPage extends StatefulWidget {
#override
HistoryPageState createState() => HistoryPageState();
}
class HistoryPageState extends State<HistoryPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
}),
),
body: Container(
child: ListView.builder(
itemCount: historyList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
' Subtracted ${historyList[index].enteredValue} on ${historyList[index].data} ${historyList[index].dateTime.toString()}'),
);
},
),
));
}
}

Related

How do I display the output of a method from the first page on a second page in flutter?

The app is supposed to take in the first name on the first page and reverse it, then print the output on the second page. I'm having trouble implementing the output from the _incrementCounter method into the SecondScreen class in order to print the output on the second page.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext ctxt) {
return MaterialApp(
home: FirstScreen(),
);
}
}
class FirstScreen extends StatelessWidget {
String t1 = '', output = '';
RevName name = RevName();
void _incrementCounter() {
setState(() {
output = name.reverseName(t1) as String;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(child: Text("Reverse Name")),
),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(20.0),
child: TextField(keyboardType: TextInputType.name,
decoration: const InputDecoration(
labelText: 'Enter Your First Name',
border: OutlineInputBorder()),
onChanged: (text) {
t1 = text;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
_incrementCounter();
},
child: Text('Reverse Name'),
),
),
],
)
);
}
void setState(Null Function() param0) {}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Reverse Name"),
),
body: Column(
children: [
Center(
child: OutlinedButton(
onPressed: (){
Navigator.pop(context);
},
child: Text('Back')
),
),
],
)
);
}
}
The class where name is being reversed and returning the reversed name
class RevName {
String name, reversed;
RevName({this.name = '', this.reversed = ''});
String reverseName(name) {
reversed = name.split('').reversed.join('');
return '$reversed';
}
}
You've RevName model class, to store name and reverse name. You can modify like,
class RevName {
String name, reversed;
RevName({
required this.name,
}) : reversed = name.split('').reversed.join('');
}
Now let's pass data using constructor. Remove state RevName and follow this,
child: OutlinedButton(
onPressed: () {
RevName revName = RevName(name: t1);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(
data: revName,
),
),
);
},
child: const Text('Reverse Name'),
),
On receiver side SecondScreen.
class SecondScreen extends StatelessWidget {
final RevName data;
const SecondScreen({
Key? key,
required this.data,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Reverse Name"),
),
body: Column(
children: [
Text(data.name),
Text(data.reversed),
You can follow this answer to explore alternative way.

How to navigate to a different page on a different tab using CupertinoTabBar?

I have two tabs - Tab1 and Tab2. Tab1 has 3 pages - Tab1 Page1, Tab1 Page2, Tab1 Page3.
I want to be able to navigate from Tab2 to Tab1 Page2. I can switch the index using controller.index = 0 but am not sure how to navigate to to Page2 of this tab. What is a clean solution for this?
// main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(child: Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [GlobalKey<NavigatorState>(), GlobalKey<NavigatorState>()];
var currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
Page1();
#override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2'),
onPressed: () {
Navigator.pushNamed(context, 'page1b');
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
#override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child:
Text('Tab1 Page2', style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
const Page2(this.controller);
#override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
// TODO I want this to go to Tab1 Page2
this.controller.index = 0;
Navigator.of(context).pushNamed('page1b');
},
)
],
),
);
}
}
You can copy paste run full code below
Step 1: You can pass navigatorKeyList[0]) to Page2
Step 2: call navigatorKey.currentState.pushNamed("page1b"); and change index
code snippet
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
...
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
...
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
navigatorKey.currentState.pushNamed("page1b");
this.controller.index = 0;
},
)
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(
child:
Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>()
];
var currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(
title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(
title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
Page1();
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2'),
onPressed: () {
Navigator.pushNamed(context, 'page1b');
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
class Page1c extends StatelessWidget {
Page1c();
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
navigatorKey.currentState.pushNamed("page1b");
this.controller.index = 0;
},
)
],
),
);
}
}
full code 2
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(
child:
Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>()
];
int currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(
title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(
title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(controller, navigatorKeyList[1]),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page1(this.controller, this.navigatorKey);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab2 Page2'),
onPressed: () async {
controller.index = 1;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKey.currentState.pushNamed("/");
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
class Page1c extends StatelessWidget {
Page1c();
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () async {
navigatorKey.currentState.pushNamed("page1b");
await Future.delayed(Duration(seconds: 1), () {});
this.controller.index = 0;
},
)
],
),
);
}
}
full code 3
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(controller, navigatorKeyList),
onWillPop: () => Future<bool>.value(true),
),
'page2b': (context) => Page2b(),
'page3b': (context) => Page3b(),
},
);
...
import 'package:cupertino_tab_bar/base_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Page1 extends StatelessWidget {
final CupertinoTabController controller;
final List<GlobalKey<NavigatorState>> navigatorKeyList;
const Page1(this.controller, this.navigatorKeyList);
#override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab2 Page2'),
onPressed: () async{
controller.index = 1;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKeyList[1].currentState.pushNamed("page2b");
},
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab3 Page2'),
onPressed: () async{
controller.index = 2;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKeyList[2].currentState.pushNamed("page3b");Navigator.pushNamed(context, 'page3b');
},
)
],
),
);
}
}

PushNamed issue: Type 'FillData' (a Statefulwidget) is not a subtype of type 'List<Object>'

I'm new in Flutter. I'm trying to push a List from NewData to FillData screen with pushNamed. But it said:
The following _TypeError was thrown while handling a gesture:
type 'FillData' is not a subtype of type 'List'
If i remove the comment in '/FillData', i receive null data instead. What should i do?
This is my code:
SettingNavigator
class SettingNavigator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => Home(),
'/NewData': (context) => NewData(),
// '/FillData': (context) => FillData(), (in comment)
}
onGenerateRoute: (setting) {
if (setting.name == '/FillData') {
final ChartGroupData chartName = setting.arguments;
final List<ChartGroupData> groupNames = setting.arguments;
return MaterialPageRoute(builder: (context) {
return FillData(
chartName: chartName,
gName: groupNames,
);
});
}
return null;
},
);
}
}
NewData
import 'package:flutter/material.dart';
class NewData extends StatefulWidget {
List<ChartGroupData> groupNames;
NewData({Key key, #required this.groupNames}) : super(key: key);
#override
NewDataStage createState() => NewDataStage();
}
class NewDataStage extends State<NewData> {
TextEditingController _nameCtrl = new TextEditingController();
var textFields = <Widget>[];
var groupTECs = <TextEditingController>[];
#override
void initState() {
super.initState();
textFields.add(createCustomTextField());
}
Widget createCustomTextField() {
var groupCtrl = TextEditingController();
groupTECs.add(groupCtrl);
return Container(
padding: EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Row(
children: <Widget>[
Expanded(flex: 3, child: Text("Group ${textFields.length}")),
Container(
constraints: BoxConstraints.tightFor(width: 120, height: 60),
child: TextField(
controller: groupCtrl,
),
),
],
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Center(child: Text("New Chart")),
),
body: Container(
alignment: AlignmentDirectional.center,
constraints: BoxConstraints.expand(),
child: Column(
children: <Widget>[
Text(
"Your chart name",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
TextField(
style: TextStyle(fontSize: 20),
controller: _nameCtrl,
),
Expanded(
flex: 3,
child: Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: textFields.length,
itemBuilder: (BuildContext context, int index) {
return textFields[index];
},
),
),
),
SizedBox(
height: 60,
width: 120,
child: RaisedButton(
onPressed: _onTapNext,
child: Text("NEXT"),
color: Colors.green,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _onTapCreate,
child: Icon(Icons.add, color: Colors.white),
shape: CircleBorder(),
),
),
);
}
void _onTapNext() {
/// Push Groups name to FillData
widget.groupNames = List<ChartGroupData>();
for (int i = 0; i < textFields.length; i++) {
var name = groupTECs[i].text;
widget.groupNames.add(ChartGroupData(name));
}
print(widget.groupNames.toString());
Navigator.pushNamed(context, '/FillData',
arguments: FillData(
gName: widget.groupNames,
chartName: ChartGroupData(_nameCtrl.text),
));
}
void _onTapCreate() {
setState(() {
textFields.add(createCustomTextField());
});
}
}
FillData
class FillData extends StatefulWidget {
final ChartGroupData chartName;
final List<ChartGroupData> gName;
FillData({Key key, #required this.chartName, #required this.gName})
: super(key: key);
#override
FillDataStage createState() => FillDataStage();
}
class FillDataStage extends State<FillData> {
void _showDialog() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Received Data"),
content: Text(widget.chartName.toString()),
);
},
);
}
void _onTapPrintReceivedData() {
print(widget.gName);
print(widget.chartName);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Center(
child: Text("Fill your Data"),
),
),
body: Center(
child: RaisedButton(
onPressed: () {
_onTapPrintReceivedData();
_showDialog();
},
child: Text("Print Data"),
),
),
));
}
}
Class ChartGroupData
lass ChartGroupData {
final String groupNames;
ChartGroupData(this.groupNames);
#override
String toString() {
return 'Group: $groupNames';
}
}
You have 2 problems with your code:
1- you cant user routes with onGenerateRoute, because now the app doesn't know where to go, to the widget that you didn't pass anything to (inside routes) or to the widget inside the onGenerateRoute.
2- arguments is a general object that you can put whatever you want inside of it, and doing this:
final ChartGroupData chartName = setting.arguments; final
List groupNames = setting.arguments;
passes the same value to two different objects, I solved this by doing the following (it's not the best but will give you a rough idea of what you should do)
created a new object that contains the data to be passed:
class ObjectToPass {
final ChartGroupData chartName;
final List<ChartGroupData> groupNames;
ObjectToPass({this.chartName, this.groupNames});
}
changed FillData implementation:
class FillData extends StatefulWidget {
final ObjectToPass objectToPass;
FillData({Key key, #required this.objectToPass}) : super(key: key);
#override
FillDataStage createState() => FillDataStage();
}
...
void _showDialog() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Received Data"),
content: Text(widget.objectToPass.chartName.toString()),
);
},
);
}
void _onTapPrintReceivedData() {
print(widget.objectToPass.groupNames);
print(widget.objectToPass.chartName);
}
to navigate to FillData you would:
Navigator.pushNamed(
context,
'/FillData',
arguments: ObjectToPass(
chartName: ChartGroupData(_nameCtrl.text),
groupNames: groupNames,
),
);
finally this is how your MaterialApp should look like:
return MaterialApp(
initialRoute: '/NewData',
onGenerateRoute: (setting) {
if (setting.name == '/FillData') {
return MaterialPageRoute(builder: (context) {
return FillData(
objectToPass: setting.arguments,
);
});
} else if (setting.name == '/NewData') {
return MaterialPageRoute(builder: (_) => NewData());
}
return null;
},
);
you can pass a list instead of the object I created and get your objects from it by it's index.

Flutter CupertinoActionSheet: how to define Variable number of actions

Depending on number of entries in List distinctEmnen,
I would like to show variable number of menu-choices.
Is it possible to achieve something like this?
CupertinoActionSheet(
title: Text( tjo),
actions: [
CupertinoActionSheetAction(
child: Text( distinctEmnen[0]),
Navigator.of(context).pushNamed(distinctEmnen[0]);
}),
CupertinoActionSheetAction(
child: Text( distinctEmnen[1]),
onPressed: () {
Navigator.of(context).pushNamed(distinctEmnen[1]);
}),
CupertinoActionSheetAction(
child: Text( distinctEmnen[n...]),
onPressed: () {
Navigator.of(context).pushNamed(distinctEmnen[n...]);
}),
],
cancelButton: CupertinoActionSheetAction(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
),
You can copy paste run full code below
Step 1: You can define a class Emnen
Step 2: Init List<Emnen> distinctEmnen
Step 3: Use List<Widget>.generate(distinctEmnen.length,
code snippet
class Emnen {
String title;
String routeName;
Emnen({this.title, this.routeName});
}
...
List<Emnen> distinctEmnen = [];
...
#override
void initState() {
distinctEmnen = [
Emnen(title: "1", routeName: "/1"),
Emnen(title: "2", routeName: "/2")
];
super.initState();
}
...
CupertinoActionSheet(
title: Text("tjo"),
actions: List<Widget>.generate(
distinctEmnen.length,
(int index) => CupertinoActionSheetAction(
child: Text(distinctEmnen[index].title),
onPressed: () => Navigator.of(context)
.pushNamed(distinctEmnen[index].routeName))));
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Emnen {
String title;
String routeName;
Emnen({this.title, this.routeName});
}
class CupertinoActionSheetApp extends StatelessWidget {
#override
Widget build(BuildContext context) => CupertinoApp(
initialRoute: "/",
routes: {
'/': (context) => HomePage(),
'/1': (context) => FirstScreen(),
'/2': (context) => SecondScreen(),
},
);
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Emnen> distinctEmnen = [];
#override
void initState() {
distinctEmnen = [
Emnen(title: "1", routeName: "/1"),
Emnen(title: "2", routeName: "/2")
];
super.initState();
}
#override
Widget build(BuildContext context) {
return Center(
child: CupertinoButton(
child: Text("show dialog"),
onPressed: () {
_showDialog(context);
}),
);
}
void _showDialog(BuildContext cxt) {
showCupertinoModalPopup<int>(
context: cxt,
builder: (cxt) {
var dialog = CupertinoActionSheet(
title: Text("tjo"),
actions: List<Widget>.generate(
distinctEmnen.length,
(int index) => CupertinoActionSheetAction(
child: Text(distinctEmnen[index].title),
onPressed: () => Navigator.of(context)
.pushNamed(distinctEmnen[index].routeName))));
return dialog;
});
}
}
void main() {
runApp(CupertinoActionSheetApp());
}
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Cupertino App"),
),
child: Center(
child: Text("First"),
),
);
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Cupertino App"),
),
child: Center(
child: Text("Second"),
),
);
}
}
full code

Alert box with multi select chip in flutter

I have a multiselect chip in my app , but when since the data in the AlertDialog depends dynamically, it will be 1 or 100, so I have added SingleChildScrollView over the alert Dialog to give scrolling if there are more entries , but when I added SingleChildScrollView my alert box goes to top of the screen like this, I want it to align in center,
If I removed the SingleChildScrollView then It will come like this which I wanted. but If there are lot of entries I cant select because It cant cover the entire data?
Is there any way where I can align it to center of screen with scroll enabled?
Thanks
showDialog(
context: context,
builder: (BuildContext context) {
return SingleChildScrollView(
child: AlertDialog(
title: Text("choose items"),
content: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
listSelectedItem = selectedList;
});
},
),
actions: <Widget>[
FlatButton(
child: Text("CANCEL"),
onPressed: () {
setState(() {
dropdownSelected = null;
listSelectedItem.clear();
});
Navigator.of(context).pop();
}),
In AlertDialog's content use Container and constraints, and in Container's child wrap SingleChildScrollView then wrap MultiSelectChip
code snippet
return AlertDialog(
title: Text("Report Video"),
content: Container(
constraints: BoxConstraints(
maxHeight: 100.0,
),
child: SingleChildScrollView(
child: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
selectedReportList = selectedList;
});
},
),
),
),
actions: <Widget>[
FlatButton(
child: Text("Report"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
})
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> reportList = [
"Not relevant",
"Illegal",
"Spam",
"Offensive",
"Uncivil",
"a123",
"b234",
"c2314",
"aaaa",
"a",
"1Not relevant",
"2Illegal",
"3Spam",
"4Offensive",
"5Uncivil",
"6a123",
"7b234",
"8c2314",
"9aaaa",
"0a",
"Not relevant",
"Illegal",
"Spam",
"Offensive",
"Uncivil",
"a123",
"b234",
"c2314",
"aaaa",
"a",
"1Not relevant",
"2Illegal",
"3Spam",
"4Offensive",
"5Uncivil",
"6a123",
"7b234",
"8c2314",
"9aaaa",
"0a",
];
List<String> selectedReportList = List();
_showReportDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
//Here we will build the content of the dialog
return AlertDialog(
title: Text("Report Video"),
content: Container(
constraints: BoxConstraints(
maxHeight: 100.0,
),
child: SingleChildScrollView(
child: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
selectedReportList = selectedList;
});
},
),
),
),
actions: <Widget>[
FlatButton(
child: Text("Report"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Report"),
onPressed: () => _showReportDialog(),
),
Text(selectedReportList.join(" , ")),
],
),
),
);
}
}
class MultiSelectChip extends StatefulWidget {
final List<String> reportList;
final Function(List<String>) onSelectionChanged;
MultiSelectChip(this.reportList, {this.onSelectionChanged});
#override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
// String selectedChoice = "";
List<String> selectedChoices = List();
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(item),
selected: selectedChoices.contains(item),
onSelected: (selected) {
setState(() {
selectedChoices.contains(item)
? selectedChoices.remove(item)
: selectedChoices.add(item);
widget.onSelectionChanged(selectedChoices);
});
},
),
));
});
return choices;
}
#override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}