Flutter input widget with @ mention functionality

CodeWithFlutter
3 Min Read

To implement an input widget with @ mention functionality in Flutter, you can use a TextField widget and listen to the TextEditingController for changes. You can then parse the text and check if an @ symbol is followed by any characters, and if so, display a list of suggestions to the user.

Here’s an example implementation:

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController _controller;
  final List<String> _suggestions = ['John', 'Jane', 'Jim', 'Jill'];
  String _mention;
  List<String> _filteredSuggestions;

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
    _controller.addListener(() {
      setState(() {
        final text = _controller.text;
        final index = text.lastIndexOf('@');
        if (index >= 0 && index < text.length - 1) {
          final mention = text.substring(index + 1);
          if (mention != _mention) {
            _mention = mention;
            _filteredSuggestions = _suggestions
                .where((name) => name.startsWith(_mention))
                .toList();
          }
        } else {
          _mention = null;
          _filteredSuggestions = null;
        }
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: [
            TextField(
              controller: _controller,
              decoration: InputDecoration(hintText: 'Enter text with @ mentions'),
            ),
            if (_mention != null)
              Expanded(
                child: ListView.builder(
                  itemCount: _filteredSuggestions.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(_filteredSuggestions[index]),
                      onTap: () {
                        final mention = _filteredSuggestions[index];
                        final text = _controller.text;
                        final index = text.lastIndexOf('@');
                        _controller.value = TextEditingValue(
                          text: text.substring(0, index + 1) + mention,
                          selection: TextSelection.collapsed(
                            offset: text.length,
                          ),
                        );
                      },
                    );
                  },
                ),
              ),
          ],
        ),
      ),
    );
  }
}

In this example, the TextEditingController is used to listen for changes to the text in the TextField, and the suggestions are filtered based on the entered text. The filtered suggestions are displayed in a ListView below the TextField.

Share this Article
Leave a comment