Flutter dropdown items not showing - flutter

I am showing i simple drop down but my options are not opening mean its not showing a dropdown.
I have a simple list like this
[352094083791878, 358480083322091, 358480081409924]
This is my code
class _SettingPageState extends State<SettingPage> {
bool isSwitched = false;
bool _shoW = true;
var items = [];
#override
void initState() {
super.initState();
getImi();
}
getImi() async {
final storage = new FlutterSecureStorage();
String userNumber = await storage.read(key: "userNumber");
String userPassword = await storage.read(key: "userPassword");
print('showimi');
print(userNumber);
print(userPassword);
var map = new Map<String, dynamic>();
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Center(
child: SpinKitWave(
color: Color(0xff00abb5), type: SpinKitWaveType.center));
});
var url =
'http://api.igiinsurance.com.pk:8888/drive_api/login.php?number=${userNumber}&password=${userPassword}';
print(url);
http.Response res = await http.get(
url,
headers: <String, String>{'token': 'c66026133e80d4960f0a5b7d418a4d08'},
);
var data = json.decode(res.body.toString());
print(data);
if (data['status'].toString() == "Success") {
Navigator.pop(context);
_shoW = true;
data['data'].forEach((row) {
print(row['imei_number']);
items.add(row['imei_number']);
print(items);
});
} else {
Navigator.pop(context);
_shoW = false;
}
}
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
body: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/sidebg.png"), fit: BoxFit.cover),
),
child: Column(
children: [
_shoW
? DropdownButton(
hint: Text('Select Vechile'),
items: items.map((val) {
return DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
onChanged: null)
: Container()
],
),
),
);
}
}
I am simply adding values in the Items array. I need to show the array in the select down list. But it's not opening the options i have try to put static list but that's also not working .

You need to set onChanged to not null value. onChanged without listener cannot allow you to open list.
If you need to showing current selected value, pass value parameter to DropdownButton. Also you can find more examples in Official Flutter Documentation.

Change Your Code Like THis :
if (data['status'].toString() == "Success") {
Navigator.pop(context);
setState(){
_shoW = true;
}
data['data'].forEach((row) {
print(row['imei_number']);
items.add(row['imei_number']);
print(items);
});
} else {
Navigator.pop(context);
setState(){
_shoW = false;
}
}

Related

Create a pin code. No navigation when re-entering a pin

