Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

TextFormField not working properly with AutoRoute

I am trying to set up AutoRoute for my Flutter app. it is pretty simple and I haven’t added a lot of pages yet. However, in the pages I have made, the TextFormField doesn’t work. Whenever I tap the input field, the sceen flickers (possibly the widget rebuilding) and the keyboard shows up for a short time and then nothing happens. If I try to do the same on a page other than the route with initial: true , I get navigated to the initial page. I confirmed that it has something to do with the autoroute because if i remove it from the app the fields start working properly. I also added buttons on the pages to navigate among them. they work properly.

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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 that contains the input fields I created:

@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
                    ),)
            ],
          ),
        ),
      ),
    );
  }
}

My custom input widget just in case someone needs to take a look. I think there isnt an issue with it since even a plain TextFormField widget is not working:

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
                
              ),
            ],
          ),
        ),
      ),
    );
  }
}


I tried adding a Form widget around the inputs, passing a key to each of them but none of them work.

>Solution :

Do not initiate AppRouter inside the build method.

From the readme of auto_route:

after you run the generator your router class will be generated, hook it up with MaterialApp.

// assuming this is the root widget of your App                 
class App extends StatelessWidget {            
  // make sure you don't initiate your router                
  // inside of the build function.                
  final _appRouter = AppRouter();            
            
  @override            
  Widget build(BuildContext context){            
    return MaterialApp.router(            
      routerConfig: _appRouter.config(),         
    );            
  }            
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading