How to add another List of item for DropDownMenu, and then use the items in widget - flutter

So I'm trying to make a drop down menu for each options and insert a different List of items each. First of all, because my Dropdownmenu widget shares the same properties for one and another, I extracted the widget to another class name "MenuDropDown". Here is the code for the widget.
import 'package:flutter/material.dart';
import 'List.dart';
class MenuDropDown extends StatefulWidget {
final String dropdownText;
final List<DropdownMenuItem<String>> itemList;
MenuDropDown({this.dropdownText, this.itemList});
#override
_MenuDropDownState createState() => _MenuDropDownState();
}
class _MenuDropDownState extends State<MenuDropDown> {
String selectedItem;
List<DropdownMenuItem> getGroomingTypeList() {
List<DropdownMenuItem<String>> dropdownItems = [];
for (String groomingType in groomingTypeList) {
var newItem = DropdownMenuItem(
child: Text(groomingType),
value: groomingType,
);
dropdownItems.add(newItem);
}
return dropdownItems;
}
List<DropdownMenuItem> getCatBreedsList() {
List<DropdownMenuItem<String>> dropdownItems = [];
for (String catBreed in catBreedsList) {
var newItem = DropdownMenuItem(
child: Text(catBreed),
value: catBreed,
);
dropdownItems.add(newItem);
}
return dropdownItems;
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 8.0, 0, 10.0),
child: Container(
width: 325.0,
height: 50.0,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(2.5, 5.5),
blurRadius: 5.0,
)
],
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
child: DropdownButtonHideUnderline(
child: DropdownButton(
value: selectedItem,
hint: Padding(
padding: const EdgeInsets.fromLTRB(22.0, 0, 0, 0),
child: Text(
widget.dropdownText,
style: TextStyle(),
),
),
items: widget.itemList,
onChanged: (value) {
setState(() {
selectedItem = value;
});
}),
),
),
);
}
}
above here I created a method to get the list item from the list class that I already created, First it works if I hardcoded the method into the Dropdownmenu's items properties to show the item list, but because I need to use the different list for the different widget, so I think if I try to create a variable of List named itemList, so I can access it from the other class where I can call just the customized variable.
And this is the Stateful widget where i use my Extracted Dropdownmenu widget :
import 'package:flutter/material.dart';
import 'TitleName.dart';
import 'dropdownmenu.dart';
class InformationDetail extends StatefulWidget {
#override
_InformationDetailState createState() => _InformationDetailState();
}
class _InformationDetailState extends State<InformationDetail> {
MenuDropDown _menuDropDown = MenuDropDown();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(25.0, 68.0, 70.0, 26.0),
child: Text(
'Information Detail',
style: TextStyle(fontSize: 35.0),
),
),
Column(
// Wrap Column
children: <Widget>[
Column(
children: <Widget>[
TitleName(
titleText: 'Grooming Type',
infoIcon: Icons.info,
),
MenuDropDown(
dropdownText: 'Grooming Type...',
//I'm trying to implement the list here with a custom variable that contain
a method with different list in dropdownmenu class
itemlist: getGroomingTypeList(),
),
TitleName(
titleText: 'Cat Breeds',
),
MenuDropDown(
dropdownText: 'Cat Breeds...',
),
TitleName(
titleText: 'Cat Size',
infoIcon: Icons.info,
),
MenuDropDown(
dropdownText: 'Cat Size...',
),
TitleName(
titleText: 'Add-On Services',
),
MenuDropDown(
dropdownText: 'Add - On Services...',
),
Container(
margin: EdgeInsets.fromLTRB(0, 15.0, 0, 0),
width: 75.0,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
border: Border.all(
color: Colors.black,
),
borderRadius: BorderRadius.circular(12.0),
),
child: IconButton(
icon: Icon(Icons.arrow_forward),
onPressed: () {
Navigator.of(context)
.pushNamed('/ReservationDetail');
},
),
),
],
),
],
),
],
),
),
),
);
}
}
And this is the list that I want to use for each of dropdown menu widget
const List groomingTypeList = ['Basic Grooming', 'Full Grooming'];
const List catBreedsList = [
'Persia',
'Anggora',
'Domestic',
'Maine Coon',
'Russian Blue',
'Slamese',
'Munchkin',
'Ragdoll',
'Scottish Fold',
];
const List catSizeList = [
'Small Size',
'Medium Size',
'Large Size',
'Extra Large Size',
];
const List addOnServicesList = [
'Spa & Massage',
'Shaving Hair / Styling',
'Injection Vitamis Skin & Coat',
'Cleaning Pet House and Environment',
'Fur Tangled Treatment',
];
I got stuck from there. How to use a different list for each dropdown menu widget that I made, because I already tried to make a constructor, variable, and method so I can use it separately, but instead I got an error that says,
type 'List' is not a subtype of type 'List<DropdownMenuItem>'
I think I implemented it in the wrong way in the first place. I really need help with another solution to these problems. thank you, everyone!

