Skip to content

Software Development at Program Tom LTD

Place for coding, programming, development and software in general.

Menu
  • Blog
  • PDF Booklets
  • Dev Utils & Content
  • Java Spring Boot Or Web Apps
  • English
    • български
    • English
    • Español
    • Português
    • हिन्दी
    • Русский
    • Deutsch
    • Français
    • Italiano
    • العربية
  • About Us
Menu
Autocomplete input field in Flutter

Autocomplete input field in Flutter

Posted on October 19, 2025 by Toma Velev

Let’s go step by step on how to implement an autocomplete text field in Flutter without any plugins, using only built-in widgets. I’ll show you two main approaches:

  1. ✅ With preloaded items (local list) — simplest version.
  2. 🌐 With backend fetching (async suggestions) — slightly more advanced.

🧰 1. Autocomplete with Preloaded Items (Local List)

Flutter has a built-in widget: RawAutocomplete (and a higher-level wrapper: Autocomplete<T>).
Here’s a simple example:

import 'package:flutter/material.dart';

class LocalAutocompleteExample extends StatelessWidget {
  final List<String> countries = [
    'USA', 'Canada', 'Mexico', 'Germany', 'France', 'Italy', 'India', 'Japan'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Local Autocomplete')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Autocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            if (textEditingValue.text.isEmpty) {
              return const Iterable<String>.empty();
            }
            return countries.where((String option) {
              return option.toLowerCase().contains(textEditingValue.text.toLowerCase());
            });
          },
          onSelected: (String selection) {
            print('You selected: $selection');
          },
          fieldViewBuilder: (context, controller, focusNode, onFieldSubmitted) {
            return TextField(
              controller: controller,
              focusNode: focusNode,
              decoration: InputDecoration(
                labelText: 'Country',
                border: OutlineInputBorder(),
              ),
            );
          },
          optionsViewBuilder: (context, onSelected, options) {
            return Align(
              alignment: Alignment.topLeft,
              child: Material(
                elevation: 4.0,
                child: ListView.builder(
                  padding: EdgeInsets.zero,
                  shrinkWrap: true,
                  itemCount: options.length,
                  itemBuilder: (BuildContext context, int index) {
                    final String option = options.elementAt(index);
                    return ListTile(
                      title: Text(option),
                      onTap: () => onSelected(option),
                    );
                  },
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

✅ What this does:

  • Uses Flutter’s built-in Autocomplete widget.
  • Filters a local list (countries) as you type.
  • Shows suggestions in a dropdown.
  • No plugins needed. Always trive to nimize external dependencies – https://programtom.com/dev/2023/09/02/strengths-and-weaknesses-of-flutter-ai-will-not-tell-you/

🌐 2. Autocomplete with Backend Fetching (Async Suggestions)

If you want to fetch suggestions from an API as the user types, you can still use RawAutocomplete or a custom solution.
Here’s a pattern using a TextField + FutureBuilder:

import 'dart:async';
import 'package:flutter/material.dart';

class AsyncAutocompleteExample extends StatefulWidget {
  @override
  _AsyncAutocompleteExampleState createState() => _AsyncAutocompleteExampleState();
}

class _AsyncAutocompleteExampleState extends State<AsyncAutocompleteExample> {
  final TextEditingController _controller = TextEditingController();
  final FocusNode _focusNode = FocusNode();
  List<String> _suggestions = [];
  Timer? _debounce;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_onSearchChanged);
  }

  @override
  void dispose() {
    _debounce?.cancel();
    _controller.dispose();
    super.dispose();
  }

  void _onSearchChanged() {
    if (_debounce?.isActive ?? false) _debounce!.cancel();
    _debounce = Timer(const Duration(milliseconds: 300), () {
      if (_controller.text.isNotEmpty) {
        _fetchSuggestions(_controller.text);
      } else {
        setState(() => _suggestions = []);
      }
    });
  }

  Future<void> _fetchSuggestions(String query) async {
    // TODO: Replace with your real API call
    await Future.delayed(Duration(milliseconds: 500)); // simulate network delay
    setState(() {
      _suggestions = List.generate(5, (i) => "$query suggestion $i");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Async Autocomplete')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _controller,
              focusNode: _focusNode,
              decoration: InputDecoration(
                labelText: 'Search',
                border: OutlineInputBorder(),
              ),
            ),
            if (_suggestions.isNotEmpty && _focusNode.hasFocus)
              Material(
                elevation: 4,
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _suggestions.length,
                  itemBuilder: (context, index) {
                    final suggestion = _suggestions[index];
                    return ListTile(
                      title: Text(suggestion),
                      onTap: () {
                        _controller.text = suggestion;
                        setState(() => _suggestions = []);
                        _focusNode.unfocus();
                      },
                    );
                  },
                ),
              )
          ],
        ),
      ),
    );
  }
}

✅ What’s happening here:

  • A TextField listens for changes.
  • Debounce prevents too many API calls while typing.
  • _fetchSuggestions simulates a backend request (replace with your real API call).
  • Suggestions are shown below the field.
  • Tap a suggestion → fills the field and hides the list.

🧠 Pro Tips

  • Use FocusNode to hide suggestions when the field is not focused.
  • Wrap the suggestions list in a Material for proper elevation/shadow.
  • Add a Container with a max height to prevent overflow.
  • For performance, debounce your API calls as shown.

  • Feature Flags – Enable Functionality from the BackEnd
  • Integrating xAI Grok API with Spring Boot
  • How to Progresively Integrate AI
  • What is an AI Agent
  • Flutter image scaling

Categories

  • Apps (22)
  • ChatGPT (23)
  • Choosing a Framework (38)
  • Flutter (256)
  • Graphical User Interface (14)
  • Marketing (116)
  • Software Development (281)
  • Spring (44)
  • StartUp (22)
  • Uncategorized (14)
  • Uncategorized (4)
  • Vaadin (14)

Tags

Algorithms (9) crypto (29) flutterdev (39) General (86) Java (7) QR & Bar Codes (3) Software Dev Choices (33) Spring Boot (1) standards (1) Theme (3) User Authentication & Authorization (9) User Experience (10) Utilities (19) WordPress (11)

Product categories

  • All Technologies (84)
    • Flutter Apps (24)
    • GPT (4)
    • Java (38)
    • Native Android (3)
    • PHP (9)
    • Spring (Boot) / Quarkus (35)
    • Utils (15)
    • Vaadin 24+ (27)
    • Vaadin 8 (1)
  • Apps (18)
    • Employees DB (1)
    • Notes (6)
    • Personal Budget (1)
    • Recipes Book (1)
    • Stuff Organizer (1)
    • To-Do (2)
  • PDF Books (3)
  • Source Code Generators (8)

Recent Posts

  • Feature Flags – Enable Functionality from the BackEnd
  • Integrating xAI Grok API with Spring Boot
  • How to Progresively Integrate AI
  • What is an AI Agent
  • Flutter image scaling

Post Categories

  • Apps (22)
  • ChatGPT (23)
  • Choosing a Framework (38)
  • Flutter (256)
  • Graphical User Interface (14)
  • Marketing (116)
  • Software Development (281)
  • Spring (44)
  • StartUp (22)
  • Uncategorized (14)
  • Uncategorized (4)
  • Vaadin (14)