I'm making a screen with creating a pin code to enter the application. But unfortunately my code doesn't work.
I'm trying to implement this through local storage. Here's the logic - as soon as the user goes to the create screen, I check if there is a pin code in the local storage.
Here is the function -
Future<int?> sharedPrefsGet() async {
final prefs = await SharedPreferences.getInstance();
print(await prefs.getInt('pinCode'));
return await prefs.getInt('pinCode');
}
late final Future<int?> future = sharedPrefsGet();
void initState() {
super.initState();
sharedPrefsGet();
}
Further, when entering the pin code, I check if there is a pin code and what will happen -
onCompleted: (value) async {
pinCode = int parse(value);
sharedPrefsSet(pinCode);
if(sharedPrefsGet() == value) {
context.go('/home');
} else {
context.go('/createPinCode');
}
context.go('/createPinCode');
},
and of course, there I try to save the pin code to the local storage. Here is the function -
var pinCode;
sharedPrefsSet(int pin) async {
final prefs = await SharedPreferences.getInstance();
return await prefs.setInt('pinCode', pin);
}
but my code doesn't work, I don't get any errors.
The user enters the password, this screen opens again, he enters the code again, but navigation to the home page no longer occurs. Why?
full code -
class CreatePinCode extends StatefulWidget {
#override
_CreatePinCodeState createState() => _CreatePinCodeState();
}
class _CreatePinCodeState extends State<CreatePinCode> {
final TextEditingController _controller = TextEditingController();
var pinCode;
sharedPrefsSet(int pin) async {
final prefs = await SharedPreferences.getInstance();
return await prefs.setInt('pinCode', pin);
}
Future<int?> sharedPrefsGet() async {
final prefs = await SharedPreferences.getInstance();
print(await prefs.getInt('pinCode'));
return await prefs.getInt('pinCode');
}
late final Future<int?> future = sharedPrefsGet();
#override
void initState() {
super.initState();
sharedPrefsGet();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ConfigColor.background,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder(
future: future,
builder: (context, snapshot) =>
snapshot.hasData? Text('123123123123123') : Text('ababababab')
),
Padding(
padding: const EdgeInsets.all(100),
child: SizedBox(
height: 70,
child: Center(
child: PinCodeTextField(
controller: _controller,
mainAxisAlignment: MainAxisAlignment.spaceAround,
obscuringWidget: Container(
width: 15,
height: 15,
decoration: BoxDecoration(
color: ConfigColor.green,
shape: BoxShape.circle
),
),
appContext: context,
length: 4,
onChanged: (value) {
print(value);
},
pinTheme: PinTheme(
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(50),
fieldHeight: 15,
fieldWidth: 15,
activeColor: ConfigColor.green,
inactiveColor: Colors.white.withOpacity(0.3),
disabledColor: Colors.white.withOpacity(0.3),
),
onCompleted: (values) async {
final prefs = await SharedPreferences.getInstance();
final pinCod = await prefs.setInt('pinCod', int.parse(values));
if(!pinCod) {// either true or false
if(pinCod == int.parse(values)) {
log('Все хорошо');
} else {
log('Код не совпадает!');
}
}
pinCode = int.parse(values);
final int? value = await sharedPrefsGet() ;
if(value== null) {
context.go('/createPinCode');
} else if (value == pinCode){
await sharedPrefsSet(pinCode);
context.go('/home');
} else {
}
},
)
),
),
),
// implement the custom NumPad
NumPad(
buttonSize: 65,
buttonColor: ConfigColor.background,
iconColor: Colors.deepOrange,
controller: _controller,
delete: () {
_controller.text = _controller.text
.substring(0, _controller.text.length - 1);
},
// do something with the input numbers
onSubmit: () {
debugPrint('Your code: ${_controller.text}');
showDialog(
context: context,
builder: (_) => AlertDialog(
content: Text(
"You code is ${_controller.text}",
style: const TextStyle(fontSize: 30),
),
));
},
),
],
)
);
}
}
It would better add return type on sharedPrefsGet while it is returning a future.
Future<int> sharedPrefsGet() async {
Using Future builder to get data.
sharedPrefsSet(int pin) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('pinCode', pin);
}
Future<int?> sharedPrefsGet() async {
final prefs = await SharedPreferences.getInstance();
print(await prefs.getInt('pinCode'));
return await prefs.getInt('pinCode');
}
late final Future<int?> future = sharedPrefsGet();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: future,
builder: (context, snapshot) =>
snapshot.hasData?
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
!snapshot.hasData ? Text('ababababab') : Text('123123123'),
.........
And use await to get data
onCompleted: (value) async {
final prefs = await SharedPreferences.getInstance();
final pinCod = await prefs.setInt('pinCod', int.parse(value));
if(!pinCod) {// either true or false
if(pinCod == int.parse(value)) {
log('Все хорошо');
} else {
log('Код не совпадает!');
}
}
pinCode = int.parse(value);
final int? value = await sharedPrefsGet() ;
if(value== null) {
} else if (value== youValue){
await sharedPrefsSet(pinCode);
} else {
}
},
problem is here :
sharedPrefsGet() async {
final prefs = await SharedPreferences.getInstance();
print(await prefs.getInt('pinCode'));
return await prefs.getInt('pinCode');
}
when you are doing this : prefs.getInt('pinCode')
Instead of this Try to do this :
sharedPrefsGet() async {
final prefs = await SharedPreferences.getInstance();
print(await prefs.getInt('pinCode') ?? -1);
return await prefs.getInt('pinCode') ?? -1; //here -1 means not given pin
}
now add your code for this logic