Just check out the code that I have made some changes :
import 'package:flutter/material.dart';
void main() => runApp(InformationDetail());
class InformationDetail extends StatefulWidget {
#override
_InformationDetailState createState() => _InformationDetailState();
}
class _InformationDetailState extends State<InformationDetail> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Container(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(25.0, 68.0, 70.0, 26.0),
child: Text(
'Information Detail',
style: TextStyle(fontSize: 35.0),
),
),
Column(
// Wrap Column
children: <Widget>[
Column(
children: <Widget>[
Text(
'Grooming Type',
),
MenuDropDown(
dropdownText: 'Grooming Type...',
//I'm trying to implement the list here with a custom variable that contain
// a method with different list in dropdownmenu class
type: "groomingType",
),
Text(
'Cat Breeds',
),
MenuDropDown(
dropdownText: 'Cat Breeds...',
type: "catBreeds",
),
Text(
'Cat Size',
),
MenuDropDown(
dropdownText: 'Cat Size...',
type: "catSize",
),
Text(
'Add-On Services',
),
MenuDropDown(
dropdownText: 'Add - On Services...',
type: "addOnServices",
),
Container(
margin: EdgeInsets.fromLTRB(0, 15.0, 0, 0),
width: 75.0,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
border: Border.all(
color: Colors.black,
),
borderRadius: BorderRadius.circular(12.0),
),
child: IconButton(
icon: Icon(Icons.arrow_forward),
onPressed: () {
Navigator.of(context)
.pushNamed('/ReservationDetail');
},
),
),
],
),
],
),
],
),
),
),
),
);
}
}
class MenuDropDown extends StatefulWidget {
final String dropdownText;
final String type;
MenuDropDown({this.dropdownText, this.type});
#override
_MenuDropDownState createState() => _MenuDropDownState();
}
class _MenuDropDownState extends State<MenuDropDown> {
String selectedItem;
List<String> dropdownItems = [];
List<String> groomingTypeList = ['Basic Grooming', 'Full Grooming'];
List<String> catBreedsList = [
'Persia',
'Anggora',
'Domestic',
'Maine Coon',
'Russian Blue',
'Slamese',
'Munchkin',
'Ragdoll',
'Scottish Fold',
];
List<String> catSizeList = [
'Small Size',
'Medium Size',
'Large Size',
'Extra Large Size',
];
List<String> addOnServicesList = [
'Spa & Massage',
'Shaving Hair / Styling',
'Injection Vitamis Skin & Coat',
'Cleaning Pet House and Environment',
'Fur Tangled Treatment',
];
List<String> getListBasedOnName(String value) {
print(value);
switch (value) {
case "groomingType":
return groomingTypeList;
break;
case "catBreeds":
return catBreedsList;
break;
case "catSize":
return catSizeList;
break;
case "addOnServices":
return addOnServicesList;
break;
}
return null;
}
#override
void initState() {
super.initState();
print(widget.type);
dropdownItems = getListBasedOnName(widget.type);
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 8.0, 0, 10.0),
child: Container(
width: 325.0,
height: 50.0,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(2.5, 5.5),
blurRadius: 5.0,
)
],
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
child: DropdownButtonHideUnderline(
child: DropdownButton(
value: selectedItem,
hint: Padding(
padding: const EdgeInsets.fromLTRB(22.0, 0, 0, 0),
child: Text(
widget.dropdownText,
style: TextStyle(),
),
),
items: dropdownItems.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
selectedItem = value;
});
}),
),
),
);
}
}
As some of the widgets were missing, I have added mine you can change as per your needs. Let me know if it works.

Related

