Flutter中TextFormField与AutoRoute集成异常问题求助
问题:Flutter AutoRoute路由下TextFormField功能异常
- 配置AutoRoute后,页面中的TextFormField出现以下问题:
- 点击输入框时屏幕闪烁(疑似组件重复重建),键盘短暂弹出后无法响应输入
- 在非初始路由(
initial: true)页面点击输入框,会自动跳转到初始路由页面
- 移除AutoRoute后输入框恢复正常,页面间导航按钮功能不受影响
- 已尝试用Form包裹输入框、为输入框设置key,均未解决问题
相关代码
main.dart
void main() async { await ScreenUtil.ensureScreenSize(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { ScreenUtil.init(context, designSize: const Size(AppConstants.appWidth, AppConstants.appHeight)); final _appRouter = AppRouter(); return MaterialApp.router( routerConfig: _appRouter.config(), debugShowCheckedModeBanner: false, title: 'Book AI', theme: AppTheme.darkTheme(), themeMode: ThemeMode.system, //home: const TestingScreen() ); } }
router.dart
import 'package:auto_route/auto_route.dart'; import 'package:book_ai/presentation/pages/route_test.dart'; import 'package:book_ai/presentation/pages/test.dart'; // import 'package:book_ai/presentation/router/router.dart'; part 'router.gr.dart'; @AutoRouterConfig() class AppRouter extends _$AppRouter { @override List<AutoRoute> get routes => [ AutoRoute(page: TestingRoute.page, initial: true), AutoRoute(page: RoutingTestRoute.page) ]; }
test.dart(包含输入框的页面)
@RoutePage() class TestingScreen extends StatefulWidget { const TestingScreen({super.key}); @override State<TestingScreen> createState() => _TestScreenState(); } class _TestScreenState extends State<TestingScreen> { final TextEditingController textController = TextEditingController(); final TextEditingController testController = TextEditingController(); @override Widget build(BuildContext context) { ScreenUtil.init(context, designSize: const Size(AppConstants.appWidth, AppConstants.appHeight)); return Scaffold( resizeToAvoidBottomInset: true, backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Theme.of(context).focusColor, title: const Text('Testing page'), ), body: Container( decoration:const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/bg-dark.png'), // Replace with your image path fit: BoxFit.cover, ), ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FilterButton(text: "hello", active: false, onPressed: () { }), // FilterButton(text: "hello", active: false, onPressed: () { }), PrimaryButton(text: "hello", onPressed: () { context.router.push(const RoutingTestRoute());}), SearchInput(controller: textController, hintText: 'Search for something'), TextFormField(controller: testController, decoration: InputDecoration( hintText: 'this is a test', border: InputBorder.none, hintStyle: Theme.of(context).textTheme.titleMedium ),) ], ), ), ), ); } }
自定义SearchInput组件
class SearchInput extends StatefulWidget { final TextEditingController controller; final String hintText; final VoidCallback? onSearchPressed; SearchInput({ required this.controller, required this.hintText, this.onSearchPressed, }); @override State<SearchInput> createState() => _SearchInputState(); } class _SearchInputState extends State<SearchInput> { @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.w), color: Theme.of(context).disabledColor, // Adjust the flopacity as needed ), child: ClipRRect( borderRadius: BorderRadius.circular(6.w), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Row( children: [ Expanded( child: Padding( padding: EdgeInsets.symmetric(horizontal: 16.w), child: Form( child: TextFormField( controller: widget.controller, decoration: InputDecoration( hintText: widget.hintText, border: InputBorder.none, hintStyle: Theme.of(context).textTheme.titleMedium ), ), ), ), ), IconButton( icon: const Icon(Icons.search), onPressed: widget.onSearchPressed, color: Theme.of(context).primaryColor, // fix issue that it shows as gray ), ], ), ), ), ); } }
解决方案
1. 固定AppRouter实例,避免每次build重建
在MyApp的build方法中每次创建新的AppRouter实例,会导致路由状态丢失,进而引发输入框异常。将_appRouter提升为类成员变量:
class MyApp extends StatelessWidget { const MyApp({super.key}); final _appRouter = AppRouter(); // 移至类成员位置 @override Widget build(BuildContext context) { ScreenUtil.init(context, designSize: const Size(AppConstants.appWidth, AppConstants.appHeight)); return MaterialApp.router( routerConfig: _appRouter.config(), debugShowCheckedModeBanner: false, title: 'Book AI', theme: AppTheme.darkTheme(), themeMode: ThemeMode.system, ); } }
2. 统一初始化ScreenUtil,避免页面内重复调用
每个页面build方法中调用ScreenUtil.init会触发不必要的组件重建,建议使用ScreenUtilInit组件统一初始化:
void main() async { await ScreenUtil.ensureScreenSize(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); final _appRouter = AppRouter(); @override Widget build(BuildContext context) { return ScreenUtilInit( designSize: const Size(AppConstants.appWidth, AppConstants.appHeight), builder: (context, child) { return MaterialApp.router( routerConfig: _appRouter.config(), debugShowCheckedModeBanner: false, title: 'Book AI', theme: AppTheme.darkTheme(), themeMode: ThemeMode.system, ); }, ); } }
同时移除TestingScreen中build方法内的ScreenUtil.init调用。
3. 检查路由页面注解
确保RoutingTestRoute对应的页面也正确添加@RoutePage()注解,避免路由配置错误导致的页面跳转异常。
内容的提问来源于stack exchange,提问作者safwanyasin
相关产品推荐
相关产品推荐

