How to avoid using FutureBuilder as it is duplicating items in setState - flutter

I believe I am having issues with using setState in a futurebuilder - but Im not sure how to change this? Below you can see I am building a listView using a futureBuilder (http request to api) and connecting it to my ProjectModel model. From here I filter the values I need into List<ProjectSearch> searchList. What I am finding is when I try to implement a search box to filter through the objects I believe the setState is causing the futurebuilder to rebuild the page each time causing duplications. How can I separate the futurebuilder from the listView so that it only displays the one list object as the user types?
class _HomePageState extends State<HomePage> {
TextEditingController controller = TextEditingController();
late final Future<ProjectModel> futureProjects;
List<ProjectSearch> searchList = [];
List<ProjectSearch> finder = [];
var jobNames = [];
var jobNumbers = [];
var techs = [];
var pms = [];
var address = [];
var majors = [];
var budget = [];
#override
void initState() {
super.initState();
futureProjects = fetchProjects();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'Upcoming/Live Projects',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
backgroundColor: ColorConstants.darkScaffoldBackgroundColor,
),
drawer: const CustomDrawer(),
backgroundColor: ColorConstants.lightScaffoldBackgroundColor,
body: Center(
child: FutureBuilder<ProjectModel>(
future: futureProjects,
builder: (context, snapshot) {
// finder.clear();
if (snapshot.hasData) {
var data = snapshot.data!;
var columns = data.columns;
var rows = data.rows;
for (var item in rows!) {
var cells = item.cells;
for (var elements in cells!) {
if (elements.columnId != null) {
if (elements.columnId == 2057691532158852) {
var displayValues = elements.displayValue;
if (displayValues != null) {
jobNames.add(displayValues);
}
if (displayValues == null) {
pms.removeLast();
techs.removeLast();
address.removeLast();
majors.removeLast();
budget.removeLast();
}
}
if (elements.columnId == 697505454286724) {
var projectNumber = elements.displayValue;
if (projectNumber != null) {
jobNumbers.add(projectNumber);
}
}
if (elements.columnId == 7452904895342468) {
var techAssigned = elements.displayValue;
if (techAssigned != null) {
if (techAssigned == 'ts#ag.com.au') {
techAssigned = 'Ts';
techs.add(techAssigned);
} else {
techs.add(techAssigned);
}
}
if (techAssigned == null) {
techAssigned = 'No tech assigned as yet';
techs.add(techAssigned);
}
}
if (elements.columnId == 2949305267971972) {
var pmName = elements.displayValue;
if (pmName != null) {
pms.add(pmName);
}
if (pmName == null) {
pmName = 'No project manager allocated';
pms.add(pmName);
}
}
if (elements.columnId == 5201105081657220) {
var addressValue = elements.displayValue;
if (addressValue != null) {
address.add(addressValue);
}
if (addressValue == null) {
addressValue = '';
address.add(addressValue);
}
}
if (elements.columnId == 52961559766916) {
var majorValue = elements.displayValue;
if (majorValue != null) {
majors.add(majorValue);
}
if (majorValue == null) {
majorValue = 'No';
majors.add(majorValue);
}
}
if (elements.columnId == 4226807856686980) {
var budgetHours = elements.displayValue;
if (budgetHours != null) {
budget.add(budgetHours);
}
if (budgetHours == null) {
budgetHours = 'TBA';
budget.add(budgetHours);
}
}
}
}
}
int index = 0;
for (int i = 0; i < jobNames.length; i++) {
// List<ProjectSearch> innerMap = [];
ProjectSearch myProjects = ProjectSearch(
address: jobNames[index],
budget: budget[index],
jobNumber: jobNumbers[index],
major: majors[index],
name: jobNames[index],
pM: pms[index],
tech: techs[index]);
index++;
searchList.add(myProjects);
}
return Container(
child: Column(
children: <Widget>[
Padding(
padding:
const EdgeInsets.only(left: 20, top: 20, right: 20),
child: TextField(
textAlign: TextAlign.center,
controller: controller,
onChanged: search,
keyboardType: const TextInputType.numberWithOptions(
signed: true),
// keeps going....
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: finder.length,
itemBuilder: (context, index) {
// print(finder.length);
final projectData = finder[index];
return MaterialButton(
onPressed: () => showModalBottomSheet<void>(
backgroundColor: Colors.transparent,
context: context,
builder: (BuildContext context) {
return ClipRRect(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(27.0),
topLeft: Radius.circular(27.0)),
child: Container(
height: 1000,
color: ColorConstants
.secondaryDarkAppColor,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: Container(
height: 400,
margin: const EdgeInsets.only(
top: 20,
left: 20,
right: 20),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment
.spaceAround,
children: [
const Padding(
padding:
EdgeInsets.only(
top: 10.0,
bottom: 5.0)),
const Center(
child: Text(
'Project Details',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight:
FontWeight
.w700),
),
),
Row(
children: [
const Text(
'Project: ',
style: TextStyle(
color: Colors
.white70,
fontWeight:
FontWeight
.w600,
fontSize: 17),
),
const SizedBox(
width: 20),
Flexible(
child: Padding(
padding:
const EdgeInsets
.symmetric(
horizontal:
8.0),
child: Text(
projectData.name,
overflow:
TextOverflow
.ellipsis,
maxLines: 2,
style: const TextStyle(
color: Colors
.white,
fontWeight:
FontWeight
.w600,
fontSize: 17),
),
),
),
],
),
],
),
),
);
},
),
child: Container(
height: 50,
margin: const EdgeInsets.only(
top: 30, left: 20, right: 20),
decoration: const BoxDecoration(
color: ColorConstants
.darkScaffoldBackgroundColor,
borderRadius:
BorderRadius.all(Radius.circular(8)),
),
padding: const EdgeInsets.all(15),
child: Center(
child: Text(
projectData.name,
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 17),
),
),
),
);
}),
),
],
),
);
} else if (snapshot.hasError) {
print(snapshot);
return Text(
'${snapshot.error}',
style: const TextStyle(color: Colors.white),
);
} else {
return const CircularProgressIndicator();
}
}),
),
);
}
void search(String query) {
final suggestions = searchList.where((search) {
final projectName = search.name.toLowerCase();
final input = query.toLowerCase();
return projectName.contains(input);
}).toList();
setState(() {
finder.clear();
finder = suggestions;
});
}
}
Here is what my UI looks like after searching....