How do I create a function that changes data on page so I don't have to create multiple different pages for each stall

I have to create multiple files for different stalls but it seems so wrong and I know there's a better way but I just don't know how. Is there a way to create something like a page builder that will let me create multiple pages with different information from a single file. The difficult part is to make the onTap function of the images send the user to the stall_page of the selected stall. I tried doing this by making a view attribute in which I create a page and manually import the page route. But that involves creating a stall_info and stall_page for every single stall.
Instead of creating stall1_page, stall2_page and so on, can I create a generic stall function that will use the same page but just change the data? I know that's LITERALLY the point of object oriented programming languages but I'm really new to them as you'll tell my previous stupid questions.
This is the homescreen dashboard
class GridDashboard extends StatelessWidget {
Item item1 = Item(
title: 'Tray blazers',
subtitle: 'Open',
event: 'by Chef Tracy',
img: 'assets/images/tray_blazers-cr.png',
view: stallPage,
);
Item item2 = Item(
title: 'Papa Rimz',
subtitle: 'Open',
event: '',
img: 'assets/images/papa_rimz.png',
view: papaRimzPage,
);
Item item3 = Item(
title: 'W SAUCE',
subtitle: 'Open',
event: '',
img: 'assets/images/w_sauce-removebg.png',
view: wSaucePage,
);
Item item4 = Item(
title: 'African Kitchen',
subtitle: 'Open',
event: '',
img: 'assets/images/cherry-kitchen.png',
view: africanKitchenPage,
);
Item item5 = Item(
title: 'Suya Craze',
subtitle: 'Open',
event: '',
img: 'assets/images/suya_craze.png',
view: suyaCrazePage,
);
Item item6 = Item(
title: 'Zulkys cafe',
subtitle: 'Open',
event: '',
img: 'assets/images/zulkys-removeb.png',
view: zulkysCafePage,
);
Item item7 = Item(
title: 'Street food',
subtitle: 'Open',
event: '',
img: 'assets/images/street_food--removebg-.png',
view: streetFoodPage,
);
#override
Widget build(BuildContext context) {
List<Item> myList = [
item1,
item2,
item3,
item4,
item5,
item6,
item7,
];
return Flexible(
child: GridView.count(
childAspectRatio: 1.0,
padding: const EdgeInsets.only(left: 16, right: 16),
crossAxisCount: 2,
crossAxisSpacing: 18,
mainAxisSpacing: 18,
children: myList.map(
(data) {
return Container(
decoration: BoxDecoration(
color: const Color(0xff453658),
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(data.view);
},
child: Image.asset(
data.img,
width: 90, //double.infinity
),
),
const SizedBox(height: 14),
Text(
data.title,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 13,
color: Colors.white,
),
),
const SizedBox(height: 8),
Text(
data.subtitle,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 10,
color: Colors.white38,
),
),
const SizedBox(height: 8),
// Text(
// data.event,
// style: const TextStyle(
// fontWeight: FontWeight.w600,
// fontSize: 11,
// color: Colors.white70,
// ),
// ),
],
),
);
},
).toList(),
),
);
}
}
class Item {
String title;
String subtitle;
String event;
String img;
String view;
Item({
required this.title,
required this.subtitle,
required this.event,
required this.img,
required this.view,
});
}
This is my stall_page:
class StallPage extends StatefulWidget {
const StallPage({super.key});
#override
State<StallPage> createState() => _StallPageState();
}
class _StallPageState extends State<StallPage> {
var selected = 0;
final pageController = PageController();
final stall = Stall.generateRestaurant1();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xff392850), //kBackground,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomAppBar(
Icons.arrow_back_ios_outlined,
Icons.search_outlined,
leftCallback: () => Navigator.of(context).pop(),
),
StallInfo(), //
FoodList(
selected,
(int index) {
setState(() {
selected = index;
});
pageController.jumpToPage(index);
},
stall,
),
Expanded(
child: FoodListView(
selected,
(int index) {
setState(() {
selected = index;
});
},
pageController,
stall,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 25),
height: 60,
child: SmoothPageIndicator(
controller: pageController,
count: stall.menu.length,
effect: CustomizableEffect(
dotDecoration: DotDecoration(
width: 8,
height: 8,
color: Colors.grey.withOpacity(0.5),
borderRadius: BorderRadius.circular(8),
),
activeDotDecoration: DotDecoration(
width: 10,
height: 10,
color: kBackground,
borderRadius: BorderRadius.circular(10),
dotBorder: const DotBorder(
color: kPrimaryColor,
padding: 2,
width: 2,
),
),
),
onDotClicked: (index) => pageController.jumpToPage(index),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: kPrimaryColor,
elevation: 2,
child: const Icon(
Icons.shopping_cart_outlined,
color: Colors.black,
size: 30,
),
),
);
}
}
This is my stall_info
class StallInfo extends StatelessWidget {
final stall = Stall.generateRestaurant1();
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 40),
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
stall.name,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Row(
children: [
Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.blueGrey.withOpacity(0.4),
borderRadius: BorderRadius.circular(5),
),
child: Text(
stall.label,
style: const TextStyle(
color: Colors.white,
),
)),
const SizedBox(
width: 10,
),
],
)
],
),
ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.asset(
stall.logoUrl,
width: 80,
),
),
],
),
const SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
stall.desc,
style: const TextStyle(fontSize: 16),
),
Row(
children: [
const Icon(
Icons.star_outline,
color: Colors.amber,
),
Text(
'${stall.score}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 15),
],
)
],
)
],
),
);
}
}
And this is stall
class Stall {
String name;
String label;
String logoUrl;
String desc;
num score;
Map<String, List<Food>> menu;
Stall(
this.name,
this.label,
this.logoUrl,
this.desc,
this.score,
this.menu,
);
static Stall generateRestaurant1() {
return Stall(
'Tray blazers',
'Restaurant',
'assets/images/tray_blazers.jpg',
'Tray Blazers by Chef Tracy',
4.5,
{
'Recommended': Food.generateRecommendedFoods1(),
'Popular': Food.generatePopularFoods1(),
'Smoothie': [],
'Rice': [],
},
);
}
}
If I understand the question correctly, you want to open the StallPage but show different values on the page depending on which image (pertaining to a given 'Stall') was selected on the previous page? I.e. clicking on item2 should open the StallPage with the restaurant title "Papa Rimz" etc.?
In that case, you can pass the argument to your new route builder via the onTap() function as a constructor parameter instead of calling Stall.generateRestaurant1() with hardcoded values in a given dart file.
StallInfo
Instead of getting your stall data inside the build method, you simply accept it as a required parameter for your widget. Now you have access to the data (title, ...) anywhere inside here.
class StallInfo extends StatelessWidget {
// Contains the stall object with its name, label, menu etc.
final Stall stall;
StallInfo({super.key, required this.stall});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 40),
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Column(
...
),
);
}
}
HomeScreen
I'm a bit confused as to what the item list in your your home screen is for. Are these food items in a restaurant? Because if so, I think it would be much easier to save them inside the stall as a list of items and then use that list here:
List<Stall> _stalls = [...];
I'd like to note here that you hardcoded all the items by name and then, in your build method, added them to a list. Since you don't need their names anywhere, it would be just a little bit better to move the List<Stall> myList outside the build method and simply assign the objects directly (that is, before you add a real database):
class GridDashboard extends StatelessWidget {
List<Stall> _stalls = [
Stall('Tray blazers', ...),
Stall('Papa Rimz', ...),
];
#override
Widget build(BuildContext context) {
// do something with your stalls, onTap, pass the element directly
....
children: _stalls.map(
(data) {
return GestureDetector(
onTap: (){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => StallPage(stall: data)
));
}
);
}),
}
}
If you use a builder function for your GridView (which you should if there can be a lot of stalls), in the onTap() you can instead call:
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => StallPage(stall: _stalls.elementAt(index))
));
StallPage
This page will look something like this
class StallPage extends StatefulWidget {
final Stall stall; // Take in the stall you passed from your home screen
const StallPage({super.key, required this.stall});
#override
State<StallPage> createState() => _StallPageState();
}
class _StallPageState extends State<StallPage> {
var selected = 0;
final pageController = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
...
StallInfo(stall: widget.stall), // This is how you can access the values passed inside a StatefulWidget
...
);
}
}

