Flutter中TextFormField导致首次导航至LoginView延迟问题求助
Flutter首次导航至含自定义TextFormField的页面延迟问题
问题详情
- 技术栈:Flutter应用,采用Stacked架构及Stacked Services实现导航
- 现象:从route1首次导航至LoginView页面时出现约1秒延迟,仅在应用启动后首次出现;退出LoginView后再次导航流畅无延迟;注释掉LoginView中的2个基于TextFormField封装的CommonTextField组件后,导航恢复流畅。
自定义CommonTextField代码
class CommonTextField extends StatelessWidget { final TextEditingController? controller; final String? labelText; final String? fieldHeading; final Color? fillcolor; final TextStyle? textStyle; final Color? bordercolor; final bool? isTextHidden; final String? hintText; final String? prefixIcon; final bool? togglePassword; final int? maxLength; final int? maxlines; final void Function()? toggleFunction; final String? toggleIcon; final TextInputType? keyboardType; final void Function()? prefixIconTap; final Function(String)? onChanged; final FocusNode? focus; final double? prefixIconHeihgt; const CommonTextField( {super.key, this.controller, this.textStyle, this.maxlines = 1, this.bordercolor, this.labelText, this.fillcolor, this.hintText, this.isTextHidden, this.prefixIcon, this.onChanged, this.togglePassword = false, this.toggleFunction, this.toggleIcon, this.keyboardType, this.maxLength, this.prefixIconTap, this.fieldHeading, this.prefixIconHeihgt, this.focus}); @override Widget build(BuildContext context) { return TextFormField( controller: controller, style: TextStyles.body, onChanged: onChanged, obscureText: isTextHidden ?? false, maxLength: maxLength, cursorColor: AppConstants.primaryColor, focusNode: focus, keyboardType: keyboardType ?? TextInputType.text, textInputAction: TextInputAction.done, maxLines: maxlines, decoration: InputDecoration( counterText: "", suffixIcon: toggleIcon != null ? GestureDetector( onTap: toggleFunction, child: Padding( padding: const EdgeInsets.all(AppConstants.space12), child: SvgAsset(src: toggleIcon))) : null, enabledBorder: const OutlineInputBorder( borderSide: BorderSide( width: 0.2, color: AppConstants.primaryColor, ), borderRadius: BorderRadius.all( Radius.circular(AppConstants.space12), ), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide( width: 0.2, color: AppConstants.primaryColor, ), borderRadius: BorderRadius.all( Radius.circular(AppConstants.space12), ), ), hintText: hintText, fillColor: AppConstants.whiteColor.withOpacity(0.1), filled: true, hintStyle: TextStyles.body, contentPadding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 18.0), labelText: labelText, labelStyle: TextStyles.body, ), ); } }
解决办法
1. 预加载自定义字体
TextFormField首次渲染时会加载TextStyles.body使用的字体,首次启动时字体未缓存是延迟的常见原因。在应用启动阶段预加载字体:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 替换为你的字体路径 await Future.wait([ DefaultAssetBundle.of(WidgetsFlutterBinding.instance.window) .load('fonts/your-custom-font.ttf'), ]); runApp(const MyApp()); }
2. 预缓存SVG资源
如果toggleIcon使用的SVG是首次加载,会增加渲染耗时。在进入LoginView之前(比如route1页面的initState)预缓存SVG:
@override void initState() { super.initState(); // 替换为你的toggleIcon路径 precachePicture( ExactAssetPicture(SvgPicture.svgStringDecoder, 'assets/icons/toggle-password.svg'), context, ); }
3. 延迟加载TextField
通过延迟加载避免TextField渲染阻塞导航动画,修改CommonTextField的build方法:
@override Widget build(BuildContext context) { return FutureBuilder( future: Future.delayed(const Duration(milliseconds: 100)), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { // 原TextFormField代码 return TextFormField( controller: controller, style: TextStyles.body, onChanged: onChanged, obscureText: isTextHidden ?? false, maxLength: maxLength, cursorColor: AppConstants.primaryColor, focusNode: focus, keyboardType: keyboardType ?? TextInputType.text, textInputAction: TextInputAction.done, maxLines: maxlines, decoration: InputDecoration( counterText: "", suffixIcon: toggleIcon != null ? GestureDetector( onTap: toggleFunction, child: Padding( padding: const EdgeInsets.all(AppConstants.space12), child: SvgAsset(src: toggleIcon))) : null, enabledBorder: const OutlineInputBorder( borderSide: BorderSide( width: 0.2, color: AppConstants.primaryColor, ), borderRadius: BorderRadius.all( Radius.circular(AppConstants.space12), ), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide( width: 0.2, color: AppConstants.primaryColor, ), borderRadius: BorderRadius.all( Radius.circular(AppConstants.space12), ), ), hintText: hintText, fillColor: AppConstants.whiteColor.withOpacity(0.1), filled: true, hintStyle: TextStyles.body, contentPadding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 18.0), labelText: labelText, labelStyle: TextStyles.body, ), ); } // 占位Widget,避免布局跳动 return const SizedBox( height: 50, // 匹配TextField高度 ); }, ); }
4. 检查字体配置
确保pubspec.yaml中正确声明了自定义字体,避免字体加载失败或延迟:
flutter: fonts: - family: YourFontFamily fonts: - asset: fonts/your-custom-font.ttf
内容的提问来源于stack exchange,提问作者Usman Hafeez
相关产品推荐
相关产品推荐

