Flutter CupertinoPicker doesnt fit into screen - flutter

Im building my first flutter project and at the moment im facing a huge problem with CupertinoPicker. It appears to be fully functional, but i cannot embed it into Stepper correctly. I can only see one element at the time, not the whole selection wheel. Any ideas how to solve this ?
Almost entire code :
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'objects/Course.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#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> {
int selectedCourse = 0;
List<Course> courses;
int _currentstep = 0;
double _yearFrom = 1, _yearTo = 5;
double _currentSliderValue = 1;
go(int step) {
setState(() => _currentstep += step);
print(selectedCourse);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stepper(
currentStep: _currentstep,
onStepContinue: () {
if (_currentstep != 1 && selectedCourse >= 0) {
go(1);
} else {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Error !')));
}
},
onStepCancel: () {
if (_currentstep != 0) {
go(-1);
}
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Center(
child: Row(
children: <Widget>[
RaisedButton(
padding: const EdgeInsets.all(10.0),
color: Colors.blue,
child: Text(
"Next",
style: TextStyle(color: Colors.white),
),
onPressed: onStepContinue,
),
FlatButton(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text("Back"),
),
onPressed: onStepCancel,
),
],
),
);
},
steps: [
Step(
title: Text("Pick your study program"),
isActive: _currentstep == 0,
content: Center(
child: FutureBuilder<List<Course>>(
future: downloadData(), // function where you call your api
builder: (BuildContext context,
AsyncSnapshot<List<Course>> snapshot) {
// AsyncSnapshot<Your object type>
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait its loading...'));
} else {
if (snapshot.hasError)
return Center(child: Text('Error: ${snapshot.error}'));
else
return showCoursePicker();
// snapshot.data :- get your object which is pass from your downloadData() function
}
},
),
),
),
Step(
isActive: _currentstep == 1,
state: StepState.indexed,
title: const Text('Pick your study year'),
content: Column(
children: <Widget>[
Card(
child: Row(
children: [
Column(
children: [Text(_yearFrom.toInt().toString())],
),
Column(
children: [
Slider(
min: _yearFrom,
max: _yearTo == _yearFrom ? _yearTo + 1 : _yearTo,
divisions: _yearTo == _yearFrom
? _yearTo.toInt() - _yearFrom.toInt() + 1
: _yearTo.toInt() - _yearFrom.toInt(),
value: _currentSliderValue,
label: _currentSliderValue.round().toString(),
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
});
},
),
],
),
Column(
children: [
Text(_yearTo.toInt().toString()),
],
)
],
),
),
],
),
)
],
),
);
}
Future<List<Course>> downloadData() async {
var response = await http
.get('https://lekcijas.va.lv/lekcijas_android/getAllCourseData.php');
var data = json.decode(response.body)["result"];
courses = List<Course>.from(data.map((x) => Course.fromJson(x)));
return Future.value(courses);
}
Widget showCoursePicker() {
return CupertinoPicker.builder(
childCount: courses.length,
itemExtent: 40,
useMagnifier: true,
magnification: 1.3,
onSelectedItemChanged: (value) {
selectedCourse = value;
print(selectedCourse);
setState(() {
_yearFrom = double.parse(courses[selectedCourse].course_from);
print(_yearFrom);
_yearTo = double.parse(courses[selectedCourse].course_to);
print(_yearTo);
});
},
itemBuilder: (ctx, index) {
return Center(
child: Text(
courses.isEmpty ? '' : courses[index].abbreviation,
),
);
});
}
}
Course object code :
class Course {
final String id;
final String abbreviation;
final String course_from;
final String course_to;
Course({this.id, this.abbreviation, this.course_from, this.course_to});
factory Course.fromJson(Map<String, dynamic> json) {
return Course(
id: json['id'] as String,
abbreviation: json['abbreviation'] as String,
course_from: json['course_from'] as String,
course_to: json['course_to'] as String,
);
}
}
Pic :
Layout with CupertinoPicker (only magnifier is visible)
Note : You need to add dependencies in pubspec.yml :
dependencies:
http: ^0.12.2