How To Use Shared Preference In This Todo App Code?

import 'package:flutter/material.dart';
import '../main.dart';
import 'colors.dart';
import 'todo_item.dart';
import 'todo.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Toodoo extends StatefulWidget {
const Toodoo({Key? key}) : super(key: key);
#override
State<Toodoo> createState() => _ToodooState();
}
class _ToodooState extends State<Toodoo> {
final todosList = ToDo.todoList();
List<ToDo> _foundToDo = [];
final _todoController = TextEditingController();
final GlobalKey<ScaffoldState> _key = GlobalKey();
String ""
#override
void initState() {
_foundToDo = todosList;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.menu, color: Colors.black),
onPressed: () => _key.currentState!.openDrawer(),
),
backgroundColor: const Color(0xff346594),
title: const Text("ToDos", style: TextStyle(color: Colors.black)),
),
backgroundColor: tdBGColor,
body: Stack(
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 15,
),
child: Column(
children: [
searchBox(),
Expanded(
child: ListView(
children: [
Container(
margin: const EdgeInsets.only(
top: 50,
bottom: 20,
),
child: const Text(
'All ToDos',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
for (ToDo todo in _foundToDo.reversed)
ToDoItem(
todo: todo,
onToDoChanged: _handleToDoChange,
onDeleteItem: _deleteToDoItem,
),
],
),
)
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Row(children: [
Expanded(
child: Container(
margin: const EdgeInsets.only(
bottom: 20,
right: 20,
left: 20,
),
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 5,
),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 0.0),
blurRadius: 10.0,
spreadRadius: 0.0,
),
],
borderRadius: BorderRadius.circular(10),
),
child: TextField(
controller: _todoController,
decoration: const InputDecoration(
hintText: 'Add a new todo item',
border: InputBorder.none),
),
),
),
Container(
margin: const EdgeInsets.only(
bottom: 20,
right: 20,
),
child: ElevatedButton(
onPressed: () {
_addToDoItem(_todoController.text);
},
style: ElevatedButton.styleFrom(
backgroundColor: tdBlue,
minimumSize: const Size(60, 60),
elevation: 10,
),
child: const Text('+', style: TextStyle(fontSize: 40),),
),
),
]),
),
],
),
drawer: const Navigation(),
);
}
void _handleToDoChange(ToDo todo) {
setState(() {
todo.isDone = !todo.isDone;
});
}
void _deleteToDoItem(String id) {
setState(() {
todosList.removeWhere((item) => item.id == id);
});
}
void _addToDoItem(String toDo) async{
final sp = await SharedPreferences.getInstance();
setState(() {
todosList.add(ToDo(
id: DateTime.now().millisecondsSinceEpoch.toString(),
todoText: toDo,
));
});
sp.setString(id, todo)
_todoController.clear();
}
void _runFilter(String enteredKeyword) {
List<ToDo> results = [];
if (enteredKeyword.isEmpty) {
results = todosList;
} else {
results = todosList
.where((item) => item.todoText!
.toLowerCase()
.contains(enteredKeyword.toLowerCase()))
.toList();
}
setState(() {
_foundToDo = results;
});
}
Widget searchBox() {
return Container(
);
}
}
I am trying to save todo data locally, using shared preferences but don't know how to implement this, any help on this will be appreciated.Shared preferences is the best thing to use in such apps, so that's why I am using shared preference instead of firebase.
I have initialized Shared preferences in future but the thing is how to read and show the data with the controller given above the code.
Use Hive database or sqflite to save such kind of data(Good practice).You should use shared preference to store small bunch of data.
Yeah, shared preference is a good way to store data permanently on the local device. I can suggest you one way of doing this.
You need to create only one key (and value), and the value would be a stringified array. Every time user created new todo, you first need to pull the previous array, parse it to JSON, push the latest todo in that array, and set the key value again.
This array will also help you if you want to show the user all the todos by pulling the data only from one key, cause all the todos will the store in one array.
var todos = [
{
"id": "",
"todoText": "''"
},
{
"id": "",
"todoText": "''"
},
...
]
But you need to store stringified array, so you need to parse back to JSON after get data from shared preferences