How to display in dialog variable from API request in Flutter

I want to access the variable totalPresences that I have in my API request where I sum up the values from a map. Then I want to display the variable in my widget inside a dialog. How can I do that? Thanks in advance!
Here is my code
Future<List<Presence>> getPresencesByAthleteId() async {
try {
final response = await http.get(
Uri.parse();
if (response.statusCode == 200) {
Map map = json.decode(response.body);
List<Presence>? presencesList = [];
map.forEach((key, value) {
presencesList.add(Presence(
date: map.entries.first.key, count: map.entries.first.value));
var values = map.values;
var totalPresences = values.reduce((sum, element) => sum + element); //this I want to display it in a text
});
return presencesList.toList();
}
} catch (e) {
logger.e(e.toString());
}
return getPresencesByAthleteId(depId, teamId, id, context);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Athlete>>(
...
secondary: IconButton(
icon: const Icon(Icons.history_outlined,
color: Colors.black, size: 25),
onPressed: () {
if (_athlete[i].currentMonthPresences! > 0) {
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
children: [
Column(
FutureBuilder<List<Presence>>(
future: getPresencesByAthleteId(_athlete[i].department!.id, widget._team.teamKey!.teamId, _athlete[i].id, context),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
...
}),
);
} else if (snapshot.hasError) {
logger.e('${snapshot.error}');
}
}),
Container(
child:
Row(
children: [
const Text(''), // HERE I WANT TO DISPLAY totalPresences
)
],
),
),
It was easier than I thought I just needed a setState inside my api request like this:
int total=0;
Future<List<Presence>> getPresencesByAthleteId() async {
try {
final response = await http.get(
Uri.parse();
if (response.statusCode == 200) {
Map map = json.decode(response.body);
List<Presence>? presencesList = [];
map.forEach((key, value) {
presencesList.add(Presence(
date: map.entries.first.key, count: map.entries.first.value));
var values = map.values;
var totalPresences = values.reduce((sum, element) => sum + element);
setState(() {
totalPresences = total;
});
});
return presencesList.toList();
}
} catch (e) {
logger.e(e.toString());
}
return getPresencesByAthleteId(depId, teamId, id, context);
}
and then just display in dialog
.
.
const Text($total),

Change Notifier Provider with async function

I'm trying to use provider with an async function where I'm changing a value of variable and as soon as the value changes, I want all listeners to be notified.
I'm sending a post request and waiting for response in the below async function. I'm waiting for the response and depending on that I want to show message on the Stateful Widget.
The provider seems to change value of the variable but doesn't change state on Text on the screen.
userloginprovider.dart
bool isLoading = false;
HttpService http = HttpService();
class UserLoginProvider with ChangeNotifier {
String loginMessage = '';
late UserAuthorizationResponse userRegistrationResponse;
Future loginUser(userData) async {
Response response;
print(loginMessage);
try {
isLoading = true;
response = await http.loginUser('api/v1/login/', userData);
isLoading = false;
if (response.statusCode == 200) {
var newReponse = response.data;
userRegistrationResponse =
UserAuthorizationResponse.fromJson(newReponse['data']);
loginMessage = newReponse['message'];
} else {
print('status code is not 200.');
}
} on Exception catch (e) {
isLoading = false;
loginMessage = e.toString().substring(11);
}
notifyListeners();
}
}
userloginscreen.dart
class _LoginPageState extends State<LoginPage> {
final UserLoginProvider userLoginProvider = UserLoginProvider();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ChangeNotifierProvider(
create: (context) => UserLoginProvider(),
child: Consumer<UserLoginProvider>(
builder: (context, provider, child) {
return Container(
padding: const EdgeInsets.all(8.0),
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(provider.loginMessage.toString()), //<-- I want to change value here.
AuthorizationButtons(
fieldName: 'Username',
textEditingController: usernameController,
),
AuthorizationButtons(
fieldName: 'Password',
textEditingController: passwordController,
),
OutlinedButton(
onPressed: () {
userData = {
'username': usernameController.text,
'password': passwordController.text,
};
userLoginProvider.loginUser(userData);
},
child: const Text('Submit'),
)
],
),
);
},
),
),
);
}
}
A new provider is created in every rebuild
body: ChangeNotifierProvider(
create: (context) => UserLoginProvider(),
Use the one in the state
body: ChangeNotifierProvider(
create: (context) => userLoginProvider,
you are notifying the listeners when it fails which is in catch block:-
on Exception catch (e) {
isLoading = false;
loginMessage = e.toString().substring(11); //here
notifyListeners();
}
}
but if the code runs without the error(exception). you are not notifying it on your code. so,if you want to notify, try something like this
try {
isLoading = true;
response = await http.loginUser('api/v1/login/', userData);
isLoading = false;
if (response.statusCode == 200) {
var newReponse = response.data;
userRegistrationResponse =
UserAuthorizationResponse.fromJson(newReponse['data']);
loginMessage = 'something'; //here
} else {
print('status code is not 200.');
}
notifyListeners();//notify the listeners here

Flutter - whenComplete() not working as expected when using Providers

I'm trying to display a loading while doing an API Request and when finished to show the list with the response or a custom widget to show a message(EmptyListWidget). The problem is that the whenComplete() method is being executed before the async function is finished.
I also tried using then() and using FutureBuilder but I also can't make it work using Provider (allways returns null).
If someone could help, I would really appreciate it.. thanks :)
My List Widget:
class _AbsencesListState extends State<AbsencesList> {
bool _isLoading = false;
bool _isInit = true;
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isInit) {
setState(() => _isLoading = true);
Provider.of<AbsencesTypes>(context, listen: false)
.getAbsencesTypes(widget.ctx)
.whenComplete(() {
setState(() => _isLoading = false);
});
_isInit = false;
}
}
#override
Widget build(BuildContext context) {
final absences = Provider.of<Absences>(context).items;
return Stack(
children: [
_isLoading
? const Center(child: CircularProgressIndicator())
: absences.length > 0
? Container()
: EmptyListWidget(ListType.InconsistenciesList),
ListView.builder(
itemBuilder: (_, index) {
return GestureDetector(
onTap: () {},
child: Card(
elevation: 2.0,
child: ListTile(
leading: CircleAvatar(
child: const Icon(Icons.sick),
backgroundColor: Theme.of(context).accentColor,
foregroundColor: Colors.white,
),
title: Padding(
padding: const EdgeInsets.only(top: 3),
child: Text(absences[index].absenceType.name),
),
subtitle: Text(
absences[index].firstDate
),
),
),
);
},
itemCount: absences.length,
)
],
);
}
}
The async function:
class AbsencesTypes with ChangeNotifier {
List<AbsenceType> _absencesTypesList = [];
List<AbsenceType> get items {
return [..._absencesTypesList];
}
void emptyAbsencesTypeList() {
_absencesTypesList.clear();
}
Future<void> getAbsencesTypes(BuildContext context) async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
String token = _prefs.getString(TOKEN_KEY);
http.get(
API_URL,
headers: {"Authorization": token},
).then(
(http.Response response) async {
if (response.statusCode == 200) {
final apiResponse = json.decode(utf8.decode(response.bodyBytes));
final extractedData = apiResponse['content'];
final List<AbsenceType> loadedAbsencesTypes = [];
for (var absenceType in extractedData) {
loadedAbsencesTypes.add(
AbsenceType(
id: absenceType["id"],
name: absenceType["name"].toString(),
code: absenceType["code"].toString(),
totalAllowedDays: absenceType["totalAllowedDays"],
),
);
}
_absencesTypesList = loadedAbsencesTypes;
} else if (response.statusCode == 401) {
Utility.showToast(
AppLocalizations.of(context).translate("expired_session_string"));
Utility.sendUserToLogin(_prefs, context);
}
notifyListeners();
},
);
}
}
Your problem here is probably that you're calling http.get without awaiting for it's result.
The getAbsencesTypes returns the Future<void> as soon as the http.get method is executed, without waiting for the answer, and it results in your onComplete method to be triggered.
A simple fix would be to add the await keyword before the http.get, but you could do even better.
In your code, you're not fully using the ChangeNotifierProvider which could solve your problem. You should check the Consumer class which will be pretty useful for you here, but since it's not your initial question I won't go more in depth on this subject.