You can copy paste run full code below
Step 1: Set Future like this to avoid rebuild cause reload data
Future<List<Course>> _future;
...
#override
void initState() {
_future = downloadData();
...
child: FutureBuilder<List<Course>>(
future: _future,
Step 2: Use Container to set height
Widget showCoursePicker() {
return Container(
height: 250,
child: CupertinoPicker.builder(
working demo
full code
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Course {
final String id;
final String abbreviation;
final String course_from;
final String course_to;
Course({this.id, this.abbreviation, this.course_from, this.course_to});
factory Course.fromJson(Map<String, dynamic> json) {
return Course(
id: json['id'] as String,
abbreviation: json['abbreviation'] as String,
course_from: json['course_from'] as String,
course_to: json['course_to'] as String,
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#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> {
int selectedCourse = 0;
List<Course> courses;
int _currentstep = 0;
double _yearFrom = 1, _yearTo = 5;
double _currentSliderValue = 1;
Future<List<Course>> _future;
go(int step) {
setState(() => _currentstep += step);
print(selectedCourse);
}
#override
void initState() {
_future = downloadData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stepper(
currentStep: _currentstep,
onStepContinue: () {
if (_currentstep != 1 && selectedCourse >= 0) {
go(1);
} else {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Error !')));
}
},
onStepCancel: () {
if (_currentstep != 0) {
go(-1);
}
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Center(
child: Row(
children: <Widget>[
RaisedButton(
padding: const EdgeInsets.all(10.0),
color: Colors.blue,
child: Text(
"Next",
style: TextStyle(color: Colors.white),
),
onPressed: onStepContinue,
),
FlatButton(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text("Back"),
),
onPressed: onStepCancel,
),
],
),
);
},
steps: [
Step(
title: Text("Pick your study program"),
isActive: _currentstep == 0,
content: Center(
child: FutureBuilder<List<Course>>(
future: _future, // function where you call your api
builder: (BuildContext context,
AsyncSnapshot<List<Course>> snapshot) {
// AsyncSnapshot<Your object type>
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait its loading...'));
} else {
if (snapshot.hasError)
return Center(child: Text('Error: ${snapshot.error}'));
else
return showCoursePicker();
// snapshot.data :- get your object which is pass from your downloadData() function
}
},
),
),
),
Step(
isActive: _currentstep == 1,
state: StepState.indexed,
title: const Text('Pick your study year'),
content: Column(
children: <Widget>[
Card(
child: Row(
children: [
Column(
children: [Text(_yearFrom.toInt().toString())],
),
Column(
children: [
Slider(
min: _yearFrom,
max: _yearTo == _yearFrom ? _yearTo + 1 : _yearTo,
divisions: _yearTo == _yearFrom
? _yearTo.toInt() - _yearFrom.toInt() + 1
: _yearTo.toInt() - _yearFrom.toInt(),
value: _currentSliderValue,
label: _currentSliderValue.round().toString(),
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
});
},
),
],
),
Column(
children: [
Text(_yearTo.toInt().toString()),
],
)
],
),
),
],
),
)
],
),
);
}
Future<List<Course>> downloadData() async {
var response = await http
.get('https://lekcijas.va.lv/lekcijas_android/getAllCourseData.php');
var data = json.decode(response.body)["result"];
courses = List<Course>.from(data.map((x) => Course.fromJson(x)));
return Future.value(courses);
}
Widget showCoursePicker() {
return Container(
height: 250,
child: CupertinoPicker.builder(
childCount: courses.length,
itemExtent: 40,
useMagnifier: true,
magnification: 1.3,
onSelectedItemChanged: (value) {
selectedCourse = value;
print(selectedCourse);
setState(() {
_yearFrom = double.parse(courses[selectedCourse].course_from);
print(_yearFrom);
_yearTo = double.parse(courses[selectedCourse].course_to);
print(_yearTo);
});
},
itemBuilder: (ctx, index) {
return Center(
child: Text(
courses.isEmpty ? '' : courses[index].abbreviation,
),
);
}),
);
}
}

Related

Additional filters in Flutter

I am writing an application on Flutter. I was able to make one filter with multiple selections.
But I want to have additional filters.
I used Multi-Select, but in the case of multiple filters, I don't know how to apply it
With what help can I implement this?
import 'package:flutter/material.dart';
class MainPage extends StatelessWidget {
#override
Widget build(context) => Scaffold(
appBar: AppBar(title: Text("f"),
backgroundColor: Colors.black),
drawer: MediaQuery.of(context).size.width < 500 ? Drawer(
child: HomePage(),
) : null,
body: SafeArea(
child:Center(
child: MediaQuery.of(context).size.width < 500 ? Content() :
Row(
children: [
Container(
width: 200.0,
child: HomePage()
),
Container(
width: MediaQuery.of(context).size.width-200.0,
child: Content()
)
]
)
)
)
);
}
List devices_list = ["First device", "Second device", "Third device", "Fourth device", "Fifth device", "Sixth device", "Seventh device", "Eighth device", "Ninth device"];
class Content extends StatelessWidget{
#override
Widget build(context) =>
Scaffold(
backgroundColor: Colors.white,
body: LayoutBuilder(
builder: (context, constraints){
return AnimatedContainer(
duration: Duration(milliseconds: 500),
color: Colors.white,
child: Center(
child: Container(
constraints: BoxConstraints(
maxWidth: 800,),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5.0),),
child: ListView.builder(
itemCount: devices_list.length,
itemBuilder: (BuildContext context, int index) {
return SizedBox (
height: 60,
key: Key(devices_list[index]),
child: Card(
shape: const RoundedRectangleBorder(
side: BorderSide(color: Colors.black,width: 3),
borderRadius: BorderRadius.all(Radius.circular(15))),
child: TextButton(
onPressed: (){},
child: ListTile(title: Text(devices_list[index]))),
)
);
}
))));
}));
}
class MultiSelect extends StatefulWidget {
final List<String> items;
const MultiSelect({Key? key, required this.items}) : super(key: key);
#override
State<StatefulWidget> createState() => _MultiSelectState();
}
class _MultiSelectState extends State<MultiSelect> {
// this variable holds the selected items
final List<String> _selectedItems = [];
// This function is triggered when a checkbox is checked or unchecked
void _itemChange(String itemValue, bool isSelected) {
setState(() {
if (isSelected) {
_selectedItems.add(itemValue);
} else {
_selectedItems.remove(itemValue);
}
});
}
// this function is called when the Cancel button is pressed
void _cancel() {
Navigator.pop(context);
}
// this function is called when the Submit button is tapped
void _submit() {
Navigator.pop(context, _selectedItems);
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Select Manufactures'),
content: SingleChildScrollView(
child: ListBody(
children: widget.items
.map((item) => CheckboxListTile(
value: _selectedItems.contains(item),
title: Text(item),
controlAffinity: ListTileControlAffinity.leading,
onChanged: (isChecked) => _itemChange(item, isChecked!),
))
.toList(),
),
),
actions: [
TextButton(
child: const Text('Cancel'),
onPressed: _cancel,
),
ElevatedButton(
child: const Text('Submit'),
onPressed: _submit,
),
],
);
}
}
// Implement a multi select on the Home screen
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<String> _selectedItemsManufactures = [];
void _showMultiSelectManufactures() async {
// a list of selectable items
// these items can be hard-coded or dynamically fetched from a database/API
final List<String> _items = [
'Apple',
'Samsung',
'Xiaomi',
'Nokia',
'Huawei',
'Alcatel'
];
final List<String>? results = await showDialog(
context: context,
builder: (BuildContext context) {
return MultiSelect(items: _items);
},
);
// Update UI
if (results != null) {setState(() {_selectedItemsManufactures = results;});}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// use this button to open the multi-select dialog
ElevatedButton(
child: const Text('Manufactures'),
onPressed: _showMultiSelectManufactures,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black)
),
),
const Divider(
height: 5,
color: Colors.white,
),
// display selected items
Wrap(
children: _selectedItemsManufactures
.map((e) => Chip(
label: Text(e),
))
.toList(),
)
],
),
),
);
}
}
Addition. Addition. I would like changes in the Menu class to be reflected in the class MainPage.
class DevicesPage extends StatelessWidget {
#override
Widget build(context) => Scaffold(
appBar: AppBar(title: Text("IT"),
backgroundColor: Colors.black),
drawer: MediaQuery.of(context).size.width < 500 ? Drawer(
child: Menu(),
) : null,
body: SafeArea(
child:Center(
child: MediaQuery.of(context).size.width < 500 ? MainPage() :
Row(
children: [
Container(
width: 200.0,
child: Menu()
),
Container(
width: MediaQuery.of(context).size.width-200.0,
child: MainPage()
)
]
)
)
)
);
}
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
Map<String, List<String>?> filters = {};
List<Phone> filteredPhones = phoneList;
#override
Widget build(BuildContext context) {
return Scaffold(
body: filteredPhones.isEmpty
? const Center(child: Text('No product', style: TextStyle(fontSize: 16),))
: ListView.builder(
itemCount: filteredPhones.length,
itemBuilder: (_, index) {
final currentPhone = filteredPhones[index];
return ListTile(
title: Text(currentPhone.name),
subtitle: Text('${currentPhone.brand}-${currentPhone.color}'),
trailing: Text('${currentPhone.operation_system}'),
);
}
),
);
}
}
class Menu extends StatefulWidget {
const Menu({Key? key}) : super(key: key);
#override
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> {
Map<String, List<String>?> filters = {};
List<Phone> filteredPhones = phoneList;
void _filter() {
setState(() {
filteredPhones = phoneList;
filters.forEach((key, value) {
if((value ?? []).isNotEmpty) {
filteredPhones = filteredPhones.where((phone) {
switch(key) {
case 'brand':
return value!.contains(phone.brand);
case 'color':
return value!.contains(phone.color);
case 'operation_system':
return value!.contains(phone.operation_system);
return true;
default:
return false;
}
}).toList();
}
});
filters.clear();
Navigator.of(context).pop();
});
}
void _handleCheckFilter(bool checked, String key, String value) {
final currentFilters = filters[key] ?? [];
if(checked) {
currentFilters.add(value);
} else {
currentFilters.remove(value);
}
filters[key] = currentFilters;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('phones List'),
actions: [
IconButton(
icon: const Icon(Icons.filter_alt),
onPressed: () {
showDialog<Filter>(context: context, builder: (_) {
return SimpleDialog(
title: const Text('Filters',textAlign: TextAlign.center,),
contentPadding: const EdgeInsets.all(16),
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text('Select a brand'),
...brands.map((el) =>
CustomCheckboxTile(
label: el,
onChange: (check) => _handleCheckFilter(check, 'brand', el),
),
).toList(),
const Text('Select a operation_system'),
...operation_system.map((el) =>
CustomCheckboxTile(
label: el,
onChange: (check) => _handleCheckFilter(check, 'operation_system', el),
)
).toList(),
const Text('Select a colors'),
...colors.map((el) =>
CustomCheckboxTile(
label: el,
onChange: (check) => _handleCheckFilter(check, 'color', el),
),
).toList(),
const SizedBox(height: 24,),
ElevatedButton(onPressed: _filter, child: const Text('APPLY')),
],
),
],
);
});
},
),
],
),
body: filteredPhones.isEmpty
? const Center(child: Text('No product', style: TextStyle(fontSize: 16),))
: ListView.builder(
itemCount: filteredPhones.length,
itemBuilder: (_, index) {
final currentPhone = filteredPhones[index];
return ListTile(
title: Text(currentPhone.name),
subtitle: Text('${currentPhone.brand}-${currentPhone.color}'),
trailing: Text('${currentPhone.operation_system}'),
);
}
),
);
}
}
enter image description here
Well... you have many options. One way is to store all filters selected in a Map, like this:
final allFilters = {
"filterName1": "someValue",
"filterName2": "someOtherValue",
"fitlerName3": ["value1", "value2", "value3"]
}
And create a function that can handle each key of this map:
allFilter.forEach((key, value) {
switch(key) {
case "filterName1":
// ...some code
case "fitlerName2":
// ...more code
case "filterName3":
// ...much more code
}
})
You can check this demo project that I created https://github.com/felipeemidio/ListWithMultipleFilters

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.