How to solve: type 'List<dynamic>' is not a subtype of type 'String' [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I want to update image from listofTaskNotApprove class which it will pass the object of documentsnapshot into the EditTaskNotApprove. Before I update the image, I need to display specific of image where the user will be select specific info from listofTaskNotApprove. The problem is how to display the current index of image into the new screen?
ListOfTaskNotAccepted class.
import 'package:carousel_pro/carousel_pro.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fyp/screen/RecordOfficer/EditTaskNotApprove.dart';
import 'package:fyp/shared/Loading.dart';
import 'package:google_fonts/google_fonts.dart';
class ListOfTaskNotAccepted extends StatefulWidget {
#override
_ListOfTaskNotAcceptedState createState() => _ListOfTaskNotAcceptedState();
}
final FirebaseAuth auth = FirebaseAuth.instance;
Stream<QuerySnapshot> getUser(BuildContext context) async* {
final FirebaseUser rd = await auth.currentUser();
yield* Firestore.instance.collection("Task").where('uid',isEqualTo: rd.uid).where("verified", isEqualTo: 'TidakSah').snapshots();
}
class _ListOfTaskNotAcceptedState extends State<ListOfTaskNotAccepted> {
List<NetworkImage> _listOfImages = <NetworkImage>[];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Aduan Tidak Diterima"),
backgroundColor: Colors.redAccent,
),
body: Container(
child: StreamBuilder(
stream: getUser(context),
builder: (context, snapshot){
if (snapshot.hasError || !snapshot.hasData) {
return Loading();
} else{
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index){
DocumentSnapshot da = snapshot.data.documents[index];
_listOfImages =[];
for(int i =0; i <da['url'].length; i++){
_listOfImages.add(NetworkImage(da['url'][i]));
}
return Card(
child:ListTile(
title: Container(
alignment: Alignment.centerLeft,
child: Column(
children: <Widget>[
SizedBox(height: 5.0),
Container(alignment: Alignment.centerLeft,
child: Row(
children: [
Text("Sumber Aduan: ", style: GoogleFonts.asap(fontWeight: FontWeight.bold)),
Text(da['sumberAduan'], style: GoogleFonts.asap(fontWeight: FontWeight.bold)),
],
),
),
SizedBox(height: 5.0),
Container(alignment: Alignment.centerLeft,
child: Row(
children: [
Text("Nombor Aduan: ", style: GoogleFonts.lato(fontWeight: FontWeight.bold)),
Text(da['noAduan'], style: GoogleFonts.lato(fontWeight: FontWeight.bold)),
],
),
),
SizedBox(height: 5.0),
Container(alignment: Alignment.centerLeft,
child: Row(
children: [
Text("Lokasi: ", style: GoogleFonts.lato(fontWeight: FontWeight.bold)),
Text(da['kawasan'] + " " + da['naJalan'], style: GoogleFonts.lato(fontWeight: FontWeight.bold)),
],
),
),
SizedBox(height: 5.0),
Container(alignment: Alignment.centerLeft,
child: Row(
children: [
Text("Kategori: ", style: GoogleFonts.arimo(fontWeight: FontWeight.w500)),
Text(da['kategori'], style: GoogleFonts.arimo(fontWeight: FontWeight.w500)),
],
),
),
Column(
children: [
Container(
margin: EdgeInsets.all(10.0),
height: 200,
decoration: BoxDecoration(
color: Colors.white
),
width: MediaQuery.of(context).size.width,
child: Carousel(
boxFit: BoxFit.cover,
images: _listOfImages,
autoplay: false,
indicatorBgPadding: 5.0,
dotPosition: DotPosition.bottomCenter,
animationCurve: Curves.fastLinearToSlowEaseIn,
animationDuration: Duration(milliseconds: 2000),
),
)
],
)
],
),
),
subtitle: Container(
child: Column(
children: [
SizedBox(height: 5.0),
Container(alignment: Alignment.centerLeft,
child: Row(
children: [
Text("Catatan: ", style: GoogleFonts.arimo(fontWeight: FontWeight.w500)),
Text(da['comments'], style: GoogleFonts.arimo(fontWeight: FontWeight.w500)),
],
),
),
],
),
),
onTap: () {Navigator.push(context, MaterialPageRoute(builder: (context) => EditTask(da:da)));}
)
);
});
}
}),
)
);
}
}
Here is EditTask class which I need to display current index of image that selected by user.
import 'package:carousel_pro/carousel_pro.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class EditTask extends StatefulWidget {
final DocumentSnapshot da;
const EditTask({Key key, this.da}) : super(key: key);
#override
_EditTaskState createState() => _EditTaskState(da);
}
class _EditTaskState extends State<EditTask> {
DocumentSnapshot da;
_EditTaskState(DocumentSnapshot da){
this.da = da;
}
TextEditingController _noAduan;
TextEditingController _sumberAduan;
TextEditingController _kategori;
DateTime myDateTime = DateTime.now();
#override
void initState(){
super.initState();
_noAduan = TextEditingController(text: widget.da.data['noAduan']);
_sumberAduan =TextEditingController(text: widget.da.data['sumberAduan']);
_kategori = TextEditingController(text: widget.da.data['kategori']);
myDateTime = (da.data['date']).toDate();
_listOfImages = NetworkImage(da.data['url']) as List<NetworkImage>; // this line show the error
}
List <String> sumber = <String> ['Sistem Aduan MBPJ', 'Sistem Aduan Waze', 'Sistem Aduan Utiliti'];
List <String> kate = <String> ['Segera', 'Pembaikan Biasa'];
String kategori;
String sumberAduan;
List <NetworkImage> _listOfImages = <NetworkImage>[];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Kemaskini Aduan"),
backgroundColor: Colors.redAccent,
),
body: Container(
padding: const EdgeInsets.all(16.0),
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(height: 10.0),
TextFormField(
decoration:InputDecoration(
hintText: myDateTime.toString(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5))),
onChanged: (value){
setState(() {
myDateTime = value as DateTime;
print(myDateTime);
});
},
),
SizedBox(height: 10.0),
TextFormField(
decoration:InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5))),
controller: _noAduan,
),
SizedBox(height: 10.0),
DropdownButtonFormField(
hint:Text(widget.da.data['sumberAduan']),
decoration: InputDecoration(
prefixIcon: Icon(Icons.perm_contact_calendar),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(5))),
isExpanded: true,
value: sumberAduan,
onChanged: (newValue) {
setState(() {
sumberAduan = newValue;
_sumberAduan.text = sumberAduan;
});
},
items: sumber.map((sum){
return DropdownMenuItem(
value: sum,
child: new Text(sum),
);
}).toList(),
),
SizedBox(height: 10.0),
DropdownButtonFormField(
hint:Text(widget.da.data['kategori']),
decoration: InputDecoration(
prefixIcon: Icon(Icons.perm_contact_calendar),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(5))),
isExpanded: true,
value: kategori,
onChanged: (newValue) {
setState(() {
kategori = newValue;
_kategori.text = kategori;
});
},
items: kate.map((ka){
return DropdownMenuItem(
value: ka,
child: new Text(ka),
);
}).toList(),
),
Container(
margin: EdgeInsets.all(10.0),
height: 200,
decoration: BoxDecoration(
color: Colors.white
),
width: MediaQuery.of(context).size.width,
child: Carousel(
boxFit: BoxFit.cover,
autoplay: false,
//images: _listOfImages,
indicatorBgPadding: 5.0,
dotPosition: DotPosition.bottomCenter,
animationCurve: Curves.fastLinearToSlowEaseIn,
animationDuration: Duration(milliseconds: 2000),
),
)
],
),
),
)
);
}
}
the image that need to display for update image
This is how I want to display image in class EditTask when the user want to update information from ListOfTaskNotApprove
The error show that "type 'List' is not a subtype of type 'String'"
Can someone help me? because I had tried many method to solve this problem but it didn't work for me.
You say:
_listOfImages = NetworkImage(da.data['url']) as List<NetworkImage>; // this line show the error
Yes, you can't cast a NetworkImage to a List<NetworkImage>. You probably meant:
_listOfImages = [ NetworkImage(da.data['url']) ] as List<NetworkImage>;
The thing is your are getting a list of url's from Firebase storage which are Strings but you are adding this strings into a list of type Network Image which is wrong. As a list of string cannot be converted to a list of Network Image.
There are 2 ways to resolve this-
Change your list type to List and then wherever you show this image use
list data as an argument for Network Image.
List<String> urls=new List();
//suppose list is not empty
....
return NetworkImage(urls[i]);
....
While adding url's to your list add an Network Image object and directly use the list item while showing images.
List<NetworkImage> list=new List();
list.add(NetworkImage('some url'));
....
return list[i];
....