How to use image_picker in flutter

I am confused about how to use image_picker, this is how I use it in my application (like in many tutorials):
class AddDialogState extends State<AddDialog> {
File galleryFile;
Widget _onlyStatus() {
getLocalImage() async {
var _galleryFile = await ImagePicker.pickImage(
source: ImageSource.gallery
};
setState(() {
galleryFile = _galleryFile;
});
print(_galleryFile.path);
}
return Column(
........
FlatButton.icon(
onPressed: () {
getLocalImage();
}
)
)
}
#override
Widget build(BuildContext context) {
// fullscreen dialog
.........
body: _onlyStatus()
}
}
The problem was, the above code doesn't start ImagePicker, when i click the FlatButton, the above code just produce an error the getter 'path' was called on null, it doesn't start any new activity related to gallery, so what's wrong with my code?
Actually pickImage() is deprecated now. So you have to use ImagePicker.getImage(source: ImageSource.gallery)
Click here for more
void getImage(ImageSource imageSource) async {
PickedFile imageFile = await picker.getImage(source: imageSource);
if (imageFile == null) return;
File tmpFile = File(imageFile.path);
final appDir = await getApplicationDocumentsDirectory();
final fileName = basename(imageFile.path);
tmpFile = await tmpFile.copy('${appDir.path}/$fileName');
setState(() {
_image = tmpFile;
});
}
The code also store image file in device directory. Path pacakage is also used.
Here is my example you only need to call the SelectionItem and pass the required parameters and it's done, also it includes support for Android and iOS.
class SelectionItem {
String text;
GestureTapCallback action;
SelectionItem({
this.text,
this.action,
});
}
Widget _getOptionWidget(SelectionItem item) {
return SimpleDialogOption(
onPressed: item.action,
child: Text(item.text),
);
}
Widget _getCupertinoOptionWidget(SelectionItem item) {
return CupertinoActionSheetAction(
onPressed: item.action,
child: Text(item.text),
);
}
showSelector(
BuildContext context, {
String title,
List<SelectionItem> actions,
}) {
bool isAndroid = Injector.instance.platform == Platform.ANDROID;
if (isAndroid) {
final items = actions.map((action) => _getOptionWidget(action)).toList();
return SimpleDialog(
title: Text(title),
children: items,
);
} else {
final items =
actions.map((action) => _getCupertinoOptionWidget(action)).toList();
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CupertinoActionSheet(
title: Text(title),
actions: items,
cancelButton: CupertinoActionSheetAction(
onPressed: () {
NavigationUtils.pop(context);
},
child: Text("Cancel"),
),
),
],
);
}
}
your showDialog should be something like this:
Container(
width: 300,
height: 300,
child: GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) => showSelector(
context,
"Select",
actions: [
SelectionItem(
"Camera",
action: () {
getImage(ImageSource.camera);
Navigator.of(context).pop();
},
),
SelectionItem(
"Gallery",
action: () {
getImage(ImageSource.gallery);
Navigator.of(context).pop();
},
)
],
),
);
},
),
)
Here is my code for image_picker: ^0.8.4+4 (flutter 2.8.1)
bool hasImage = false;
File? image;
Future getImage(ImageSource source) async {
try {
final image = await ImagePicker().pickImage(source: source);
if (image == null) return;
final imageTemporary = File(image.path);
setState(() {
this.image = imageTemporary;
hasImage = true;
});
} on PlatformException catch (e) {
debugPrint('Failed to pick image: $e');
}
}