changing slider value as List item value in flutter New version - flutter

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.

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;
}
} ```

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

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();
}
}

how to solve "The method 'call' was called on null. Receiver: null Tried calling: call()" error on flutter?

i am trying to integrate stripe payment method in flutter. i am following the tutorial from https://www.youtube.com/watch?v=VOtmM9i25R4.
i got error that says The method 'call' was called on null.
Receiver: null
Tried calling: call()
this is the code where the error is
import 'package:flutter/material.dart';
import 'package:flutter_credit_card/credit_card_widget.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:izzilly_customer/API_service/payment_service/stripe-
payment-service.dart';
import 'package:stripe_payment/stripe_payment.dart';
class ExistingCardsPage extends StatefulWidget {
static const String id = 'existing-card';
ExistingCardsPage({Key key}) : super(key: key);
#override
ExistingCardsPageState createState() => ExistingCardsPageState();
}
class ExistingCardsPageState extends State<ExistingCardsPage> {
List cards = [{
'cardNumber': '4242424242424242',
'expiryDate': '04/24',
'cardHolderName': 'Muhammad Ahsan Ayaz',
'cvvCode': '424',
'showBackView': false,
}, {
'cardNumber': '5555555566554444',
'expiryDate': '04/23',
'cardHolderName': 'Tracer',
'cvvCode': '123',
'showBackView': false,
}];
payViaExistingCard(BuildContext context, card) async {
await EasyLoading.show(status: 'Please wait....' );
var expiryArr = card['expiryDate'].split('/');
CreditCard stripeCard = CreditCard(
number: card['cardNumber'],
expMonth: int.parse(expiryArr[0]),
expYear: int.parse(expiryArr[1]),
);
var response = await StripeService.payViaExistingCard(
amount: '2500',
currency: 'USD',
card: stripeCard
);
await EasyLoading.dismiss();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(response.message),
duration: new Duration(milliseconds: 1200),
)
).closed.then((_) {
Navigator.pop(context);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Choose existing card'),
),
body: Container(
padding: EdgeInsets.all(20),
child: ListView.builder(
itemCount: cards.length,
itemBuilder: (BuildContext context, int index) {
var card = cards[index];
return InkWell(
onTap: () {
payViaExistingCard(context, card);
},
child: CreditCardWidget(
cardNumber: card['cardNumber'],
expiryDate: card['expiryDate'],
cardHolderName: card['cardHolderName'],
cvvCode: card['cvvCode'],
showBackView: false,
)
);
}
},
),
),
);
}
}
and this is the error
this is the code for CreditCardWidget
const Map<CardType, String> CardTypeIconAsset = <CardType, String>{
CardType.visa: 'icons/visa.png',
CardType.americanExpress: 'icons/amex.png',
CardType.mastercard: 'icons/mastercard.png',
CardType.discover: 'icons/discover.png',
};
class CreditCardWidget extends StatefulWidget {
const CreditCardWidget(
{Key? key,
required this.cardNumber,
required this.expiryDate,
required this.cardHolderName,
required this.cvvCode,
required this.showBackView,
this.animationDuration = const Duration(milliseconds: 500),
this.height,
this.width,
this.textStyle,
this.cardBgColor = const Color(0xff1b447b),
this.obscureCardNumber = true,
this.obscureCardCvv = true,
this.labelCardHolder = 'CARD HOLDER',
this.labelExpiredDate = 'MM/YY',
this.cardType,
this.isHolderNameVisible = false,
this.backgroundImage,
this.glassmorphismConfig,
this.isChipVisible = true,
this.isSwipeGestureEnabled = true,
this.customCardTypeIcons = const <CustomCardTypeIcon>[],
required this.onCreditCardWidgetChange})
: super(key: key);
final String cardNumber;
final String expiryDate;
final String cardHolderName;
final String cvvCode;
final TextStyle? textStyle;
final Color cardBgColor;
final bool showBackView;
final Duration animationDuration;
final double? height;
final double? width;
final bool obscureCardNumber;
final bool obscureCardCvv;
final void Function(CreditCardBrand) onCreditCardWidgetChange;
final bool isHolderNameVisible;
final String? backgroundImage;
final bool isChipVisible;
final Glassmorphism? glassmorphismConfig;
final bool isSwipeGestureEnabled;
final String labelCardHolder;
final String labelExpiredDate;
final CardType? cardType;
final List<CustomCardTypeIcon> customCardTypeIcons;
#override
_CreditCardWidgetState createState() => _CreditCardWidgetState();
}
class _CreditCardWidgetState extends State<CreditCardWidget>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> _frontRotation;
late Animation<double> _backRotation;
late Gradient backgroundGradientColor;
late bool isFrontVisible = true;
late bool isGestureUpdate = false;
bool isAmex = false;
#override
void initState() {
super.initState();
///initialize the animation controller
controller = AnimationController(
duration: widget.animationDuration,
vsync: this,
);
_gradientSetup();
_updateRotations(false);
}
void _gradientSetup() {
backgroundGradientColor = LinearGradient(
// Where the linear gradient begins and ends
begin: Alignment.topRight,
end: Alignment.bottomLeft,
// Add one stop for each color. Stops should increase from 0 to 1
stops: const <double>[0.1, 0.4, 0.7, 0.9],
colors: <Color>[
widget.cardBgColor.withOpacity(1),
widget.cardBgColor.withOpacity(0.97),
widget.cardBgColor.withOpacity(0.90),
widget.cardBgColor.withOpacity(0.86),
],
);
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
///
/// If uer adds CVV then toggle the card from front to back..
/// controller forward starts animation and shows back layout.
/// controller reverse starts animation and shows front layout.
///
if (!isGestureUpdate) {
_updateRotations(false);
if (widget.showBackView) {
controller.forward();
} else {
controller.reverse();
}
} else {
isGestureUpdate = false;
}
final CardType? cardType = widget.cardType != null
? widget.cardType
: detectCCType(widget.cardNumber);
widget.onCreditCardWidgetChange(CreditCardBrand(cardType));
return Stack(
children: <Widget>[
_cardGesture(
child: AnimationCard(
animation: _frontRotation,
child: _buildFrontContainer(),
),
),
_cardGesture(
child: AnimationCard(
animation: _backRotation,
child: _buildBackContainer(),
),
),
],
);
}
void _leftRotation() {
_toggleSide(false);
}
void _rightRotation() {
_toggleSide(true);
}
void _toggleSide(bool isRightTap) {
_updateRotations(!isRightTap);
if (isFrontVisible) {
controller.forward();
isFrontVisible = false;
} else {
controller.reverse();
isFrontVisible = true;
}
}
void _updateRotations(bool isRightSwipe) {
setState(() {
final bool rotateToLeft =
(isFrontVisible && !isRightSwipe) || !isFrontVisible &&
isRightSwipe;
///Initialize the Front to back rotation tween sequence.
_frontRotation = TweenSequence<double>(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: Tween<double>(
begin: 0.0, end: rotateToLeft ? (pi / 2) : (-pi / 2))
.chain(CurveTween(curve: Curves.linear)),
weight: 50.0,
),
TweenSequenceItem<double>(
tween: ConstantTween<double>(rotateToLeft ? (-pi / 2) : (pi /
2)),
weight: 50.0,
),
],
).animate(controller);
///Initialize the Back to Front rotation tween sequence.
_backRotation = TweenSequence<double>(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: ConstantTween<double>(rotateToLeft ? (pi / 2) : (-pi /
2)),
weight: 50.0,
),
TweenSequenceItem<double>(
tween: Tween<double>(
begin: rotateToLeft ? (-pi / 2) : (pi / 2), end: 0.0)
.chain(
CurveTween(curve: Curves.linear),
),
weight: 50.0,
),
],
).animate(controller);
});
}
///
/// Builds a front container containing
/// Card number, Exp. year and Card holder name
///
Widget _buildFrontContainer() {
final TextStyle defaultTextStyle =
Theme.of(context).textTheme.headline6!.merge(
const TextStyle(
color: Colors.white,
fontFamily: 'halter',
fontSize: 16,
package: 'flutter_credit_card',
),
);
final String number = widget.obscureCardNumber
? widget.cardNumber.replaceAll(RegExp(r'(?<=.{4})\d(?=.{4})'),
'*')
: widget.cardNumber;
return CardBackground(
backgroundImage: widget.backgroundImage,
backgroundGradientColor: backgroundGradientColor,
glassmorphismConfig: widget.glassmorphismConfig,
height: widget.height,
width: widget.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: widget.isChipVisible ? 2 : 0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
if (widget.isChipVisible)
Padding(
padding: const EdgeInsets.only(left: 16),
child: Image.asset(
'icons/chip.png',
package: 'flutter_credit_card',
scale: 1,
),
),
const Spacer(),
Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.only(left: 16, right: 16,
top: 8),
child: widget.cardType != null
? getCardTypeImage(widget.cardType)
: getCardTypeIcon(widget.cardNumber),
),
),
],
),
),
const SizedBox(
height: 10,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Text(
widget.cardNumber.isEmpty ? 'XXXX XXXX XXXX XXXX' :
number,
style: widget.textStyle ?? defaultTextStyle,
),
),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'VALID\nTHRU',
style: widget.textStyle ??
defaultTextStyle.copyWith(fontSize: 7),
textAlign: TextAlign.center,
),
const SizedBox(width: 5),
Text(
widget.expiryDate.isEmpty
? widget.labelExpiredDate
: widget.expiryDate,
style: widget.textStyle ?? defaultTextStyle,
),
],
),
),
),
Visibility(
visible: widget.isHolderNameVisible,
child: Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 16, right: 16,
bottom: 16),
child: Text(
widget.cardHolderName.isEmpty
? widget.labelCardHolder
: widget.cardHolderName,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: widget.textStyle ?? defaultTextStyle,
),
),
),
),
],
),
);
}
///
/// Builds a back container containing cvv
///
Widget _buildBackContainer() {
final TextStyle defaultTextStyle =
Theme.of(context).textTheme.headline6!.merge(
const TextStyle(
color: Colors.black,
fontFamily: 'halter',
fontSize: 16,
package: 'flutter_credit_card',
),
);
final String cvv = widget.obscureCardCvv
? widget.cvvCode.replaceAll(RegExp(r'\d'), '*')
: widget.cvvCode;
return CardBackground(
backgroundImage: widget.backgroundImage,
backgroundGradientColor: backgroundGradientColor,
glassmorphismConfig: widget.glassmorphismConfig,
height: widget.height,
width: widget.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
margin: const EdgeInsets.only(top: 16),
height: 48,
color: Colors.black,
),
),
Expanded(
flex: 2,
child: Container(
margin: const EdgeInsets.only(top: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 9,
child: Container(
height: 48,
color: Colors.white70,
),
),
Expanded(
flex: 3,
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(5),
child: Text(
widget.cvvCode.isEmpty
? isAmex
? 'XXXX'
: 'XXX'
: cvv,
maxLines: 1,
style: widget.textStyle ?? defaultTextStyle,
),
),
),
)
],
),
),
),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(left: 16, right: 16,
bottom: 16),
child: widget.cardType != null
? getCardTypeImage(widget.cardType)
: getCardTypeIcon(widget.cardNumber),
),
),
),
],
),
);
}
Widget _cardGesture({required Widget child}) {
bool isRightSwipe = true;
return widget.isSwipeGestureEnabled
? GestureDetector(
onPanEnd: (_) {
isGestureUpdate = true;
if (isRightSwipe) {
_leftRotation();
} else {
_rightRotation();
}
},
onPanUpdate: (DragUpdateDetails details) {
// Swiping in right direction.
if (details.delta.dx > 0) {
isRightSwipe = true;
}
// Swiping in left direction.
if (details.delta.dx < 0) {
isRightSwipe = false;
}
},
child: child,
)
: child;
}
/// Credit Card prefix patterns as of March 2019
/// A [List<String>] represents a range.
/// i.e. ['51', '55'] represents the range of cards starting with
'51'
to those starting with '55'
Map<CardType, Set<List<String>>> cardNumPatterns =
<CardType, Set<List<String>>>{
CardType.visa: <List<String>>{
<String>['4'],
},
CardType.americanExpress: <List<String>>{
<String>['34'],
<String>['37'],
},
CardType.discover: <List<String>>{
<String>['6011'],
<String>['622126', '622925'],
<String>['644', '649'],
<String>['65']
},
CardType.mastercard: <List<String>>{
<String>['51', '55'],
<String>['2221', '2229'],
<String>['223', '229'],
<String>['23', '26'],
<String>['270', '271'],
<String>['2720'],
},
};
/// This function determines the Credit Card type based on the
cardPatterns
/// and returns it.
CardType detectCCType(String cardNumber) {
//Default card type is other
CardType cardType = CardType.otherBrand;
if (cardNumber.isEmpty) {
return cardType;
}
cardNumPatterns.forEach(
(CardType type, Set<List<String>> patterns) {
for (List<String> patternRange in patterns) {
// Remove any spaces
String ccPatternStr =
cardNumber.replaceAll(RegExp(r'\s+\b|\b\s'), '');
final int rangeLen = patternRange[0].length;
// Trim the Credit Card number string to match the pattern
prefix length
if (rangeLen < cardNumber.length) {
ccPatternStr = ccPatternStr.substring(0, rangeLen);
}
if (patternRange.length > 1) {
// Convert the prefix range into numbers then make sure the
// Credit Card num is in the pattern range.
// Because Strings don't have '>=' type operators
final int ccPrefixAsInt = int.parse(ccPatternStr);
final int startPatternPrefixAsInt = int.parse(patternRange[0]);
final int endPatternPrefixAsInt = int.parse(patternRange[1]);
if (ccPrefixAsInt >= startPatternPrefixAsInt &&
ccPrefixAsInt <= endPatternPrefixAsInt) {
// Found a match
cardType = type;
break;
}
} else {
// Just compare the single pattern prefix with the Credit
Card prefix
if (ccPatternStr == patternRange[0]) {
// Found a match
cardType = type;
break;
}
}
}
},
);
return cardType;
}
Widget getCardTypeImage(CardType? cardType) {
final List<CustomCardTypeIcon> customCardTypeIcon =
getCustomCardTypeIcon(cardType!);
if(customCardTypeIcon.isNotEmpty){
return customCardTypeIcon.first.cardImage;
} else {
return Image.asset(
CardTypeIconAsset[cardType]!,
height: 48,
width: 48,
package: 'flutter_credit_card',
);
}
}
// This method returns the icon for the visa card type if found
// else will return the empty container
Widget getCardTypeIcon(String cardNumber) {
Widget icon;
final CardType ccType = detectCCType(cardNumber);
final List<CustomCardTypeIcon> customCardTypeIcon =
getCustomCardTypeIcon(ccType);
if (customCardTypeIcon.isNotEmpty) {
icon = customCardTypeIcon.first.cardImage;
isAmex = ccType == CardType.americanExpress;
} else {
switch (ccType) {
case CardType.visa:
icon = Image.asset(
CardTypeIconAsset[ccType]!,
height: 48,
width: 48,
package: 'flutter_credit_card',
);
isAmex = false;
break;
case CardType.americanExpress:
icon = Image.asset(
CardTypeIconAsset[ccType]!,
height: 48,
width: 48,
package: 'flutter_credit_card',
);
isAmex = true;
break;
case CardType.mastercard:
icon = Image.asset(
CardTypeIconAsset[ccType]!,
height: 48,
width: 48,
package: 'flutter_credit_card',
);
isAmex = false;
break;
case CardType.discover:
icon = Image.asset(
CardTypeIconAsset[ccType]!,
height: 48,
width: 48,
package: 'flutter_credit_card',
);
isAmex = false;
break;
default:
icon = Container(
height: 48,
width: 48,
);
isAmex = false;
break;
}
}
return icon;
}
List<CustomCardTypeIcon> getCustomCardTypeIcon(CardType
currentCardType) =>
widget.customCardTypeIcons
.where((CustomCardTypeIcon element) =>
element.cardType == currentCardType)
.toList();
}
class MaskedTextController extends TextEditingController {
MaskedTextController(
{String? text, required this.mask, Map<String, RegExp>?
translator})
: super(text: text) {
this.translator = translator ??
MaskedTextController.getDefaultTranslator();
addListener(() {
final String previous = _lastUpdatedText;
if (beforeChange(previous, this.text)) {
updateText(this.text);
afterChange(previous, this.text);
} else {
updateText(_lastUpdatedText);
}
});
updateText(this.text);
}
String mask;
late Map<String, RegExp> translator;
Function afterChange = (String previous, String next) {};
Function beforeChange = (String previous, String next) {
return true;
};
String _lastUpdatedText = '';
void updateText(String text) {
if (text.isNotEmpty) {
this.text = _applyMask(mask, text);
} else {
this.text = '';
}
_lastUpdatedText = this.text;
}
void updateMask(String mask, {bool moveCursorToEnd = true}) {
this.mask = mask;
updateText(text);
if (moveCursorToEnd) {
this.moveCursorToEnd();
}
}
void moveCursorToEnd() {
final String text = _lastUpdatedText;
selection = TextSelection.fromPosition(TextPosition(offset:
text.length));
}
#override
set text(String newText) {
if (super.text != newText) {
super.text = newText;
moveCursorToEnd();
}
}
static Map<String, RegExp> getDefaultTranslator() {
return <String, RegExp>{
'A': RegExp(r'[A-Za-z]'),
'0': RegExp(r'[0-9]'),
'#': RegExp(r'[A-Za-z0-9]'),
'*': RegExp(r'.*')
};
}
String _applyMask(String? mask, String value) {
String result = '';
int maskCharIndex = 0;
int valueCharIndex = 0;
while (true) {
// if mask is ended, break.
if (maskCharIndex == mask!.length) {
break;
}
// if value is ended, break.
if (valueCharIndex == value.length) {
break;
}
final String maskChar = mask[maskCharIndex];
final String valueChar = value[valueCharIndex];
// value equals mask, just set
if (maskChar == valueChar) {
result += maskChar;
valueCharIndex += 1;
maskCharIndex += 1;
continue;
}
// apply translator if match
if (translator.containsKey(maskChar)) {
if (translator[maskChar]!.hasMatch(valueChar)) {
result += valueChar;
maskCharIndex += 1;
}
valueCharIndex += 1;
continue;
}
// not masked value, fixed char on mask
result += maskChar;
maskCharIndex += 1;
continue;
}
return result;
}
}
enum CardType {
otherBrand,
mastercard,
visa,
americanExpress,
discover,
}
can someone help me to fix this??
thank you very much
The issue is CreditCardWidget has a required parameter onCreditCardWidgetChange which expects a function, it's missing in your code. You should change your code to pass that:
CreditCardWidget(
cardNumber: card['cardNumber'],
expiryDate: card['expiryDate'],
cardHolderName: card['cardHolderName'],
cvvCode: card['cvvCode'],
showBackView: false,
onCreditCardWidgetChange: (brand) {
print(brand);
},
),

Update page data after pop Navigation Updated #5

I have page Navigate to second page with variable (dID) with await to return same value if it has been changed ,at the second page if i did't do anything the value must return without any changes ,if i changed slider the value of (dID) must be increase by (1) ,but when i Navigate.pop the return value is same without increasing.
New update : After many test i did the problem is in the second page ,when i change the slider value i call a function to get the new value (newSavedDayId) ,and it is get it correctly but just inside the function ,after the slider change and get the new value ,it is returned to null :
newSavedDayId = Instance of 'Future<dynamic>'
second page which return value :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../classes/viewdigree.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Days extends StatefulWidget {
#override
_DaysState createState() => _DaysState();
}
TextEditingController insertedDegree = TextEditingController();
class _DaysState extends State<Days> {
#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'];
var lang = rdata['lang'];
int w_id;
var newSavedDayId = rdata['savedDayID']; ----// received value
var username;
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 =
'https://srdtraining.com/api/controller/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(),
'digree': degree.toString(),
'm_id': m_id.toString(),
'd_id': did.toString(),
'w_id': w_id.toString()
};
var url = 'https://srdtraining.com/api/controller/data/changedata.php';
var response = await http.post(url, body: sendData);
}
// End of Insert Func
//get user status .................. // this is the function to get new value
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
print('newSavedDayId = $newSavedDayId');----// here it is print new value with increasing correctly
}
// End get user
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
child: Center(
child: Text("Loading"),
),
),
);
} else {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data[0].link,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: false,
));
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, newSavedDayId);
}),
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 32),
),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
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(
fontFamily: 'Hafs',
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 =
double.parse(item.mydigree.toString());
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: 100,
value: _value,
label: _value.round().toString(),
onChanged: (val) {
send_degree(u_id, item.act_id,
val, w_id, did, m_id);
},
onChangeEnd: (val) {
setState(() {
_value = val;
});
getUserStatus(); /// when i print the value here it is give me null
}),
),
SizedBox(
height: 10,
),
Text('$_value',
style: TextStyle(
fontSize: 26,
color: Colors.white))
],
),
)
],
),
);
}).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,
),
],
),
],
),
),
);
}
});
}
}
you can usef ValueChanged onChanged and do a callback to the page you want to update ,
you can passe the onChanged funtion on the parametre ,
when you change your value use : onChanged()
than in the page you want to see the update on call your function with set state ,
I solved it by merging two function in one :
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/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;
}
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
and they now like this and worked correctly :
Future<List> fetchDigrees() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
username = preferences.getString('username');
var url1 =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response1 = await http.get(url1);
var data1 = jsonDecode(response1.body);
newSavedDayId = int.parse(data1['d_id']);
print('newSavedDayId before retrun = $newSavedDayId');
var url =
'https://srdtraining.com/api/controller/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;
}

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);
}