Inside your FutureBuilder's builder, try this:
searchList = [];// <---- add this
int index = 0;
for (int i = 0; i < jobNames.length; i++) {
// List<ProjectSearch> innerMap = [];
ProjectSearch myProjects = ProjectSearch(
address: jobNames[index],
budget: budget[index],
jobNumber: jobNumbers[index],
major: majors[index],
name: jobNames[index],
pM: pms[index],
tech: techs[index]);
index++;
searchList.add(myProjects);
}
and also because when every time keyboard status change your FutureBuilder rebuild again do this:
var data = snapshot.data!;
var columns = data.columns;
var rows = data.rows;
jobNames = [];
jobNumbers = [];
techs = [];
pms = [];
address = [];
majors = [];
budget = [];
for (var item in rows!) {
var cells = item.cells;
for (var elements in cells!) {
...
}
}

define the future in the build and use it once like this:
..
Widget build(BuildContext context) {
Future<ProjectModel> futureProjects = fetchProjects() ;
...
Then remove it in the initState() and use it in the future builder like you've done. Refer to this and read more on when to use initSate() and when to use FutureBuilder()
About your Query search: Try removing the setState() in the search method
void search(String query) {
final suggestions = searchList.where((search) {
final projectName = search.name.toLowerCase();
final input = query.toLowerCase();
return projectName.contains(input);
}).toList();
}
}

Related

Try create Dynamic Widget, data from API but when I click on dropdown, radion selection not visible on UI

