无法更改下拉按钮值 Flutter
Cannot change Dropdown button value Flutter
我想从firebase获取下拉按钮的初始值;
但是当我尝试在构建方法中设置 governorateDDValue = selectedUser.governorate;
Dropdown 的值从 firebase 获取值,但我无法更改它
DropdownButton.gif
这是我的代码
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
var governorateDDValue;
@override
Widget build(BuildContext context) {
final userList= Provider.of<List<User>>(context);
final userID = ModalRoute.of(context)!.settings.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
governorateDDValue = selectedUser.governorate;
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);
}
}
提前致谢
你不能改变它的原因是每次调用setState
你的build
方法。因此,您的值将始终设置为 governorateDDValue = selectedUser.governorate;
因此,要允许更改,您应该将此 governorateDDValue = selectedUser.governorate;
放在 iniState
中
或者你可以这样做,这样它只会设置一次
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
bool initState = true; // ADD HERE
var governorateDDValue;
@override
Widget build(BuildContext context) {
final userList= Provider.of<List<User>>(context);
final userID = ModalRoute.of(context)!.settings.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
if(initState){ // ADD HERE
governorateDDValue = selectedUser.governorate;
initState = false; // ADD HERE
}
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);
}
因为您在构建小部件中使用 governorateDDValue = selectedUser.governorate;
,所以每次更改下拉菜单时都会重置其值
构建小部件将重建并且下拉列表的值将保持等于来自 firebase 的值
你应该在构建小部件之外使用 governorateDDValue = selectedUser.governorate;
这段代码应该可以工作
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
var loading = false;
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
var governorateDDValue;
@override
void initState() {
super.initState();
loading = true;
print('Future.delayed outside');
print(loading);
Future.delayed(Duration.zero, () {
governorateDDValue = selectedUser.governorate;
setState(() {
loading = false;
});
});
}
@override
Widget build(BuildContext context) {
final userList = Provider.of<List<User>>(context);
final userID = ModalRoute
.of(context)!
.settings
.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
governorateDDValue = selectedUser.governorate;
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);
我想从firebase获取下拉按钮的初始值;
但是当我尝试在构建方法中设置 governorateDDValue = selectedUser.governorate;
Dropdown 的值从 firebase 获取值,但我无法更改它
DropdownButton.gif
这是我的代码
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
var governorateDDValue;
@override
Widget build(BuildContext context) {
final userList= Provider.of<List<User>>(context);
final userID = ModalRoute.of(context)!.settings.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
governorateDDValue = selectedUser.governorate;
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);
} }
提前致谢
你不能改变它的原因是每次调用setState
你的build
方法。因此,您的值将始终设置为 governorateDDValue = selectedUser.governorate;
因此,要允许更改,您应该将此 governorateDDValue = selectedUser.governorate;
放在 iniState
或者你可以这样做,这样它只会设置一次
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
bool initState = true; // ADD HERE
var governorateDDValue;
@override
Widget build(BuildContext context) {
final userList= Provider.of<List<User>>(context);
final userID = ModalRoute.of(context)!.settings.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
if(initState){ // ADD HERE
governorateDDValue = selectedUser.governorate;
initState = false; // ADD HERE
}
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);
}
因为您在构建小部件中使用 governorateDDValue = selectedUser.governorate;
,所以每次更改下拉菜单时都会重置其值
构建小部件将重建并且下拉列表的值将保持等于来自 firebase 的值
你应该在构建小部件之外使用 governorateDDValue = selectedUser.governorate;
这段代码应该可以工作
class UserInfo extends StatefulWidget {
static const routeName = '/UserInfoScreen';
const UserInfo({Key? key}) : super(key: key);
@override
_UserInfoState createState() => _UserInfoState();
}
class _UserInfoState extends State<UserInfo> {
var loading = false;
late User selectedUser;
final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
var governorateDDValue;
@override
void initState() {
super.initState();
loading = true;
print('Future.delayed outside');
print(loading);
Future.delayed(Duration.zero, () {
governorateDDValue = selectedUser.governorate;
setState(() {
loading = false;
});
});
}
@override
Widget build(BuildContext context) {
final userList = Provider.of<List<User>>(context);
final userID = ModalRoute
.of(context)!
.settings
.arguments as String;
selectedUser =
userList.firstWhere((user) => user.id == userID);
// this line makes dropdown value always equal to value from firestore
governorateDDValue = selectedUser.governorate;
return Scaffold(
appBar: AppBar(
title: Text('report'),
),
body: SingleChildScrollView(
child: Container(
child: Row(
children: <Widget>[
Text('Governorate',),
Container(height: 5),
DropdownButton<String>(
value: governorateDDValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
governorateDDValue = newValue!;
});
},
items: Constants.governoratesOfEgypt
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
),
);