Страница StatefulWidget воссоздается при открытой клавиатуре

На странице моего профиля есть опция редактирования, когда я использую значок редактирования, я меняю текстовый виджет на TextField Widget, используя логическое условие, такое как
widget.isUpdate ? new Flexible(child: new TextField()) : Text("Text Widget"), он работает, но когда TextField сфокусирован, клавиатура открыта в это время StatefulWidget воссоздается, поэтому снова Boolean стал false, затем Textfield перейти к текстовому виджету. Этот сценарий происходит только тогда, когда на странице есть push-страница Navigator (вторая страница), например

 Navigator.push(context,MaterialPageRoute(builder: (context) => UpdateProfile()))

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

Код:

import 'package:flutter/material.dart';

class UpdateProfile extends StatefulWidget {
  bool isUpdate = false;

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return UpdateProfileState();
  }
}

class UpdateProfileState extends State<UpdateProfile> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
          title: Text("Update"),
          elevation: 2.0),
      body: Container(
        width: double.infinity,
        height: double.infinity,
        color: Colors.red,
        margin: const EdgeInsets.all(10.0),
        child: Row(
          children: <Widget>[
            widget.isUpdate ? new Flexible(child: new TextField()) : Text("Text Widget"),
            GestureDetector(
              child: IconTheme(
                  data: IconThemeData(color: Color(0xFFffffff)),
                  child: Icon(Icons.edit)),
              onTap: () {
                setState(() {
                  widget.isUpdate = !widget.isUpdate;
                });
              },
            )
          ],
        ),
      ),
    );
  }
}

Проблема:

Если я установил домашнюю страницу, то все будет нормально, как показано ниже.

import 'package:expense_manager_app/page/splash_page.dart';
import 'package:expense_manager_app/page/update_profile.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        brightness: Brightness.dark,
        primaryColor: Colors.red[500],
        accentColor: Colors.green[900],
      ),
      home: UpdateProfile(),
    );
  }
}

person Magesh Pandian    schedule 25.12.2018    source источник
comment
если кто-то проголосует против, укажите причину этого   -  person Magesh Pandian    schedule 25.12.2018


Ответы (3)


Вы должны переместить вашу переменную isUpdate внутрь вашего состояния, помните, что виджет неизменяем.

        class UpdateProfileState extends State<UpdateProfile> {

         bool isUpdate = false;

          @override
          Widget build(BuildContext context) {
            // TODO: implement build
            return Scaffold(
              appBar: AppBar(
                  title: Text("Update"),
                  elevation: 2.0),
              body: Container(
                width: double.infinity,
                height: double.infinity,
                color: Colors.red,
                margin: const EdgeInsets.all(10.0),
                child: Row(
                  children: <Widget>[
                    isUpdate ? new Flexible(child: new TextField()) : Text("Text Widget"),
                    GestureDetector(
                      child: IconTheme(
                          data: IconThemeData(color: Color(0xFFffffff)),
                          child: Icon(Icons.edit)),
                      onTap: () {
                        setState(() {
                          isUpdate = !isUpdate;
                        });
                      },
                    )
                  ],
                ),
              ),
            );
          }
        }

А также измените это:

    Navigator.push(context,MaterialPageRoute(builder: (context) => UpdateProfile()))

К этому:

    final page = UpdateProfile();
    Navigator.push(context,MaterialPageRoute(builder: (context) => page ))
person diegoveloper    schedule 25.12.2018
comment
да, я уже устал от его работы, но почему он не работает, когда эта страница является второй страницей, такой как Navigator push. как он работает как домашняя страница по умолчанию. - person Magesh Pandian; 25.12.2018
comment
Вы меняли пуш, как я писал выше? - person diegoveloper; 25.12.2018
comment
после того, как он установлен как окончательный, его работа, поэтому я сомневаюсь, что если я напрямую упоминаю внутри MaterialPageRoute, то каждый раз, когда он воссоздает объект? - person Magesh Pandian; 25.12.2018
comment
Да, весь контент внутри конструктора воссоздается, по этой причине вам нужно извлечь виджет в переменную - person diegoveloper; 25.12.2018

Это из-за того, что вы установили bool isUpdate = false; по умолчанию, измените его на bool isUpdate;

и используйте initState метод вашего класса State и установите для него isUpdate значение false. Мне позвонят один раз.

@override
void initState() { 
  widget.isUpdate = false;   
  super.initState();
}
person iPatel    schedule 25.12.2018
comment
если я установил в initState не по умолчанию, тогда он выдает ошибку, логическое выражение не должно быть нулевым - person Magesh Pandian; 25.12.2018
comment
@MageshPandian затем поместите bool isUpdate; в свой класс состояния и просто удалите префикс widget в методе initState. - person iPatel; 25.12.2018
comment
да, это уже работает, но я сомневаюсь, почему он воссоздает или повторно инициализирует при открытии клавиатуры, когда страница является второй страницей, а не домашней страницей - person Magesh Pandian; 25.12.2018

в качестве дополнения, если вы что-то сделаете с методом didChangeDependencies, это также приведет к тому, что

person Murat Aslan    schedule 28.09.2019