Try create Dynamic Widget, data from API and add widget in array
&showing in listbuilder but when I click on dropdown, radion selection
not redering. When I click on radio button value print in terminal but
changes not visible same for dropdown and filter chip also.
I want to create form dynamically based on API value like type=TextAREA so create textfield, Type=radioButton so create radio button
class ObservationCreate extends StatefulWidget {
static String tag = '/ObservationCreate';
#override
ObservationCreateState createState() => ObservationCreateState();
}
class ObservationCreateState extends State<ObservationCreate> {
PageController pageController = PageController(initialPage: 0);
int pageNumber = 0;
String token;
String positionSelection;
Animation buttonSqueezeanimation;
AnimationController buttonController;
var radioValue, previouseValue;
var getDatas;
List<EmployeeModel> employee = [];
List<OrganizationModel> organizations = [];
List<CommonModel> common = [];
List<TextEditingController> controllers = [];
List<dynamic> _selectedValues = [];
List<MultiSelectionModel> _multiSelection = [];
List<Widget> buildDotIndicator() {
List<Widget> list = [];
for (int i = 0; i <= 2; i++) {
list.add(i == pageNumber ? indicator(isActive: true) : indicator(
isActive: false));
}
return list;
}
List<Widget> _Widget = new List();
List<Widget> _ObservationDetailsWidget = new List();
List<int> _display = new List();
var masterItems;
bool getMaster = false, observation = false;
SharedPreferences prefs;
int number = 1;
bool selected = false;
#override
void initState() {
retrive();
}
Future<void> getMasterDatas(String controlType, var code) async {
Response response =
await get(getMasterData, headers: headers).timeout(
Duration(seconds: timeOut));
print("masterData: " + response.body);
getDatas = json.decode(response.body);
String error = getDatas["error"];
if (error != Error) {
setState(() {
getMaster = true;
});
var count = getDatas["items"].length;
print(code+count.toString());
if(common.length != 0){
common.removeWhere((element) => element.id == code);
}
for (int i = 0; i < count; i++) {
if (getDatas['items'][i]['masterData']['masterDataObjectId'] == code) {
var masterData = getDatas['items'][i]['masterData'];
var masterDataObject = getDatas['items'][i]['masterDataObject'];
print(i);
CommonModel commonModel = new CommonModel(masterData['value'], masterData['masterDataObjectId'],
masterDataObject['masterDataObjectValue'], masterData['showControlIDs'] == null ? " " : masterData['showControlIDs']);
common.add(commonModel);
}
}
if(getMaster){
print(getMaster);
switch (controlType){
case "RADIOBUTTON":
_Widget.add(radioitem(code));
break;
case "MASTERDROPDOWN":
_Widget.add(masterDropDownBox(code));
break;
case "MULTISELECT":
_ObservationDetailsWidget.add(multiSelections(code));
_getListings(code);
break;
}
}
} else {
print(error);
}
}
Future<void> getObsProperty() async {
var items;
String url = "https://webgateway.demoehswatch.com/api/observations-service/propertysettings/GetListPropertyAsync" +
"?Authorization=bearer" + token + "&MaxResultCount=1000";
final Uri getObsPropertyData = Uri.parse(url);
Response response =
await get(getObsPropertyData, headers: header).timeout(
Duration(seconds: timeOut));
var getData = json.decode(response.body);
String error = getData["error"];
if (error != Error) {
var count = getData["items"].length;
for (int i = 0; i < count; i++) {
if (getData['items'][i]['providerName'] == "Observation" &&
getData['items'][i]['visible'] &&
getData['items'][i]['defaultDisplay'] &&
getData['items'][i]['psDisplaySection'] == "Draft") {
items = getData['items'][i];
print(items["controlType"]+" "+items["name"]);
_display.add(items["displayOrderInView"]);
_display.sort();
}
}
for (int i = 0; i < _display.length; i++) {
for (int j = 0; j < count; j++) {
if (getData['items'][j]['providerName'] == "Observation" &&
getData['items'][j]['visible'] &&
getData['items'][j]['defaultDisplay'] &&
getData['items'][j]['psDisplaySection'] == "Draft") {
var ite = getData['items'][j];
if (_display[i].toString() == ite["displayOrderInView"].toString()) {
switch(ite['controlType']){
case "TEXTBOX":
TextEditingController controller = TextEditingController();
controllers.add(controller);
setState(() {
if (ite['masterDataObjectCode'] == "")
_Widget.add(dynamicText(
ite['name'].toString().split("Observation.")[1],
textColor: textColor));
_Widget.add(dynamicTextbox(50, controller));
});
break;
case "RADIOBUTTON":
print(ite['masterDataObjectCode']);
var codeRadio = ite['masterDataObjectCode'];
getMasterDatas(ite['controlType'], codeRadio);
print(getMaster);
break;
case "MASTERDROPDOWN":
print(ite['masterDataObjectCode']);
var codeDropDown = ite['masterDataObjectCode'];
getMasterDatas(ite['controlType'], codeDropDown);
break;
}
}
}
}
}
} else {
print(error);
}
}
Future<void> getObsPropertyObservationDetails(String objectCode) async {
var items;
String url = "https://webgateway.demoehswatch.com/api/observations-service/propertysettings/GetListPropertyAsync" +
"?Authorization=bearer" + token + "&MaxResultCount=1000";
final Uri getObsPropertyData = Uri.parse(url);
Response response =
await get(getObsPropertyData, headers: header).timeout(
Duration(seconds: timeOut));
var getData = json.decode(response.body);
String error = getData["error"];
if (error != Error) {
var count = getData["items"].length;
for (int i = 0; i < count; i++) {
if (getData['items'][i]['providerName'] == "Observation" &&
getData['items'][i]['visible'] &&
getData['items'][i]['psDisplaySection'] == "Draft" &&
getData['items'][i]['masterDataObjectCode'] == objectCode) {
items = getData['items'][i];
print(items["controlType"]+" "+items["name"]);
setState(() {
observation = true;
number = 2;
getMasterDatas(items["controlType"], getData['items'][i]['masterDataObjectCode']);
});
}
}
} else {
print(error);
}
}
#override
void dispose() {
controllers.clear();
super.dispose();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery
.of(context)
.size;
return Scaffold(
appBar: AppBar(
title: const Text('New Observation'),
backgroundColor: appBar,
),
/*body: Container(
padding: const EdgeInsets.only(left: 20, right: 20),
decoration: BoxDecoration(
color: Color(0xFFF5F5F6),
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(top: 10),
itemCount: _Widget.length,
itemBuilder: (context, index) {
Widget widget = _Widget.elementAt(index);
return widget;
})
)
],
),*/
body: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Container(
height: double.infinity,
color: bg,
child: PageView(
onPageChanged: (index) => setState(() {
pageNumber = index;
}),
controller: pageController,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 16, bottom: 70, right: 16, top: 30),
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.only(top: 10),
itemCount: _Widget.length,
itemBuilder: (context, index) {
Widget widget = _Widget.elementAt(index);
return widget;
})
),
],
),
),
if(observation)
Container(
padding: EdgeInsets.only(left: 16, bottom: 70, right: 16, top: 30),
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.only(top: 10),
itemCount: _ObservationDetailsWidget.length,
itemBuilder: (context, index) {
Widget widget = _ObservationDetailsWidget.elementAt(index);
return widget;
})
)*/
]
)
),
Container(
padding: EdgeInsets.only(left: 16, bottom: 70, right: 16, top: 30),
child: SingleChildScrollView(
padding: EdgeInsets.only(bottom: 60),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
decoration: boxDecoration(
showShadow: true,
bgColor: Colors.white,
radius: 8,
color: border),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset("images/app/icons/upload.png", width: 50,),
SizedBox(height: 10,),
Text(uploadFile, style: TextStyle(fontSize: 15),),
SizedBox(height: 10,),
Container(
decoration: boxDecoration(
showShadow: true,
bgColor: textColor,
radius: 8,
color: border),
child: RaisedButton(
onPressed: () {},
color: textColor,
child: Text(
"Upload Files",
style: TextStyle(color: Colors.white),
),
),
)
],
),
)
],
),
),
),
],
),
),
Container(
margin: EdgeInsets.only(left: 16, right: 16, bottom: 20),
padding: EdgeInsets.only(left: 20, right: 20),
width: size.width,
height: 50,
decoration: BoxDecoration(color: textColor, borderRadius: BorderRadius.circular(15.0)),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.white,
radius: 15,
child: Text('${pageNumber + 1}', style: primaryTextStyle(size: 16, color: textColor)),
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: buildDotIndicator(),
),
pageNumber != number
? FlatButton(
onPressed: () {
pageController.nextPage(duration: Duration(milliseconds: 250), curve: Curves.fastOutSlowIn);
},
child: Text("Next", style: primaryTextStyle(size: 16, color: opBackgroundColor)),
)
: FlatButton(
onPressed: () {
finish(context);
},
child: Text("Submit", style: primaryTextStyle(size: 16, color: opBackgroundColor)),
)
],
),
),
],
),
);
}
retrive() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final String _token = prefs.getString(TOKEN);
setState(() => token = _token);
print(token);
setState(() {
// getMemberList();
getOrganizationDatas();
getObsProperty();
/*getMasterDatas();*/
});
}
Widget masterDropDownBox(var code) {
var radiolist = common.where((element) => element.id == code).toList();
_Widget.add(dynamicText(radiolist[0].masterDataObjectValue, textColor: textColor));
return Container(
margin: const EdgeInsets.only(top:0, left: 0, right: 20),
padding: const EdgeInsets.only(top:0, left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
border: Border.all(
color: headerColor,
width: 2
),
color: Colors.white),
child: Column(
children: <Widget>[
new DropdownButton(
isExpanded: true,
iconEnabledColor: headerColor,
iconDisabledColor: headerColor,
iconSize: 40,
dropdownColor: Colors.white,
hint: new Text("Select Tanent", style: TextStyle(color: headerColor),),
items: radiolist.map((e) {
return new DropdownMenuItem(
child: new Text(e.value.toUpperCase(), style: TextStyle(color: headerColor),),
value: e.value.toString(),);
}).toList(),
onChanged: (newvalue) {
setState(() {
positionSelection = newvalue;
});
},
value: positionSelection,)
],
)
);
}
save(String key, String value) async{
prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
}
retriveMaster(String key) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
final String value = prefs.getString(key);
return value;
}
Widget multiSelect(var code){
var radiolist = common.where((element) => element.id == code).toList();
_Widget.add(dynamicText(radiolist[0].masterDataObjectValue, textColor: textColor));
return Container(
height: 200,
decoration: boxDecoration(
showShadow: false,
bgColor: ehs_white,
radius: 8,
color: border),
child: MultiSelectBottomSheetField(
items: radiolist.map((e) => MultiSelectItem(e.value, e.value)).toList(),
listType: MultiSelectListType.CHIP,
searchable: true,
decoration: boxDecoration(
showShadow: false,
bgColor: ehs_white,
radius: 8,
color: border),
onConfirm: (values) {
setState(() {
_selectedValues = values;
});
},
chipDisplay: MultiSelectChipDisplay(
chipColor: Colors.black,
textStyle: TextStyle(color: Colors.red),
items: _selectedValues.map((e) => MultiSelectItem(e, e.value)).toList(),
onTap: (value) {
setState(() {
_selectedValues.remove(value);
});
},
),
),
);
}
Widget multiSelections(var code) {
return Wrap(
spacing: 8,
direction: Axis.horizontal,
children: filterChipsList(code),
);
}
List<Widget> filterChipsList(var code){
List<Widget> chips = [];
var radiolist = common.where((element) => element.id == code).toList();
_ObservationDetailsWidget.add(dynamicText(radiolist[0].masterDataObjectValue, textColor: textColor));
for(int i = 0; i < radiolist.length; i++){
MultiSelectionModel multiSelectionModel = new MultiSelectionModel(radiolist[i].value, radiolist[i].id, radiolist[i].masterDataObjectValue, radiolist[i].controlIds, false);
_multiSelection.add(multiSelectionModel);
}
for (int i = 0; i < _multiSelection.length; i++) {
Widget item = Padding(
padding: const EdgeInsets.only(left: 10, right: 5),
child: FilterChip(
label: Text(_multiSelection[i].value),
labelStyle: const TextStyle(color: Colors.white,fontSize: 16),
backgroundColor: Colors.grey,
selected: _multiSelection[i].isSelected,
onSelected: (bool value) {
setState(() {
print(value);
_multiSelection[i].isSelected = value;
});
},
),
);
chips.add(item);
}
return chips;
}
} ```

Another exception was thrown: type 'Null' is not a subtype of type 'String'

getting this error showing in red screen I update my packages
_TypeError Another exception was thrown: type 'Null' is not a subtype of type 'String' I tried to update the sdk and I'm not understanding where the problem is in this code. I added CircularProgressIndicator with condition statements
The relevant error-causing widget was:
quizpage
quizpage:file:///C:/Users/flutt/Downloads/quiz/flutter-quizstar-master/lib/quizpage.dart:57:18
class getjson extends StatefulWidget {
String langname;
getjson(this.langname);
#override
State<getjson> createState() => _getjsonState();
}
class _getjsonState extends State<getjson> {
late String assettoload;
// a function
setasset() {
if (widget.langname == "Science") {
assettoload = "assets/Science.json";
} else if (widget.langname == "Maths") {
assettoload = "assets/Maths.json";
} else if (widget.langname == "History") {
assettoload = "assets/History.json";
}
}
#override
Widget build(BuildContext context) {
setasset();
// and now we return the FutureBuilder to load and decode JSON
return FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString(assettoload, cache: false),
builder: (context, snapshot) {
if (snapshot.hasData) {
List mydata = json.decode(snapshot.data.toString());
if (mydata == null) {
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
} else {
return quizpage(mydata: mydata);
}}
return CircularProgressIndicator();
},
);
}
}
class quizpage extends StatefulWidget {
final List mydata;
quizpage({required this.mydata});
#override
_quizpageState createState() => _quizpageState(mydata);
}
class _quizpageState extends State<quizpage> {
final List mydata;
_quizpageState(this.mydata);
Color colortoshow = Colors.indigoAccent;
Color right = Colors.green;
Color wrong = Colors.red;
int marks = 0;
int i = 1;
bool disableAnswer = false;
int j = 1;
int timer = 30;
String showtimer = "30";
var random_array;
Map<String, Color> btncolor = {
"a": Colors.indigoAccent,
"b": Colors.indigoAccent,
"c": Colors.indigoAccent,
"d": Colors.indigoAccent,
};
bool canceltimer = false;
genrandomarray(){
var distinctIds = [];
var rand = new Random();
for (int i = 0;; ) {
distinctIds.add(rand.nextInt(10));
random_array = distinctIds.toSet().toList();
if(random_array.length < 10){
continue;
}else{
break;
}
}
print(random_array);
}
#override
void initState() {
starttimer();
genrandomarray();
super.initState();
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t) {
setState(() {
if (timer < 1) {
t.cancel();
nextquestion();
} else if (canceltimer == true) {
t.cancel();
} else {
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void nextquestion() {
canceltimer = false;
timer = 30;
setState(() {
if (j < 10) {
i = random_array[j];
j++;
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(marks: marks),
));
}
btncolor["a"] = Colors.indigoAccent;
btncolor["b"] = Colors.indigoAccent;
btncolor["c"] = Colors.indigoAccent;
btncolor["d"] = Colors.indigoAccent;
disableAnswer = false;
});
starttimer();
}
void checkanswer(String k) {
// in the previous version this was
// mydata[2]["1"] == mydata[1]["1"][k]
// which i forgot to change
// so nake sure that this is now corrected
if (mydata[2][i.toString()] == mydata[1][i.toString()][k]) {
// just a print sattement to check the correct working
// debugPrint(mydata[2][i.toString()] + " is equal to " + mydata[1][i.toString()][k]);
marks = marks + 5;
// changing the color variable to be green
colortoshow = right;
} else {
// just a print sattement to check the correct working
// debugPrint(mydata[2]["1"] + " is equal to " + mydata[1]["1"][k]);
colortoshow = wrong;
}
setState(() {
btncolor[k] = colortoshow;
canceltimer = true;
disableAnswer = true;
});
// nextquestion();
// changed timer duration to 1 second
Timer(Duration(seconds: 2), nextquestion);
}
Widget choicebutton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: MaterialButton(
onPressed: () => checkanswer(k),
child: Text(
mydata[1][i.toString()][k],
style: TextStyle(
color: Colors.white,
fontFamily: "Alike",
fontSize: 16.0,
),
maxLines: 1,
),
color: btncolor[k],
splashColor: Colors.indigo[700],
highlightColor: Colors.indigo[700],
minWidth: 200.0,
height: 45.0,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () async{
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Welcome",
),
content: Text("You Can't Go Back At This Stage."),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Ok',
),
)
],
));
},
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
mydata[0][i.toString()] ,
style: TextStyle(
fontSize: 16.0,
fontFamily: "Quando",
),
),
),
),
Expanded(
flex: 6,
child: AbsorbPointer(
absorbing: disableAnswer,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choicebutton('a'),
choicebutton('b'),
choicebutton('c'),
choicebutton('d'),
],
),
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 35.0,
fontWeight: FontWeight.w700,
fontFamily: 'Times New Roman',
),
),
),
),
),
],
),
),
);
}
}
In your code some place your are show some variable in Text widget that might be null so change them to these:
Text(
mydata[1][i.toString()][k] ?? "",//<--- add this
style: TextStyle(
color: Colors.white,
fontFamily: "Alike",
fontSize: 16.0,
),
maxLines: 1,
)
and
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
mydata[0][i.toString()] ?? "",//<--- add this
style: TextStyle(
fontSize: 16.0,
fontFamily: "Quando",
),
),
),
),
Can you check if your expression is evaluating to null in Text() Widget,
just put some constant strings in text widgets and try to run.
if expression is evaluating to null, use ?? operation to provide default string value to Text Widget.

Display searched Item base on user input

I'm trying to display a result item following the user input in the text field, but I receive all the items. There were some methods I tried, but they didn't work and I encountered some errors.
here is my source code
import 'dart:convert';
import 'package:ebook_flutter_app/constant.dart';
import 'package:ebook_flutter_app/model/image.dart';
import 'package:ebook_flutter_app/model/text_value.dart';
import 'package:ebook_flutter_app/screens/show_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';
import '../widgets/showImage.dart';
class SearchScreen extends StatefulWidget {
const SearchScreen({Key? key}) : super(key: key);
#override
SearchScreenState createState() => SearchScreenState();
}
class SearchScreenState extends State<SearchScreen> {
List textValues = [];
List original = [];
List result = [];
TextEditingController txtQuery = TextEditingController();
List<TextValue> textValueList = [];
List<MyImage> myImageList = [];
List<TextValue> getCatList(List<TextValue> inputList, String query) {
List<TextValue> outputList =
inputList.where((item) => item.title == query).toList();
//textValueList = outputList;
//var myList = outputList;
return outputList;
}
List<MyImage> getImageList(List<MyImage> inputList, String query) {
List<MyImage> outputList =
inputList.where((o) => o.id_num!.toString() == query).toList();
// myImageList = outputList;
return outputList;
}
#override
void initState() {
super.initState();
txtQuery.addListener(() {
if (isNumeric(txtQuery.text) == true) {
loadImage();
searchById(txtQuery.text);
print('I\'m using search option for loading Image.... ');
} else {
loadData();
search(txtQuery.text);
print('I\'m using search option for loading Data....');
}
});
}
void loadData() async {
String jsonStr = await rootBundle.loadString('assets/db/text_value.json');
var json = jsonDecode(jsonStr);
textValues = json;
original = json;
setState(() {});
}
void loadImage() async {
String jsonStr = await rootBundle.loadString('assets/db/image_db.json');
var json = jsonDecode(jsonStr);
textValues = json;
original = json;
print('load Image is running....');
setState(() {});
}
void search(String query) {
if (query.isEmpty) {
textValues = original;
setState(() {});
return;
}
query = query.toLowerCase();
print(query);
//List result = [];
textValues.forEach((element) {
var name = element["name"].toString().toLowerCase();
var description = element["description"].toString().toLowerCase();
if (name.contains(query) || description.contains(query)) {
result.add(element);
// textValueList.add(element);
// print('textValueList is $textValueList');
}
});
textValues = result;
setState(() {});
}
void searchById(String query1) {
if (query1.isEmpty) {
textValues = original;
print('query1 is .....$query1');
setState(() {});
return;
}
print('query1 is $query1');
//List result = [];
textValues.forEach((element) {
var id_num = element["id_num"].toString();
var img_num = element["img_num"].toString();
if (id_num.contains(query1)) {
result.add(element);
// myImageList.add(element);
// print('mYImageList is $myImageList');
print('result is......$result');
}
});
textValues = result;
print('textValues is .....$textValues');
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(2),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: txtQuery,
onChanged: (value) {
setState(() {});
},
textDirection: TextDirection.rtl,
decoration: InputDecoration(
hintText: "جست وجو...",
hintTextDirection: TextDirection.rtl,
hintStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontFamily: 'iran-sans-ds',
decoration: TextDecoration.none,
fontStyle: FontStyle.italic,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0)),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black)),
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
txtQuery.text = '';
txtQuery.clear();
},
),
),
keyboardType: TextInputType.text,
),
],
),
),
txtQuery.text.isEmpty
? Container()
: Expanded(
child: ListView.builder(
itemCount: textValues.length,
// isNumeric(txtQuery.text) == true
// ? getImageList(myImageList, txtQuery.text).length
// : getCatList(textValueList, txtQuery.text).length,
itemBuilder: (context, index) {
var textVal = textValues[index];
String description = textVal['description'] ??
'we don\'t have description......';
var id_num = textVal['id_num'].toString() ??
'we don\'t have id_num......';
var img_num = textVal['img_num'].toString() ??
'we don\'t have img_num........... ';
print('id_num is ....$id_num'
' img_num is.....$img_num');
return Card(
margin:
const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
color: Colors.blue[50],
child: Theme(
data: Theme.of(context)
.copyWith(dividerColor: Colors.transparent),
child: InkWell(
onTap: (() => pushNewScreen(
context,
screen: isNumeric(id_num) == false
? ShowItem(
name: textVal['name'],
description:
textVal['description'],
)
: ShowImage(
title: id_num,
image: Myasset(img_num),
),
withNavBar:
true, // OPTIONAL VALUE. True by default.
pageTransitionAnimation:
PageTransitionAnimation.slideRight,
)),
child: ExpansionTile(
title: Text(
isNumeric(id_num) == false
? textVal['name']
: id_num,
textDirection: TextDirection.rtl,
style: const TextStyle(
fontSize: 20.0, color: Colors.black54),
),
childrenPadding: const EdgeInsets.only(
bottom: 20.0,
right: 20.0,
left: 20.0,
top: 5.0),
children: [
isNumeric(id_num) == false
? Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: [
const Text(
'بیشتر',
textDirection:
TextDirection.rtl,
textAlign: TextAlign.justify,
style: TextStyle(
color: Colors.blue,
fontWeight:
FontWeight.bold),
),
Text(
'${description.substring(0, 39)} ...',
textDirection:
TextDirection.rtl,
textAlign: TextAlign.justify,
style: TextStyle(
color: Colors.black),
),
])
: Image.asset(
Myasset(img_num),
fit: BoxFit.cover,
width: MediaQuery.of(context)
.size
.width *
0.01,
height: MediaQuery.of(context)
.size
.height *
0.01,
),
],
),
),
),
);
}),
)
]),
);
}
}
Widget _listView(text_value) {
return Expanded(
child: ListView.builder(
itemCount: text_value.length,
itemBuilder: (context, index) {
var textVal = text_value[index];
String description =
textVal['description'] ?? 'we don\'t have description......';
var id_num =
textVal['id_num'].toString() ?? 'we don\'t have id_num......';
var img_num = textVal['img_num'].toString() ??
'we don\'t have img_num........... ';
print('id_num is ....$id_num' ' img_num is.....$img_num');
return Card(
margin: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
color: Colors.blue[50],
child: Theme(
data:
Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: InkWell(
onTap: (() => pushNewScreen(
context,
screen: isNumeric(id_num) == false
? ShowItem(
name: textVal['name'],
description: textVal['description'],
)
: ShowImage(
title: id_num,
image: Myasset(img_num),
),
withNavBar: true, // OPTIONAL VALUE. True by default.
pageTransitionAnimation:
PageTransitionAnimation.slideRight,
)),
child: ExpansionTile(
title: Text(
isNumeric(id_num) == false ? textVal['name'] : id_num,
textDirection: TextDirection.rtl,
style:
const TextStyle(fontSize: 20.0, color: Colors.black54),
),
childrenPadding: const EdgeInsets.only(
bottom: 20.0, right: 20.0, left: 20.0, top: 5.0),
children: [
isNumeric(id_num) == false
? Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
const Text(
'بیشتر',
textDirection: TextDirection.rtl,
textAlign: TextAlign.justify,
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold),
),
Text(
'${description.substring(0, 39)} ...',
textDirection: TextDirection.rtl,
textAlign: TextAlign.justify,
style: TextStyle(color: Colors.black),
),
])
: Image.asset(
Myasset(img_num),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width * 0.01,
height: MediaQuery.of(context).size.height * 0.01,
),
],
),
),
),
);
}),
);
}
I didn't use getCatList & myImageListmethods because I encountered to error when I was using this methods.
How can I fix it?
Inside addListener you're calling loadData() every single time the user enter a character. Try this:
void initState() {
super.initState();
loadData();
txtQuery.addListener(() {
search(txtQuery.text);
});
}
The second thing you could try is use for in instead of forEach
void search(String query) {
if (query.isEmpty) {
textValues = [];
setState(() {});
return;
}
setState(() {
textValues = [
for (var item in yourDataSource)
if (item['key'].contains(query)) item
];
});
}
And you can use textValues in your list
body: ListView.builder(
itemCount: textValues.length,
You can use autocomplete textfield for your problem
check this plugin :
https://pub.dev/packages/auto_complete_search
You don't have any function for onChanged (TextFormField's argument), let's try this:
First edit your search() function
void search(String query) {
if (query.isEmpty) {
setState(() {
textValues = original;
});
return;
}
setState(() {
textValues = original.where( (element) =>
element['name'].contains(query.toLowerCase()).toString().toLowerCase() ||
element['description'].contains(query.toLowerCase()).toString().toLowerCase()
).toList();
});
}
Second edit onChanged argument
onChanged: (value) => search(value)

changing slider value as List item value in flutter New version

Yesterday i have ask question about this topic ,yesterday it was test project to understand the issue ,today i tried to apply what i learned on my app ,but i get small error i can't fix it.
I have this class file (viewdegree.dart):
class Digree {
final int index;
final String title_k;
final String title_a;
final String aya;
final String link;
final String activity_k;
final String activity_a;
String act_id;
String mydigree;
Digree(this.index, this.title_k, this.title_a, this.aya, this.link,
this.activity_k, this.activity_a, this.act_id, this.mydigree);
}
I have this page which import above class ,the page send request to API to display some rows ,in each row i have slider to detect the degree for each item data.
when i change the slider value it send post request to server to add degree to the row or update it ,the i want to setstate the value of Slider to new degree.
the page code :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:jiyanUquraan/classes/viewdigree.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class DisplayList extends StatefulWidget {
#override
_DisplayListState createState() => _DisplayListState();
}
TextEditingController insertedDegree = TextEditingController();
var video_link = '';
class _DisplayListState extends State<DisplayList> {
#override
Widget build(BuildContext context) {
List digrees = [];
var widthView = MediaQuery.of(context).size.width;
Map rdata = ModalRoute.of(context).settings.arguments;
var did = int.parse(rdata['dayId'].toString());
var u_id = rdata['userID'];
var m_id = rdata['courseId'];
int w_id;
if (did <= 6) {
w_id = 1;
} else if (did <= 12) {
w_id = 2;
} else if (did <= 18) {
w_id = 3;
} else {
w_id = 4;
}
Future<List> fetchDigrees() async {
var url =
'http://10.0.2.2/jiyan/test/api/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
// Insert Func
send_degree(uId, actId, degree, w_id, did, m_id) async {
var sendData = {
'u_id': uId.toString(),
'act_id': actId.toString(),
'degree': degree.toString(),
'm_id': m_id.toString(),
'd_id': did.toString(),
'w_id': w_id.toString()
};
var url = 'http://10.0.2.2/jiyan/test/api/data/changedata.php';
var response = await http.post(url, body: sendData);
var data = jsonDecode(response.body);
if (data.status) {
print('OK');
}
}
// End of Insert Func
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
Map rdata = ModalRoute.of(context).settings.arguments;
var lang = rdata['lang'];
if (snapshot.data == null) {
return Center(
child: Text("Loading"),
);
} else {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data[0].link,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: false,
));
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
padding: EdgeInsets.fromLTRB(25, 20, 25, 20),
shrinkWrap: true,
children: <Widget>[
Text(
lang == 'k'
? snapshot.data[0].title_k
: snapshot.data[0].title_a,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 32, color: Colors.white)),
//for top margin
SizedBox(height: 20.0),
// dexription
Container(
padding: const EdgeInsets.all(15),
width: widthView,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: const Color.fromRGBO(180, 80, 80, 0.3)),
child: Text(snapshot.data[0].aya,
textAlign: TextAlign.justify,
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 26, color: Colors.greenAccent[100])),
),
// now populating your ListView for `Directionality`
Column(
children: <Widget>[
// Start activities
Column(
children: snapshot.data.map<Widget>((item) {
double _value;
var xx = double.parse(item.mydigree);
if (xx > 0) {
_value = double.parse(item.mydigree);
} else {
_value = 0.0;
}
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 2, color: Colors.white),
color: Color.fromRGBO(230, 200, 200, 0.2)),
width: widthView,
padding: EdgeInsets.all(25),
margin: EdgeInsets.fromLTRB(0, 25, 0, 25),
child: Column(
children: <Widget>[
Text(
lang == 'k'
? item.activity_k
: item.activity_a,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 28, color: Colors.white),
),
SizedBox(
height: 15,
),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.yellow[200]
.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 20,
)
],
borderRadius:
BorderRadius.circular(15),
color:
Color.fromRGBO(0, 0, 0, 0.4)),
width: widthView,
padding: EdgeInsets.all(10),
child: Slider(
max: 100,
min: 0,
divisions: 20,
value: _value,
label: _value.round().toString(),
onChanged: (val) {
send_degree(u_id, item.act_id, val,
w_id, did, m_id);
setState(() {
_value = val;
item.mydigree = val.toString();
});
},
))
],
),
)
],
),
);
}).toList()),
// End activities
SizedBox(
height: 20,
),
Text('خەلەکا ئەڤرو',
textAlign: TextAlign.right,
style: TextStyle(fontSize: 26, color: Colors.yellow)),
SizedBox(
height: 20,
),
YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
progressIndicatorColor: Colors.blueAccent,
),
],
),
],
),
);
}
});
}
}
When i change the slider value it is come back to zero and degree with zero value inserted on server as show on video.
https://streamable.com/0ejpel
How can i fixed it.
Best Regards
because your variable is set value in build method, every time you call setState, your variable is set again and slider show default value again.
for solve this problem, you should set your variable out of the build method.
EDIT:
change your code like this:
List digrees = [];
var widthView;
Map rdata;
var did;
var u_id;
var m_id;
var w_id;
#override
void initState() {
super.initState();
widthView = MediaQuery.of(context).size.width;
rdata = ModalRoute.of(context).settings.arguments;
did = int.parse(rdata['dayId'].toString());
u_id = rdata['userID'];
m_id = rdata['courseId'];
w_id;
if (did <= 6) {
w_id = 1;
} else if (did <= 12) {
w_id = 2;
} else if (did <= 18) {
w_id = 3;
} else {
w_id = 4;
}
}
Future<List> fetchDigrees() async {
...
}
Future<void> send_degree(uId, actId, degree, w_id, did, m_id) async {
...
}
Widget build(BuildContext context) {
// put your future builder here
}
and in slider onChange method:
send_degree(u_id, item.act_id, val,
w_id, did, m_id).then((_){
setState(() {
_value = val;
});
});
this is not the ideal solution and best code. but you can change it to be better.

How display a list of data order by date?

Here is the result now :
It is much better but i Don't know why BELSHINA BOBRUISK is not centered vertically. As you can see the others team are centered vertically. FC SMOELVITCHI is centered. Strange. Too i would like display the "2020-06-01" in mobile format so if it is french mobile it will be "01-06-2020".
And another question i Don't know why my mobile app use the theme with fontfamily but not all. I have some pages with a part of data in good family font and the other part in default font, its is really strange
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'package:flutter_app/menu_member.dart';
import 'package:flutter_app/globals.dart' as globals;
import 'package:flutter_app/appbar_draw.dart';
// Create a Form widget.
class Affiche_Matchs extends StatefulWidget {
#override
_Affiche_Matchs_State createState() {
return _Affiche_Matchs_State();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class _Affiche_Matchs_State extends State<Affiche_Matchs> {
#override
final _formKey = GlobalKey<FormState>();
List<String> radioValues = [];
Future<List<Match>> grid;
Future <List<Match>> Liste_Match_Display() async {
// SERVER LOGIN API URL
var url = 'https://www.easytrafic.fr/game_app/display_matchs.php';
// Starting Web API Call.
var response = await http.get(url,headers: {'content-type': 'application/json','accept': 'application/json','authorization': globals.token});
// Getting Server response into variable.
var jsondata = json.decode(response.body);
List<Match> Matchs = [];
var i=0;
for (var u in jsondata) {
i=i+1;
Match match = Match(u["id"],u["equipe1"],u["equipe2"],u["type_prono"],u["date_debut"],u["heure_debut"]);
Matchs.add(match);
radioValues.add("");
}
return Matchs;
}
void initState() {
grid = Liste_Match_Display();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: drawappbar(true),
drawer: new DrawerOnly(className: Affiche_Matchs()),
body:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child:
FutureBuilder(
future: grid,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Center(child: new CircularProgressIndicator(),);
default:
if(snapshot.hasError) {
return new Center(child: new Text('Error: ${snapshot.error}'),);
}
else {
List<Match> values = snapshot.data;
Match lastitem;
lastitem=values[0];
if (values.isEmpty) {
return Container(
child: Center(
child: Text("Aucun match disponible !!!")
)
);
}
else {
return Form(
key: _formKey,
child: ListView.builder(itemCount: values.length,itemBuilder: (_,index) {
bool header = lastitem.date_debut !=
values[index].date_debut;
lastitem = values[index];
return Column(
children: [
(header || index == 0)
?
Container(
height: 30,
margin: EdgeInsets.only(top:10),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue[700],
width: 2,
),
color: Colors.blue[700]
),
child : new Text(values[index].date_debut,textAlign: TextAlign.center,style: TextStyle(fontSize: 18.0,fontWeight: FontWeight.w500,color: Colors.white),),
)// here display header
:
Container(),
Container(
margin: EdgeInsets.only(top:20,bottom:20),
child: Center(
child: Text(values[index].heure_debut),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(values[index].equipe1,style: TextStyle(fontSize:12)),
draw_grid("1", index, values[index].typeprono),
draw_grid("N", index, values[index].typeprono), //
draw_grid("2", index, values[index].typeprono), //
Text(values[index].equipe2,style: TextStyle(fontSize:12)),
]
),
]
);
}
)
);
}
};
};
}
),
),
);
}
draw_grid (String choix, int index,String type_prono) {
if (type_prono.contains(choix)) {
return new InkWell(
onTap: () {
setState(() {
if (radioValues[index] == choix) {
radioValues[index] = "";
}
else {
radioValues[index] = choix;
}
});
print(radioValues);
},
child:
Container(
height: 30.0,
width: 30.0,
margin: EdgeInsets.only(right: 2,left: 2),
child: new Center(
child: new Text(choix,
style: new TextStyle(
color:
radioValues[index] == choix ? Colors.white : Colors.red,
//fontWeight: FontWeight.bold,
fontSize: 18.0, fontWeight: FontWeight.w900)),
),
decoration: new BoxDecoration(
color: radioValues[index] == choix
? Colors.red
: Colors.white,
border: new Border.all(
width: 2.0,
color: radioValues[index] == choix
? Colors.red
: Colors.red),
borderRadius: const BorderRadius.all(const Radius.circular(5)),
),
),
);
}
else {
return Text("");
}
}
}
class Match {
final String id;
final String equipe1;
final String equipe2;
final String typeprono;
final String date_debut;
final String heure_debut;
const Match(this.id,this.equipe1, this.equipe2, this.typeprono,this.date_debut,this.heure_debut);
}
You have to sort you list base on date and then you can display by checking you have to display header or not.
Following code help you to understand more and then you can implement.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
class DeleteWidget extends StatefulWidget {
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
final _formKey = GlobalKey<FormState>();
List<String> radioValues = [];
Future<List<Match>> grid;
Future<List<Match>> Liste_Match_Display() async {
// SERVER LOGIN API URL
var url = 'https://www.easytrafic.fr/game_app/display_matchs.php';
// Starting Web API Call.
var response = await http.get(url, headers: {
'content-type': 'application/json',
'accept': 'application/json',
'authorization':
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOjE1ODg5NTQ0NDgsImlhdCI6MTU4ODk1NDQ0OCwiZXhwIjoxNTg5MDE0NDQ4LCJkYXRhIjp7ImlkIjoiMSIsImVtYWlsIjoicGFzMzBAbmV0Y291cnJpZXIuY29tIn19.-jcyoxtkNVWWagune6EOjInjBgObyxf9gweXJrA2MxLL5fRTW1pkFSFrJOW8uYzhVpaZ4CF9A-c_m8akUq74NA '
});
// Getting Server response into variable.
var jsondata = json.decode(response.body);
List<Match> Matchs = [];
var i = 0;
for (var u in jsondata) {
i = i + 1;
Match match = Match(u["id"], u["equipe1"], u["equipe2"], u["type_prono"],
u["date_debut"], u["heure_debut"]);
Matchs.add(match);
radioValues.add("");
}
return Matchs;
}
void initState() {
grid = Liste_Match_Display();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: drawappbar(true),
//drawer: new DrawerOnly(className: Affiche_Matchs()),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: FutureBuilder(
future: grid,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Center(
child: new CircularProgressIndicator(),
);
default:
if (snapshot.hasError) {
return new Center(
child: new Text('Error: ${snapshot.error}'),
);
} else {
List<Match> values = snapshot.data;
Match lastitem;
lastitem = values[0];
if (values.isEmpty) {
return Container(
child: Center(
child: Text("Aucun match disponible !!!")));
} else {
return Form(
key: _formKey,
child: ListView.builder(
itemCount: values.length,
itemBuilder: (_, index) {
bool header = lastitem.date_debut !=
values[index].date_debut;
lastitem = values[index];
return Column(
children: [
(header || index == 0)
? Container(
height: 30,
margin: EdgeInsets.only(top: 10),
width: MediaQuery.of(context)
.size
.width,
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue[700],
width: 2,
),
color: Colors.blue[700]),
child: new Text(
values[index].date_debut,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Colors.white),
),
) // here display header
: Container(),
Text(values[index].heure_debut),
Text(values[index].equipe1),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
draw_grid("1", index,
values[index].typeprono),
draw_grid("N", index,
values[index].typeprono), //
draw_grid("2", index,
values[index].typeprono), //
],
),
Text(values[index].equipe2),
// here display whole item
],
);
}));
}
}
;
}
;
}),
),
);
}
draw_grid(String choix, int index, String type_prono) {
if (type_prono.contains(choix)) {
return new InkWell(
onTap: () {
setState(() {
if (radioValues[index] == choix) {
radioValues[index] = "";
} else {
radioValues[index] = choix;
}
});
print(radioValues);
},
child: Container(
height: 40.0,
width: 40.0,
child: new Center(
child: new Text(choix,
style: new TextStyle(
color:
radioValues[index] == choix ? Colors.white : Colors.red,
//fontWeight: FontWeight.bold,
fontSize: 18.0,
fontWeight: FontWeight.w900)),
),
decoration: new BoxDecoration(
color: radioValues[index] == choix ? Colors.red : Colors.white,
border: new Border.all(
width: 2.0,
color: radioValues[index] == choix ? Colors.red : Colors.red),
borderRadius: const BorderRadius.all(const Radius.circular(5)),
),
),
);
} else {
return Text("");
}
}
}
class Match {
final String id;
final String equipe1;
final String equipe2;
final String typeprono;
final String date_debut;
final String heure_debut;
const Match(this.id, this.equipe1, this.equipe2, this.typeprono,
this.date_debut, this.heure_debut);
}