Related
I am trying to get Course List Object to the custom dropdown menu items but i am encountring an error like that
""There should be exactly one item with [DropdownButton]'s value: Instance of 'Course'.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value""
How can I fix this. Could u please help me?
import 'package:flutter/material.dart';
import 'package:internship_managing_system/model/Course.dart';
import 'package:internship_managing_system/student/widgets/widgets.dart';
import '../../shared/constants.dart';
class DropDownCourses extends StatefulWidget {
List<Course> itemList;
String hintText;
DropDownCourses(this.itemList, this.hintText, {Key? key}) : super(key: key);
#override
_DropDownCoursesState createState() => _DropDownCoursesState();
}
class _DropDownCoursesState extends State<DropDownCourses> {
printList() {
for (int i = 0; i < widget.itemList.length; i++) {
print(widget.itemList[i]);
}
}
Course? dropdownValue;
#override
void initState() {
super.initState();
dropdownValue = Course(id: 1, courseName: "C1");
}
#override
Widget build(BuildContext context) {
List<Course> courseList = <Course>[
Course(id: 1, courseName: "C1"),
Course(id: 2, courseName: "C2"),
Course(id: 3, courseName: "C3")
];
return Container(
margin: const EdgeInsets.all(4),
child: Column(
children: [
Text(
widget.hintText,
style: TEXT_STYLE,
),
Padding(
padding: const EdgeInsets.all(PADDING_VALUE),
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.grey[700],
borderRadius: BorderRadius.circular(5)),
child: DropdownButton<Course>(
/* decoration: const InputDecoration(border: InputBorder.none),
isExpanded: true,
validator: (val) =>
val == null ? 'Lütfen ${widget.hintText} giriniz' : null,*/
value: dropdownValue,
icon: const Icon(
Icons.arrow_downward,
color: ICON_COLOR,
),
iconSize: 24,
elevation: 16,
dropdownColor: Colors.grey[800],
style: TEXT_STYLE,
onChanged: (Course? val) {
setState(() {
dropdownValue = val!;
});
},
items:
courseList.map<DropdownMenuItem<Course>>((Course course) {
return DropdownMenuItem<Course>(
value: course,
child: Center(
//TODO: Liste türünü kontrol et
child: Text(
course.courseName,
style: TEXT_STYLE,
),
),
);
}).toList(),
),
),
)
],
),
);
}
}
Here an example of the solution, added comments for each line to change, you have to pass a String value to the dropdown value property not the full Course class:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DropDownCourses(),
);
}
}
class DropDownCourses extends StatefulWidget {
DropDownCourses({Key? key}) : super(key: key);
#override
_DropDownCoursesState createState() => _DropDownCoursesState();
}
class _DropDownCoursesState extends State<DropDownCourses> {
String? dropdownValue = "C1"; // 1- change this to be only a String type variable
List<Course> courseList = <Course>[
Course(id: 1, courseName: "C1"),
Course(id: 2, courseName: "C2"),
Course(id: 3, courseName: "C3")
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.all(4),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.grey[700],
borderRadius: BorderRadius.circular(5)),
child: DropdownButton<String>( // 2- also here change to only accept String values
value: dropdownValue,
icon: const Icon(
Icons.arrow_downward,
color: Colors.pink,
),
iconSize: 24,
elevation: 16,
dropdownColor: Colors.grey[800],
onChanged: (String? val) { // 3- the value pass should also be String
setState(() {
dropdownValue = val!;
});
},
items:
courseList.map<DropdownMenuItem<String>>((Course course) {
return DropdownMenuItem<String>(
value: course.courseName, // 4- and here pass the courseName since it will be the String to be used in the drop down
child: Center(
child: Text(
course.courseName!,
),
),
);
}).toList(),
),
),
)
],
),
),
);
}
}
class Course {
int? id;
String? courseName;
Course({ this.id, this.courseName });
}
I don't have much experience with flutter.
I would like to use the language_tool library for Dart and Flutter.
I created the script below:
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele';
Future<List<WritingMistake>> tool(String text) async {
var tool = LanguageTool();
var result = tool.check(text);
var correction = await result;
print(correction);
List<WritingMistake> mistakes = [];
for (var m in correction) {
//var mistake = m.issueDescription;
WritingMistake mistake = WritingMistake(
message: m.message,
offset: m.offset,
length: m.length,
issueType: m.issueType,
issueDescription: m.issueDescription,
replacements: m.replacements,
);
mistakes.add(mistake);
}
print(mistakes.length);
print(mistakes);
return mistakes;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child:
Center(child: Text(text, style: TextStyle(fontSize: 20.0))),
),
Text(
'\n Tap on the blue button to replace it in the message.\n',
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading...'),
),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(' ' +
(index + 1).toString() +
' '),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(text.substring(
snapshot.data[index].offset,
snapshot.data[index].offset +
snapshot
.data[index].length)),
),
color: Colors.blue,
),
],
),
Icon(
Icons.arrow_forward,
),
Text(snapshot.data[index].issueDescription)
],
),
// Todo: Row with List of .replacements
],
),
),
// snapshot.data[index].issueDescription),
);
},
),
);
}
},
),
Expanded(child: Container(color: Colors.grey))
],
),
),
);
}
}
And it currently looks like this:
And I would like it to become like in this screen, but I would like the green containers derive from the WritingMistake.replacements list (with each element of the list as text):
Do you know how I can do it?
Spent several hours doing exactly what you wanted. My Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:language_tool/language_tool.dart';
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele';
static List<WritingMistake> mistakes = []; // Moved Here And Init Like Static
Future<List<WritingMistake>> tool(String text) async {
var tool = LanguageTool();
var result = tool.check(text);
var correction = await result;
print(correction);
for (var m in correction) {
//var mistake = m.issueDescription;
WritingMistake mistake = WritingMistake(
message: m.message,
offset: m.offset,
length: m.length,
issueType: m.issueType,
issueDescription: m.issueDescription,
replacements: m.replacements,
);
mistakes.add(mistake);
}
print(mistakes.length);
print(mistakes);
return mistakes;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child: Center(
child: Text(text, style: const TextStyle(fontSize: 20.0))),
),
const Text(
'\n Tap on the blue button to replace it in the message.\n',
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const Center(
child: Text('Loading...'),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int mistakeIdIndex) {
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(' ' +
(mistakeIdIndex + 1).toString() +
' '),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(text.substring(
snapshot.data[mistakeIdIndex]
.offset,
snapshot.data[mistakeIdIndex]
.offset +
snapshot
.data[mistakeIdIndex]
.length)),
),
color: Colors.blue,
),
],
),
const Icon(
Icons.arrow_forward,
),
Text(snapshot
.data[mistakeIdIndex].issueDescription)
],
),
// Todo: Row with List of .replacements
SizedBox(
width: MediaQuery.of(context)
.size
.width, // Width = Screen Width
height: 44,
child: ListView.builder(
itemCount: mistakes.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (BuildContext context,
int replacementsListIndex) {
return buildReplacements(mistakeIdIndex,
replacementsListIndex);
}),
)
],
),
),
// snapshot.data[index].issueDescription),
);
},
),
);
}
},
),
Expanded(child: Container(color: Colors.grey))
],
),
),
);
}
Widget buildReplacements(int mistakeIdIndex, int replacementsListIndex) {
if (mistakes[replacementsListIndex].replacements!.length == null) {
return const SizedBox(); // Return Empty If No Replacements Found, Just To Be Safe
}
// Check For Mistake ID - Remove This Will Cause A Problem with Displaying All Replacements Under All Words
if (mistakeIdIndex == replacementsListIndex) {
// If Only 1 Replacement, No Need To Create ListView.builder
if (mistakes[replacementsListIndex].replacements!.length == 1) {
return Container(
margin: const EdgeInsets.all(4),
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 174, 213, 130)), // Green Color
child: Text(
mistakes[replacementsListIndex].replacements!.toString(),
style: const TextStyle(),
textAlign: TextAlign.center,
),
);
}
// Create ListView.builder to Create A Split Between Replacements To One Wrong-Word (Every Replacement Has It's Own Container With Green Background)
else {
return ListView.builder(
itemCount: mistakes[replacementsListIndex].replacements!.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.all(4),
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 174, 213, 130)), // Green Color
child: Text(
mistakes[replacementsListIndex]
.replacements![index]!
.toString(),
style: const TextStyle(),
textAlign: TextAlign.center,
),
);
});
}
}
// If Replacement Not For This Wrong-Word, Then Skip
else {
return const SizedBox();
}
}
}
And Screenshot:
How do I ensure that a user does not select the same security question twice by hiding the initially selected question from appearing in the second dropdown button and vice versa in flutter?. i am making a request to the same api for the questions.
Updated the question with some code snippets. Thanks
Container(
height: 60,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.black,
width: 1),
borderRadius: BorderRadius.circular(5),
),
child: DropdownButtonHideUnderline(
child: DropdownButton(
hint: Padding(
padding: const EdgeInsets.only(left:
20.0),
child: Text(
"Security Question Two",
style: TextStyle(
color: Colors.black,
fontSize: 16,
letterSpacing: 0.3,
fontWeight: FontWeight.w300),
),
),
itemHeight: 100,
isExpanded: true,
value: dropDownSecurityQuestionTwo,
icon: Padding(
padding: const EdgeInsets.only(right:
10.0),
child:
Icon(Icons.keyboard_arrow_down_outlined),
),
iconEnabledColor: Colors.black,
iconSize: 30,
style: TextStyle(
color: Colors.black,
),
items: questions.map((value) {
return DropdownMenuItem(
value: value['ID'].toString(),
child: Padding(
padding: const EdgeInsets.only(left:
20.0),
child: Text(
value['question'].toString(),
),
),
);
}).toList(),
onChanged: (newValue) async {
setState(() {
dropDownSecurityQuestionTwo =
newValue.toString();
print(dropDownSecurityQuestionTwo);
checkSelectedQuestion();
});
},
),
),
),
void checkSelectedQuestion(){
List newQuestions = [];
for(int i = 0; i<questions.length; i++){
print(questions[i]['ID']);
questions.removeWhere((value) => value['ID'] ==
int.parse(dropDownSecurityQuestionOne!) );
newQuestions.add(questions);}
setState(() {
questions = newQuestions ;
});}
You can add a where filter to the mapping of items to each DropDownButton, depending on the selected value of the other DropDownButton. As a result of setState, the items will be recreated if anything is selected in the other DropDownButton.
Note: This is easy to implement, but not very efficient. Items will be created and filtered every time. It will work perfectly with few items, but if you would like to do something like this with many items, you might need a more efficient approach. For example keep two items lists, and only add / remove what is affected.
Check this code and adopt it to your case:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyPage(),
);
}
}
class MyPage extends StatefulWidget {
const MyPage({Key? key}) : super(key: key);
#override
State<MyPage> createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
String? _selected1;
String? _selected2;
final List<String> _set = ['Alpha', 'Bravo', 'Charlie'];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(children: [
DropdownButton<String>(
value: _selected1,
onChanged: (String? newValue) {
setState(() {
_selected1 = newValue!;
});
},
items: _set
.map((value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.where((e) => _selected2 == null || e.value != _selected2)
.toList()),
DropdownButton<String>(
value: _selected2,
onChanged: (String? newValue) {
setState(() {
_selected2 = newValue!;
});
},
items: _set
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.where((e) => _selected1 == null || e.value != _selected1)
.toList()),
]),
),
),
);
}
}
My question is my
Raisedbutton of the list
Is not changing position ontap
While staying in the list of widgets
Please help me out
And tell me what's wrong in that code
class Sticker extends
StatefulWidget {
Sticker({Key key}) :
super(key: key);
#override
_StickerState
createState() => _
StickerState();
}
class _StickerState extends
State<Sticker> {
Offset position =
Offset(50, 100);
List<Widget> list = [];
#override
Widget build(BuildContext
context) {
return Container(
child: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
),
Positioned(
left: 50,
top: 50,
child:
RaisedButton(
onPressed: () {
setState(
() {
list.add(
Positioned(
left: position.dx,
top: position.dy,
child: RaisedButton(
onPressed: () {
setState(() => position = Offset(50, 150));
},
),
),
);
},
);
},
),
),
...list
],
),
);
}
}
I want that my raised change position after I tap on that while staying in the list
Please help me out dealing this problem console is giving no errors
You can copy paste run full code below
You can use StatefulBuilder
list.add(StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Positioned(
working demo
full code
import 'package:flutter/material.dart';
class Sticker extends StatefulWidget {
Sticker({Key key}) : super(key: key);
#override
_StickerState createState() => _StickerState();
}
class _StickerState extends State<Sticker> {
Offset position = Offset(50, 100);
List<Widget> list = [];
#override
Widget build(BuildContext context) {
print("build list.length ${list.length}");
return Container(
child: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
),
Positioned(
left: 50,
top: 50,
child: RaisedButton(
onPressed: () {
setState(
() {
list.add(StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Positioned(
left: position.dx,
top: position.dy,
child: RaisedButton(
onPressed: () {
setState(() {
position = Offset(50, 150);
});
},
),
);
}));
},
);
},
),
),
...list
],
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
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> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Sticker(),
);
}
}
I think you have to create a position element for each button in the list
List<Offset> position = Offset();
setState(() => position.add(Offset(50,150)));
I have a page with a list and a bar that reaches a detail page.
I would like to add a pop on the detail page to retrieve an item and save it to a todo page but I have a problem with my detail page.
With a Stateless, I have no worries but, if I'm not mistaken, I need a Stateful to add a Future, showDialog .. but, I have problems with my indexes... and there, I'm lost ...
Can someone give me a track or an explanation?
Thank you
home.dart
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
import 'package:test_todo_list/detail.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Liste Items'),
actions: <Widget>[
IconButton(icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch(listWords));
})
],
),
body: ListView.separated(
itemCount: listWords.length,
separatorBuilder: (BuildContext context, int i) =>
Divider(color: Colors.grey),
itemBuilder: (context, i) {
return ListTile(
onTap: () {
Navigator.push(
context,MaterialPageRoute(
builder: (context) => Detail(listWordsDetail: listWords[i]),
),
);
},
title: RichText(
textAlign:TextAlign.left,
text: TextSpan(
children:<TextSpan>[
TextSpan(
text:listWords[i].titlelist,
style:Theme.of(context).textTheme.title.merge(TextStyle(color: Colors.blueGrey)),
),
]
)
),
subtitle: Text(listWords[i].definitionlist,
style: Theme.of(context).textTheme.subtitle.merge(
TextStyle(fontStyle: FontStyle.italic, color: Colors.grey)),
),
trailing: Icon(Icons.arrow_forward_ios, color: Colors.grey),
);
},
),
);
}
}
class DataSearch extends SearchDelegate<String> {
final List<ListWords> listWords;
DataSearch(this.listWords);
#override
List<Widget> buildActions(BuildContext context) {
//Actions for app bar
return [IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
})];
}
#override
Widget buildLeading(BuildContext context) {
//leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
// show some result based on the selection
final suggestionList = listWords;
return ListView.builder(itemBuilder: (context, index) => ListTile(
title: Text(listWords[index].titlelist),
subtitle: Text(listWords[index].definitionlist),
),
itemCount: suggestionList.length,
);
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone searches for something
final suggestionList = query.isEmpty
? listWords
: listWords.where((p) => p.titlelist.contains(RegExp(query, caseSensitive: false))).toList();
return ListView.builder(itemBuilder: (context, index) => ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(listWordsDetail: suggestionList[index]),
),
);
},
trailing: Icon(Icons.remove_red_eye),
title: RichText(
text: TextSpan(
text: suggestionList[index].titlelist.substring(0, query.length),
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestionList[index].titlelist.substring(query.length),
style: TextStyle(color: Colors.grey)),
]),
),
),
itemCount: suggestionList.length,
);
}
}
detail.dart
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
class Detail extends StatefulWidget {
Detail({Key key, #required this.listWordsDetail}) : super(key: key);
final ListWords listWordsDetail;
#override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.dark,
title: const Text('Détails', style: TextStyle(color: Colors.white)),
iconTheme: IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(listWordsDetail.titlelist +' (on detail page)',
style:Theme.of(context).textTheme.title.merge(TextStyle(color: Colors.blueGrey)),
),
Text(listWordsDetail.definitionlist,
style: Theme.of(context).textTheme.subtitle.merge(
TextStyle(fontStyle: FontStyle.italic, color: Colors.grey)),
),
Container(
padding: EdgeInsets.all(40.0),
child: GestureDetector(
onTap: () {
},
child: Icon(Icons.add_shopping_cart),
),
)
],
),
)
);
}
}
DataList.dart
List<ListWords> listWords = [
ListWords('oneWord', 'OneWord definition'),
ListWords('twoWord', 'TwoWord definition.'),
ListWords('TreeWord', 'TreeWord definition'),
];
class ListWords {
String titlelist;
String definitionlist;
ListWords(String titlelist, String definitionlist) {
this.titlelist = titlelist;
this.definitionlist = definitionlist;
}
}
After searching on the web, by chance, I found this solution that I can not explain but it's working...
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
import 'package:test_todo_list/todo_list.dart';
class Detail extends StatefulWidget {
const Detail({Key key, this.listWordsDetail}) : super (key: key);
final ListWords listWordsDetail;
#override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.dark,
title: const Text('Détails', style: TextStyle(color: Colors.white)),
iconTheme: IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(widget.listWordsDetail.titlelist),
Text(widget.listWordsDetail.definitionlist),
Container(
padding: EdgeInsets.all(40.0),
child: GestureDetector(
onTap: () {
//open Dialog addTodoList()
},
child: Icon(Icons.add_shopping_cart),
),
)
],
),
)
);
}
Future<Null> addTodoList() async {
showDialog(context: context);
//... à construire
}
}