You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web屏幕尺寸变化时输入框状态重置问题求解

问题修复方案

核心问题原因

你当前的实现中,DesktopView和MobileView是两个独立的StatefulWidget,各自维护自己的TextEditingController和状态。当屏幕尺寸切换时,Flutter会销毁旧的视图组件,创建新的视图实例,新实例的控制器是全新的空对象,导致输入内容被清空。

修复步骤

1. 将状态提升到父组件

把共享的状态和控制器移到最上层的LoginDetails组件,让它变成StatefulWidget,这样所有视图共享同一套状态:

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

  @override
  State<LoginDetails> createState() => _LoginDetailsState();
}

class _LoginDetailsState extends State<LoginDetails> {
  // 共享的控制器和状态
  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  int userId = 0;
  bool _isAuthorized = false;
  bool _hasLicense = false;

  void loginUser() {
    // 保留你的登录逻辑
  }

  @override
  void dispose() {
    // 记得销毁控制器,避免内存泄漏
    emailController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [
            const Color(0xFFAA00FF),
            const Color.fromARGB(255, 135, 90, 86),
            const Color.fromARGB(255, 229, 255, 0),
          ],
        ),
      ),
      child: ResponsiveLayout(
        // 将共享状态传递给各个视图
        largeScreen: DesktopView(
          emailController: emailController,
          passwordController: passwordController,
          loginUser: loginUser,
        ),
        mediumScreen: TabletView(
          emailController: emailController,
          passwordController: passwordController,
          loginUser: loginUser,
        ),
        smallScreen: MobileView(
          emailController: emailController,
          passwordController: passwordController,
          loginUser: loginUser,
        ),
      ),
    );
  }
}

2. 修改子视图为无状态组件

让DesktopView和MobileView变成StatelessWidget,只负责渲染布局,不再维护自己的状态:

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

  const DesktopView({
    Key? key,
    required this.emailController,
    required this.passwordController,
    required this.loginUser,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          const 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 StatelessWidget {
  final TextEditingController emailController;
  final TextEditingController passwordController;
  final VoidCallback loginUser;

  const MobileView({
    Key? key,
    required this.emailController,
    required this.passwordController,
    required this.loginUser,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          children: [
            const 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,
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

3. 补充TabletView的修改

按照同样的逻辑修改TabletView,让它也接收父组件传递的控制器和回调,确保所有视图共享同一状态。

为什么这样能解决问题

状态被提升到父组件后,无论屏幕尺寸如何切换,LoginDetails的State始终存在,控制器和输入内容不会被销毁。子视图只是根据布局需求渲染不同的UI结构,使用的都是父组件传递过来的同一个控制器,所以输入内容会被保留。

内容的提问来源于stack exchange,提问作者Hyper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:22:02