Flutter- Why I can't see the data inside the Dropdown

I'm new to Flutter and I can't understand why I can't see the data inside the DropDownButton even tho the lists that I use to create the DropDownButton have the data inside them. Can anyone explain to me why is this happening? The only clue I have is that the DropDownButton starts the creation before I create the list from which is taking the data.
The problem is that my dropdown list is empty.
I provide the entire code below.
Code :
import 'package:flutter/material.dart';
import 'ListOfClienti.dart';
class CreateClient extends StatefulWidget {
#override
_CreateClientState createState() => _CreateClientState();
}
class _CreateClientState extends State<CreateClient> {
String ClientCod = '';
String currentClient = '';
List<String> listNameOfClients = [];
List<DropdownMenuItem<String>> actualList2 = [];
void getClientsName() {
for (var i = 0; i <= ListDatabase.length - 1; i++) {
var name = ListDatabase[i].nome;
print(name);
listNameOfClients.add(name);
}
}
void createListWithClientName() {
for (String oneByOneClient in listNameOfClients) {
var VariableToInsert2 = DropdownMenuItem(
child: Text(oneByOneClient),
value: oneByOneClient,
);
actualList2.add(VariableToInsert2);
}
}
//Method that allows me to create the DropDownButton
DropdownButton<String> createNameMachine() {
return DropdownButton(
items: actualList2,
style: TextStyle(
color: Colors.black,
fontFamily: 'Keqima',
fontSize: 15,
),
value: currentClient,
onChanged: (clientSelected) {
setState(() {
currentClient = clientSelected;
});
},
);
}
#override
Widget build(BuildContext context) {
return Container(
color: Color(0xff757575),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(16),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Inserisci il codice cliente',
),
onChanged: (textInsideTheField) {
ClientCod = textInsideTheField;
},
),
),
Padding(
padding: EdgeInsets.all(16),
child: Row(
children: <Widget>[
FlatButton(
onPressed: () {
getClientsName();
createListWithClientName();
print(actualList2.length);
},
child: Text(
'Clienti : ',
style: TextStyle(
fontSize: 20,
fontFamily: 'Keqima',
),
),
),
SizedBox(
width: 20,
),
createNameMachine(),
],
),
),
],
),
),
);
}
}
To fix this problem I had to change to things :
Thing: I had to change the List from this List listNameOfClients = []; to this List listNameOfClients = [''];
I had to integrate the setState and inside to call the functions.
setState(() {
getClientsName();
createListWithClientName();
});

