如何解决改变屏幕尺寸时widget重绘的问题?

问题描述 投票:0回答:1

我是 Flutter 新手,正在开发 Web 应用程序。根据屏幕尺寸,我更新布局。但是当布局改变时,小部件不会保存在字段中输入的值;它们与状态一起被重置。例如,我在邮件和密码字段中输入数据,并将窗口从桌面缩小到移动设备,然后重置字段中的文本。如何修复它。

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

我尝试使用提供者、使用控制器等等。但小部件仍然会重新绘制,并且字段也会被清除。

flutter dart web
1个回答
0
投票

它们会重置,因为代码中的每个视图小部件都有自己的变量

  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  int userId = 0;

  bool _isAuthorized = false;
  bool _hasLicense = false;

当布局更改时,所有这些变量都会在视图中重新创建。

你必须使用Provider等进行状态管理

© www.soinside.com 2019 - 2024. All rights reserved.