How do i customize flappy_search_bar in flutter

whenever i enter a value in search bar i want to match it from the available list, for example if this is my list
List fooList = ['one', 'two', 'three', 'four', 'five']; and i enter e in search bar it should list those items which contains e in it. How can i do that, anybody please help.
class _HomeState extends State<HeaderWithSearchBox1> {
final SearchBarController<Post> _searchBarController = SearchBarController();
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = [];
var random = new Random();
for (int i = 0; i < 10; i++) {
posts
.add(Post("$text $i", "body random number : ${random.nextInt(100)}"));
}
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SearchBar<Post>(
minimumChars: 1,
searchBarPadding: EdgeInsets.symmetric(horizontal: 10),
headerPadding: EdgeInsets.symmetric(horizontal: 10),
listPadding: EdgeInsets.symmetric(horizontal: 10),
onSearch: _getALlPosts,
searchBarController: _searchBarController,
placeHolder: Center(
child: Text(
"PlaceHolder",
style: TextStyle(fontSize: 30),
)),
cancellationWidget: Text("Cancel"),
emptyWidget: Text("empty"),
onCancelled: () {
print("Cancelled triggered");
},
mainAxisSpacing: 10,
onItemFound: (Post post, int index) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.body),
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Detail()));
},
),
);
},
),
),
);
}
}
class Detail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: Center(child: Text("Detail", style: TextStyle(fontSize: 30),)),
),
);
}
}
You can copy paste run full code below
You filter fooList with where and use contains
code snippet
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = fooList
.where((element) =>
element.title.contains(text) || element.body.contains(text))
.toList();
return posts;
}
working demo
full code
import 'dart:math';
import 'package:flappy_search_bar/flappy_search_bar.dart';
import 'package:flappy_search_bar/scaled_tile.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Post {
final String title;
final String body;
Post(this.title, this.body);
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final SearchBarController<Post> _searchBarController = SearchBarController();
bool isReplay = false;
List<Post> fooList = [
Post('one', '1'),
Post('two', '2'),
Post('three', '3'),
Post('four', '4'),
Post('five', '5')
];
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = fooList
.where((element) =>
element.title.contains(text) || element.body.contains(text))
.toList();
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SearchBar<Post>(
minimumChars: 1,
searchBarPadding: EdgeInsets.symmetric(horizontal: 10),
headerPadding: EdgeInsets.symmetric(horizontal: 10),
listPadding: EdgeInsets.symmetric(horizontal: 10),
onSearch: _getALlPosts,
searchBarController: _searchBarController,
placeHolder: Center(
child: Text(
"PlaceHolder",
style: TextStyle(fontSize: 30),
)),
cancellationWidget: Text("Cancel"),
emptyWidget: Text("empty"),
onCancelled: () {
print("Cancelled triggered");
},
mainAxisSpacing: 10,
onItemFound: (Post post, int index) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.body),
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Detail()));
},
),
);
},
),
),
);
}
}
class Detail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
Text("Detail"),
],
),
),
);
}
}

