Bill Farmer

Random thoughts on random subjects

Flutter app bar search widget

by Bill Farmer. Categories: Hacking .

As an exercise I decided to reimplement my Buses app in flutter. To do this I need an open street map library, a beautiful soup library, a location library, an OS ref library, and a search widget. All of these are available in pub.dev, except a suitable search widget. All implementations of SearchBar in the docs include an annoying dropdown suggestions feature, which appears to be mandatory.

BusApp

However it is possible to take the SearchBar and include it in an AppBar, change the icons and end up with something which looks and acts very similarly to an android search widget. To do this, add code to the actions of the app bar which either shows an icon button or the search bar, controlled by a boolean which is set by pressing the search button. The search bar is wrapped by an Expanded widget to stop it overflowing the display. The search bar has a leading button which dismisses it, a conditional trailing button to clear the search field and a button to do the search.

class BusApp extends StatefulWidget {
  const BusApp({super.key});
  @override
  _BusAppState createState() => _BusAppState();

class _BusAppState extends State<BusApp> {
  const controller = TextEditingController();
  bool searching = false;
  bool empty = true;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var converter = LatLongConverter();
    return Scaffold(
      appBar: AppBar(
        title: Text('BusApp'),
        actions: [
          if (searching)
          Expanded(
            child: SearchBar(
              controller: controller,
              leading: IconButton(
                icon: const Icon(Icons.arrow_back),
                onPressed: () {
                  setState(() =>
                    searching = false
                  );
                }
              ),
              trailing: [
                if (!empty)
                IconButton(
                  icon: const Icon(Icons.close),
                  onPressed: () {
                    controller.clear();
                  }
                ),
                IconButton(
                  icon: const Icon(Icons.arrow_forward_ios),
                  onPressed: () {
                    setState(() =>
                      searching = false
                    );
                  }
                ),
              ],
              hintText: 'Search…',
              onChanged: (value) {
                setState(() =>
                  empty = value.isEmpty
                );
              },
              onSubmitted: (value) {
                setState(() =>
                  searching = false
                );
                doSearch(value);
              },
            )
          )
          else
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              setState(() =>
                searching = true
              );
            }
          )
        ],
      ),
      body: // …
    );
  }
}

This seems to work quite well, although the app can be a bit slow starting on an old phone.


See Also