Flutter how change dropdownlist item color

I want to make the color of the values ​​in the hour list yellow with the data in the selected list. Here is the code for the dropdown list and screenshot. how can I do that.
enter image description here
import 'package:flutter/material.dart';
class deneme extends StatefulWidget {
#override
_denemeState createState() => _denemeState();
}
class _denemeState extends State<deneme> {
List<String> hour = ["09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00"];
List<String> selected = ["09:00", "12:00", "16:00"];
int hourId;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Deneme"),
),
body: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent, width: 2),
borderRadius: BorderRadius.all((Radius.circular(10)))),
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 24),
margin: EdgeInsets.all(12),
child: DropdownButtonHideUnderline(
child: DropdownButton<int>(
items: hour.map((h) {
return DropdownMenuItem<int>(
child: Text(
h,
style: TextStyle(fontSize: 24),
),
value: hour.indexOf(h),
);
}).toList(),
value: hourId,
onChanged: (secilenOncelikId) {
setState(() {
hourId = secilenOncelikId;
});
},
hint: Text("Select Hour"),
),
),
),
);
}
}
Just compute the background color for each item: var backgroundColor = (selected.contains(h)) ? Colors.yellow : Colors.white; and assign it in your existing TextStyle:
child: DropdownButton<int>(
items: hour.map((h) {
var backgroundColor = (selected.contains(h)) ? Colors.yellow : Colors.white;
return DropdownMenuItem<int>(
child: Text(
h,
style: TextStyle(
fontSize: 24,
backgroundColor: backgroundColor,
),
),
value: hour.indexOf(h),
);
}).toList(),
value: hourId,
onChanged: (secilenOncelikId) {
setState(() {
hourId = secilenOncelikId;
});
},
hint: Text("Select Hour"),
),
Results:
you can wrap your child of Drop down Menu Item child (text) by colored container