Flutter实现键盘弹出时组件先缩放后可滚动的登录界面
Flutter登录界面实现键盘弹出时先自适应布局再滚动
要实现键盘弹出时先让组件完成大小调整,空间不足时才允许滚动的效果,可以通过LayoutBuilder结合SingleChildScrollView和ConstrainedBox来实现,既保留原布局的自适应特性,又能在需要时启用滚动。
修改后的完整代码
return Scaffold( body: SafeArea( // 使用LayoutBuilder获取父容器的约束信息 child: LayoutBuilder( builder: (context, constraints) { return SingleChildScrollView( child: ConstrainedBox( // 设置最小高度为父容器的最大高度,确保空间足够时Column撑满布局 constraints: BoxConstraints(minHeight: constraints.maxHeight), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Flexible(flex: 2, child: Container()), Container( padding: const EdgeInsets.symmetric(horizontal: 32), child: Column( children: [ SvgPicture.asset( "assets/images/ic_instagram.svg", colorFilter: ColorFilter.mode(isDarkMode ? primaryColor : Colors.black, BlendMode.srcIn), ), const SizedBox(height: 20.0), InputTextField( fillColor: isDarkMode ? Colors.grey.shade800 : Colors.grey[100], borderSideColor: isDarkMode ? Colors.black : Colors.grey.shade400, hintText: "Phone number, email or username", textInputType: TextInputType.emailAddress, textEditingController: _emailController, isPassword: false, ), const SizedBox(height: 15.0), InputTextField( fillColor: isDarkMode ? Colors.grey.shade800 : Colors.grey[100], borderSideColor: isDarkMode ? Colors.black : Colors.grey.shade400, hintText: "Password", textInputType: TextInputType.visiblePassword, textEditingController: _passwordController, isPassword: true, ), const SizedBox(height: 17.0), CustomButton( buttonContext: const Text( "Log in", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), onPressed: () {}, ), const SizedBox(height: 9.0), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: () => print("a"), child: const Padding( padding: EdgeInsets.symmetric(vertical: 5.0), child: Text( "Forgot your login details? ", style: TextStyle(color: Colors.grey, fontSize: 12.0, letterSpacing: 0.1), ), ), ), GestureDetector( onTap: () => print("a"), child: Padding( padding: const EdgeInsets.symmetric(vertical: 5.0), child: Text( "Get help logging in.", style: TextStyle( fontFamily: 'Roboto', color: isDarkMode ? Colors.white : Colors.purple.shade900, fontSize: 12.0, letterSpacing: 0.1, fontWeight: FontWeight.w700), ), ), ), ], ), const SizedBox(height: 5.0), Row( children: [ Expanded( child: Divider(color: Colors.grey[400], height: 36), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( "OR", style: TextStyle(color: Colors.grey.shade600, fontWeight: FontWeight.bold), ), ), Expanded(child: Divider(color: Colors.grey[400], height: 36)), ], ), const SizedBox(height: 5.0), CustomButton( buttonContext: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SvgPicture.asset( "assets/images/ic_facebook.svg", colorFilter: const ColorFilter.mode(primaryColor, BlendMode.srcIn), ), const SizedBox(width: 8.0), const Text( 'Logging in with Facebook', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), ], ), onPressed: () {}, ), ], ), ), Flexible(flex: 1, child: Container()), Divider(color: Colors.grey[400], height: 36), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: () => print("a"), child: const Padding( padding: EdgeInsets.symmetric(vertical: 5.0), child: Text( "Forgot your login details? ", style: TextStyle(color: Colors.grey, fontSize: 12.0, letterSpacing: 0.1), ), ), ), GestureDetector( onTap: () => print("a"), child: Padding( padding: const EdgeInsets.symmetric(vertical: 5.0), child: Text( "Get help logging in.", style: TextStyle( fontFamily: 'Roboto', color: isDarkMode ? Colors.white : Colors.purple.shade900, fontSize: 12.0, letterSpacing: 0.1, fontWeight: FontWeight.w700), ), ), ), ], ), ], ), ), ); }, ), ), );
关键修改说明
- LayoutBuilder:获取父容器的可用高度约束,动态设置Column的最小高度
- ConstrainedBox + minHeight:空间足够时让Column撑满父容器,保留原布局中
Flexible的上下间距比例;键盘弹出导致高度不足时,Column总高度超过最小高度,SingleChildScrollView自动启用滚动 - 完全保留原有布局组件和样式,无需调整
Flexible、间距等设置,完美兼容原设计
内容的提问来源于stack exchange,提问作者minh minh
相关产品推荐
相关产品推荐

