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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:22:47