Am Trying To calculate total price of a List of items

am making a shopping cart app where I want to calculate the total price of the products present in the cart I made a function for it and tried executing in init state but it's not working
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
#override
void initState() {
total();
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
the error I get:
The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (Student) => Null)
Try this:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
#override
void initState() {
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> studList=[];
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
studlist.forEach((element) {
setState((){
sum = sum + element.price;
});
});
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
Try running total() function if the data when the data is loaded, not in init. As data is initially empty, running it inside init will cause this error.
if (snapshot.hasData) {
studlist = snapshot.data;
total();
}
Full Code:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
total(); //Run the total() function here
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
try this
If I added Quantity increased totalQty but I have one issue if I removing Item in list
did not decrease. sorry my english not good
`total() {
studlist.forEach((element) {
if(element.qty!=null){
totalQty=totalQty+element.qty;
print(totalQty);
}
});
}
`

Can someone check my Dart code and tell me where I'm making mistake in returning data from my screen as a ListView

I am stuck here for the past 20 days in returning data in my app from the other screen. I'm new to programming and need help. I've been searching through all the internet to find an answer related to my query but nothing is helping though. I ask my fellow SO guys to please help.
You can look at the entire code which I've made open here.
My code:
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(30),
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () async {
final newList = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavoriteList(),
),
);
setState(() {
return ListView.builder(
itemCount: newList.length,
itemBuilder: (context, index){
return Container(
child: Text('item: $newList'),
);
},
);
});
},
)
],
),
);
}
}
The screen where Navigator.pop() is used:
final Set saved = Set();
class FavoriteList extends StatefulWidget {
#override
_FavoriteListState createState() => _FavoriteListState();
}
class _FavoriteListState extends State<FavoriteList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red),
body: SafeArea(
child: ListView.builder(
itemCount: 53,
itemBuilder: (context, index) {
return CheckboxListTile(
activeColor: Colors.red,
checkColor: Colors.white,
value: saved.contains(index),
onChanged: (val) {
setState(() {
// isChecked = val; // changed
// if(val == true){ // changed
// __saved.add(context); // changed
// } else{ // changed
// __saved.remove(context); // changed
// } // changed
if (val == true) {
saved.add(index);
} else {
saved.remove(index);
}
});
},
title: Row(
children: <Widget>[
Image.asset('lib/images/${images[index]}'),
SizedBox(
width: 10,
),
Text(nameOfSite[index]),
],
),
);
},
),
),
floatingActionButton: FloatingActionButton(
foregroundColor: Colors.red,
child: Icon(Icons.check),
onPressed: () {
Navigator.pop<Set>(context, saved);
},
),
);
}
}
Here is the SecondPage and FavoriteList that I made
import 'package:flutter/material.dart';
import 'package:aioapp2/lists.dart';
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) {
if (updatedFavorites != null)
setState(() {
favorites = updatedFavorites;
});
});
},
),
),
)
],
);
}
Widget _getFavoriteList() {
if (favorites?.isNotEmpty == true)
return _FavoriteList();
else
return _EmptyFavoriteList();
}
}
class _EmptyFavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Add Your Favorite Sites Here!❤',
style: TextStyle(color: Colors.white),
),
Icon(
Icons.favorite,
size: 150,
color: Colors.blue[100],
),
],
),
),
),
),
],
);
}
}
class _FavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: favorites.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('lib/images/${images[index]}'),
),
title: Text(nameOfSite[favorites.elementAt(index)]),
);
},
);
}
}
//Its FavoriteList Page. I changed the name
class EditFavorites extends StatefulWidget {
#override
_EditFavoritesState createState() => _EditFavoritesState();
}
class _EditFavoritesState extends State<EditFavorites> {
final _editableFavorites = <int>{};
#override
void initState() {
_editableFavorites.addAll(favorites);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red,
actions: <Widget>[
IconButton(
icon: Icon(Icons.done),
onPressed: () {
Navigator.pop<Set>(context, _editableFavorites);
},
)
],
),
//backgroundColor: Colors.indigo,
body: SafeArea(
child: ListView.builder(
itemCount: nameOfSite.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('lib/images/${images[index]}'),
),
title: Text(nameOfSite[index]),
trailing: IconButton(
icon: _editableFavorites.contains(index)
? Icon(
Icons.favorite,
color: Colors.red,
)
: Icon(
Icons.favorite_border,
color: Colors.grey,
),
onPressed: () {
setState(() {
if (_editableFavorites.contains(index))
_editableFavorites.remove(index);
else
_editableFavorites.add(index);
});
},
),
);
},
),
),
);
}
}
Just replace secondtab.dart with this code.
You can copy paste run full code below
You have to move out return ListView to the same layer with FloatingActionButton
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SecondPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
Set newList = {};
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(30),
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
ListView.builder(
itemCount: newList.length,
itemBuilder: (context, index) {
return Container(
child: Text('item: ${newList.elementAt(index)}'),
);
},
),
FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () async {
newList = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavoriteList(),
),
);
setState(() {});
},
)
],
),
);
}
}
final Set saved = Set();
class FavoriteList extends StatefulWidget {
#override
_FavoriteListState createState() => _FavoriteListState();
}
class _FavoriteListState extends State<FavoriteList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red),
body: SafeArea(
child: ListView.builder(
itemCount: 53,
itemBuilder: (context, index) {
return CheckboxListTile(
activeColor: Colors.red,
checkColor: Colors.white,
value: saved.contains(index),
onChanged: (val) {
setState(() {
// isChecked = val; // changed
// if(val == true){ // changed
// __saved.add(context); // changed
// } else{ // changed
// __saved.remove(context); // changed
// } // changed
if (val == true) {
saved.add(index);
} else {
saved.remove(index);
}
});
},
title: Row(
children: <Widget>[
//Image.asset('lib/images/${images[index]}'),
SizedBox(
width: 10,
),
Text('nameOfSite[index]'),
],
),
);
},
),
),
floatingActionButton: FloatingActionButton(
foregroundColor: Colors.red,
child: Icon(Icons.check),
onPressed: () {
Navigator.pop<Set>(context, saved);
},
),
);
}
}