0

After reviewing this article from this Flutter issue (regarding to identify when back key is pressed to work with a pin alike widget)

I've been trying to add the \u200b special character as suggested in the article, but it is always taking it as a String with of length 6.

How can I work with it to place a \u200b Unicode character in the TextEditingController and make it work?

This is what the article suggests:

Take whatever content you want in your TextEditingController and place a \u200b unicode character at the front of that text. When the user deletes all of your content, the text field looks empty, but there is single remaining \u200b character. When the user presses “delete” one more time, your TextEditingController receives a change event, and the text in your TextEditingController goes from a length of 1 to a length of 0. Now you know that the user pressed “delete” in an “empty” text field and you can take whatever action you want as a developer.

Ken White
  • 123,280
  • 14
  • 225
  • 444
Carlos Daniel
  • 2,459
  • 25
  • 30

1 Answers1

1

For adding the zero-width-space to the TextEditingController it was enough to provide "\u200b" in the initializer and when updating the value of the controller.

As for how to make this detect delete presses, you can try the code below, it have a callback onEmptyTextField which triggers when the TextEditingController's text turns empty or already is empty.

import 'package:flutter/material.dart';

const zeroWidthSpace = "\u200b";

class DetectDeleteTextField extends StatelessWidget {
  const DetectDeleteTextField({
    Key? key,
    required this.onEmptyTextField,
    required this.controller,
  }) : super(key: key);

  /// Triggered when the TextField turns/is empty, such as when the zero-width-space ("\u200b")
  /// or another character is deleted, or delete is pressed repeatedly.
  final Function() onEmptyTextField;

  final TextEditingController controller;

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
      onChanged: (text) {
        print("onChanged - Length: ${text.length}, Text runes:${text.runes.toString()}");

        // Remove the zero-width-space character, handle cursor position
        // correctly, and ensure no zero-width-space is present if text is pasted.
        if (text.length >= 2 && text.contains(zeroWidthSpace)) {
          String trimmedText = text.replaceAll(zeroWidthSpace, "");
          controller.value = TextEditingValue(
              text: trimmedText,
              selection: TextSelection.fromPosition(TextPosition(offset: trimmedText.length)),
          );
          print("Trimming - Length: ${controller.text.length}, Text runes:${controller.text.runes.toString()}");
        }

        // Trigger the callback and reset the text to the zero-width-space character.
        // The selection is needed for detecting backspace when only the
        // zero-width-space exist in the text.
        if (text.isEmpty) {
          onEmptyTextField();
          controller.value = const TextEditingValue(text: zeroWidthSpace);
          controller.selection = const TextSelection(baseOffset: 0, extentOffset: 1);
          print("After delete - Length: ${controller.text.length}, Text runes:${controller.text.runes.toString()}");
        }
      },
    );
  }
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            DetectDeleteTextField(
                controller: TextEditingController(text: zeroWidthSpace),
                onEmptyTextField: () => print("Delete triggered!")
            ),
          ],
        ),
      ),
    );
  }
}

void main() => runApp(const App());

Tested on Android and Windows.

Tor-Martin Holen
  • 1,359
  • 1
  • 13
  • 19