Пользовательский интерфейс не обновляется после изменения состояния - PullRequest
0 голосов
/ 01 мая 2020

Я создаю флаттер приложение, которое включает в себя форму. Форма реализует модальный нижний лист, который я реализовал, используя плоскую кнопку, где дочерний элемент является текстом, и он динамически изменяется, когда пользователь выбирает значение в модальном нижнем листе. Все работает нормально, но пользовательский интерфейс не обновляется при изменении состояния, то есть дочерний текст плоской кнопки не меняется. Ниже приведен код. Я также открыт для предложений о том, как я могу использовать ввод текстовой формы для реализации модального нижнего листа.

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

1 Ответ

0 голосов
/ 01 мая 2020

Проблема в том, что контекст отличается. После выполнения «Navigator.pop (context)» в «_selectItem» вы должны вернуть значение, которое вы хотите установить в родительском виджете.

Если вы посмотрите документацию showModalBottomSheet Метод , вы обнаружите, что метод является Future, который возвращает значение в Navigator.pop.

Возвращает Future, который разрешается в значение (если есть), которое было передано в Navigator.pop когда модальный нижний лист был закрыт.

Таким образом, вы захотите вернуть значение с помощью функции Navigator.pop (context, value) и установить состояние после разрешения Future в родительском виджете.

[...]
void _bringBottomSheet(double height, childWidget) {
  var value = await showModalBottomSheet(...)
  setState((){stateVariable = value;})
  [...]

Кроме того, я бы дважды проверил метод showModalBottomSheet в вашем решении. Вы должны удалить StateBuilder внутри bottomModalSheet.

Это должно быть довольно просто, просто поместите showModalBottomSheet в функцию обратного вызова onTap TextFormField.

  TextFormField(
    decoration: InputDecoration(
      border: OutlineInputBorder(),
      labelText: 'Name',
    ),
    onTap: () {
      var value = showModalBottomSheet(
          context: context,
          builder: (context) => Container());
      // DO something with the value for example update a TextEditingController or your state
    },
    validator: (value) {
      if (value.isEmpty) {
        return 'Please enter your full name';
      }
      return null;
    },
  ),
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...