Я создаю флаттер приложение, которое включает в себя форму. Форма реализует модальный нижний лист, который я реализовал, используя плоскую кнопку, где дочерний элемент является текстом, и он динамически изменяется, когда пользователь выбирает значение в модальном нижнем листе. Все работает нормально, но пользовательский интерфейс не обновляется при изменении состояния, то есть дочерний текст плоской кнопки не меняется. Ниже приведен код. Я также открыт для предложений о том, как я могу использовать ввод текстовой формы для реализации модального нижнего листа.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shelter/models/user.dart';
import 'package:shelter/src/screens/home.screen.dart';
import 'package:shelter/src/screens/verification.screen.dart';
import 'package:shelter/src/utils/sizeconfig.dart';
class SignupScreen extends StatefulWidget {
@override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _user = User();
String _selectedAge;
String _selectedGender;
String _selectedRegion;
@override
void initState() {
// TODO: implement initState
super.initState();
_selectedAge = 'Select your age group';
_selectedGender = 'Select one..';
_selectedRegion = 'Choose your locality..';
}
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
backgroundColor: Color(0xFFF7CEB7),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(
horizontal: 15.0,
vertical: 25.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
IconButton(
onPressed: () => Navigator.pop(context),
icon: Icon(Icons.arrow_back_ios),
color: Color(0xFF2C4F68),
iconSize: 20.0,
),
],
),
FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(),
),
);
setState(() => _user.isAnonymous = true);
},
child: Text(
'Skip',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
)
]),
),
Container(
height: SizeConfig.safeBlockVertical * 120,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 20.0,
),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Create account',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 20.0,
fontWeight: FontWeight.w800,
),
),
SizedBox(
height: 10.0,
),
Text(
'Please enter your details',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: SizeConfig.safeBlockVertical * 2,
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name',
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter your full name';
}
return null;
},
),
SizedBox(
height: SizeConfig.safeBlockVertical * 2,
),
Text(
'Age Group',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 12.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 5.0),
OutlineButton(
onPressed: () => _bringBottomSheet(300.0,
singleChildScrollView(_ageGroups, _selectedAge)),
borderSide: BorderSide(
color: Colors.grey,
),
padding: EdgeInsets.only(
top: 20.0, bottom: 20.0, left: 10.0, right: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'$_selectedAge',
style: GoogleFonts.openSans(),
),
Icon(
Icons.arrow_drop_down,
),
],
),
),
SizedBox(
height: SizeConfig.safeBlockVertical * 2,
),
Text(
'Gender',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 12.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 5.0),
OutlineButton(
onPressed: () => _bringBottomSheet(
200.0, _column(_gender, _selectedGender)),
borderSide: BorderSide(
color: Colors.grey,
),
padding: EdgeInsets.only(
top: 20.0, bottom: 20.0, left: 10.0, right: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'$_selectedGender',
style: GoogleFonts.openSans(),
),
Icon(
Icons.arrow_drop_down,
),
],
),
),
SizedBox(
height: SizeConfig.safeBlockVertical * 2,
),
Text(
'Locality',
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
fontSize: 12.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 5.0),
OutlineButton(
onPressed: () => _bringBottomSheet(300.0,
singleChildScrollView(_regions, _selectedRegion)),
borderSide: BorderSide(
color: Colors.grey,
),
padding: EdgeInsets.only(
top: 20.0, bottom: 20.0, left: 10.0, right: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'$_selectedRegion',
style: GoogleFonts.openSans(),
),
Icon(
Icons.arrow_drop_down,
),
],
),
),
SizedBox(
height: SizeConfig.safeBlockVertical * 2,
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Household size',
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter your full name';
}
return null;
},
),
SizedBox(
height: SizeConfig.safeBlockVertical * 3,
),
Center(
child: FlatButton(
color: Color(0xFF2C4F68),
textColor: Colors.white,
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(),
),
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'Continue',
style: GoogleFonts.openSans(
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
],
),
),
),
)
],
),
),
);
}
List<String> _ageGroups = [
'0 - 10',
'11 - 20',
'21 - 30',
'31 - 40',
'41 - 50',
'51 - 60',
'61 - 70',
'71 - 80',
'81 - 90',
'over 90'
];
List<String> _regions = [
'Ashanti',
'Greater Accra',
'Central',
'Volta',
'Eastern',
'Northern',
];
List<String> _gender = [
'Male',
'Female',
'Prefer not to say',
];
void _bringBottomSheet(double height, childWidget) {
showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(
return Container(
color: Color(0xFF737373),
height: height,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0),
),
),
child: Padding(
padding: const EdgeInsets.all(15.0),
child: childWidget,
),
),
);
});
}
SingleChildScrollView singleChildScrollView(
List dataList, String setVariable) {
return SingleChildScrollView(child: _column(dataList, setVariable));
}
Column _column(List mapElement, String varTobeSet) {
return Column(
children: mapElement
.map(
(value) => ListTile(
title: Text(
value,
style: GoogleFonts.openSans(
color: Color(0xFF2C4F68),
),
),
onTap: () => _selectItem(value, varTobeSet),
),
)
.toList(),
);
}
void _selectItem(String value, String stateVariable) {
print(stateVariable);
Navigator.pop(context);
setState(() {
stateVariable = value;
print(stateVariable);
});
}
}