flutterdart

How to solve the problem of widget redrawing when changing screen size?


I'm new to Flutter and developing a web application. Depending on the screen size, I update the layout. But when the layout changes, the widget does not save the entered values in the fields; they are reset, along with the states. For example, I enter data in the mail and password fields and reduce the window from desktop to mobile, and then the text in the fields is reset. How to fix it.

class LoginDetails extends StatelessWidget {
  const LoginDetails({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [
            Color(0xFFAA00FF),
            Color.fromARGB(255, 135, 90, 86),
            Color.fromARGB(255, 229, 255, 0),
          ],
        ),
      ),
      child: ResponsiveLayout(
        largeScreen: DesktopView(),
        mediumScreen: TabletView(),
        smallScreen: MobileView(),
      ),
    );
  }
}

class DesktopView extends StatefulWidget {
  DesktopView({Key? key}) : super(key: key);

  @override
  State<DesktopView> createState() => _DesktopViewState();
}

class _DesktopViewState extends State<DesktopView> {
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  int userId = 0;

  bool _isAuthorized = false;
  bool _hasLicense = false;

     @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          SizedBox(
            height: 10,
          ),
          Text(
            'Авторизация',
            style: TextStyle(
              color: Colors.white,
              fontSize: 80,
              fontWeight: FontWeight.bold,
              fontFamily: 'Jura',
            ),
          ),
          Expanded(
            child: Center(
              child: Wrap(
                children: [
                  LoginCard(
                    emailController: emailController,
                    passwordController: passwordController,
                    loginUser: loginUser,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class MobileView extends StatefulWidget {
  MobileView({Key? key}) : super(key: key);

  @override
  State<MobileView> createState() => _MobileViewState();
}

class _MobileViewState extends State<MobileView> {
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  int userId = 0;
  bool _isAuthorized = false;
  bool _hasLicense = false;
@override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: SingleChildScrollView(
          child: Column(
            children: [
              SizedBox(
                height: 20,
              ),
              Text(
                'Авторизация',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 48,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'Jura',
                ),
              ),
              Center(
                child: Wrap(
                  children: [
                    LoginCard(
                      emailController: emailController,
                      passwordController: passwordController,
                      loginUser: loginUser,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class LoginCard extends StatelessWidget {
  final TextEditingController emailController;
  final TextEditingController passwordController;
  final VoidCallback loginUser;

  const LoginCard({
    required this.emailController,
    required this.passwordController,
    required this.loginUser,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final isMobile = ResponsiveLayout.isSmallScreen(context);
        final isMedium = ResponsiveLayout.isMediumScreen(context);
        final double cardWidth = 957;
        final double cardHeight = 544;
        final double contentPadding = 30.0;
        final double textFieldWidth = 557;
        final double textFieldHeight = 85;
        final double buttonMinWidth = 302;
        final double buttonMinHeight = 74;
        final double titleFontSize = 40.0;
        final double subtitleFontSize = 32.0;
        final double subtitleFontSizeSmall = 25.0;
        final double buttonFontSize = 64.0;

        return Card(
          color: Color.fromRGBO(53, 50, 50, 1),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(30.0),
          ),
          child: Container(
            width: isMobile || isMedium ? 857 : cardWidth,
            height: isMobile || isMedium ? 444 : cardHeight,
            padding: EdgeInsets.all(contentPadding),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                SizedBox(height: (isMobile) ? contentPadding / 2 : 0),
                Container(
                  width: textFieldWidth,
                  height: isMobile
                      ? textFieldHeight * 0.7
                      : isMedium
                          ? textFieldHeight * 0.7
                          : textFieldHeight,
                  child: TextFormField(
                    cursorColor: Colors.white,
                    controller: emailController,
                    keyboardType: TextInputType.emailAddress,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: isMobile || isMedium
                          ? titleFontSize * 0.6
                          : titleFontSize,
                      fontFamily: 'Jura',
                    ),
                    decoration: InputDecoration(
                      hintText: 'E-mail',
                      hintStyle: TextStyle(
                        color: Color.fromRGBO(216, 216, 216, 1),
                        fontSize: isMobile || isMedium
                            ? titleFontSize * 0.6
                            : titleFontSize,
                        fontFamily: 'Jura',
                      ),
                      filled: true,
                      fillColor: Color.fromRGBO(100, 100, 100, 1),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(30.0),
                        borderSide: BorderSide.none,
                      ),
                    ),
                  ),
                ),
                SizedBox(height: (isMobile) ? contentPadding / 2 : 40),
                Container(
                  width: textFieldWidth,
                  height: isMobile
                      ? textFieldHeight * 0.7
                      : isMedium
                          ? textFieldHeight * 0.7
                          : textFieldHeight,
                  child: TextFormField(
                    cursorColor: Colors.white,
                    controller: passwordController,
                    obscureText: true,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: isMobile || isMedium
                          ? titleFontSize * 0.6
                          : titleFontSize,
                      fontFamily: 'Jura',
                    ),
                    decoration: InputDecoration(
                      hintText: 'Пароль',
                      hintStyle: TextStyle(
                        color: Color.fromRGBO(216, 216, 216, 1),
                        fontSize: isMobile || isMedium
                            ? titleFontSize * 0.6
                            : titleFontSize,
                        fontFamily: 'Jura',
                      ),
                      filled: true,
                      fillColor: Color.fromRGBO(100, 100, 100, 1),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(30.0),
                        borderSide: BorderSide.none,
                      ),
                    ),
                  ),
                ),
                SizedBox(height: (isMobile) ? contentPadding / 2 : 40),
                Text(
                  'Нет аккаунта?',
                  style: TextStyle(
                    color: Color.fromRGBO(216, 216, 216, 1),
                    fontSize: isMobile || isMedium
                        ? subtitleFontSize * 0.75
                        : subtitleFontSize,
                    fontFamily: 'Jura',
                  ),
                ),
                Text.rich(
                  TextSpan(
                    text: 'Зарегистрироваться',
                    style: TextStyle(
                      color: Color.fromRGBO(136, 51, 166, 1),
                      fontSize: isMobile
                          ? subtitleFontSizeSmall * 0.8
                          : isMedium
                              ? subtitleFontSizeSmall * 0.8
                              : subtitleFontSizeSmall,
                      fontFamily: 'Jura',
                    ),
                    recognizer: TapGestureRecognizer()
                      ..onTap = () {
                        locator<NavigationService>().navigateTo(RegisterRoute);
                      },
                  ),
                ),
                SizedBox(height: (isMobile) ? contentPadding / 2 : 50),
                ElevatedButton(
                  onPressed: () {
                    loginUser();
                  },
                  child: Text(
                    'Войти',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: isMobile || isMedium
                          ? buttonFontSize * 0.75
                          : buttonFontSize,
                      fontFamily: 'Jura',
                    ),
                  ),
                  style: TextButton.styleFrom(
                    foregroundColor: Color.fromRGBO(216, 216, 216, 1),
                    backgroundColor: Color.fromRGBO(100, 100, 100, 1),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(35),
                    ),
                    minimumSize: Size(
                      buttonMinWidth,
                      isMobile || isMedium
                          ? textFieldHeight * 0.7
                          : buttonMinHeight,
                    ),
                  ),
                ),
                SizedBox(height: (isMobile) ? contentPadding / 2 : 0),
              ],
            ),
          ),
        );
      },
    );
  }
}

I tried using provider, working with controllers and so on. But the widget is still redrawn and the fields are cleared.


Solution

  • They resetting becasue every View widget in ur code has own variables

      TextEditingController emailController = TextEditingController();
      TextEditingController passwordController = TextEditingController();
      int userId = 0;
    
      bool _isAuthorized = false;
      bool _hasLicense = false;
    

    when ur layout is changed, all of this variables re-creating in Views.

    U have to do state management use Provider etc.