78

I am new in Flutter. I am looking for TextField value to always uppercase but I did not find any resource on that.

Another issue is the TextField onChanged event debounce implementation. When I type on TextField it immediately fires onChanged event which is not suitable for my goal. The onChange event will fire after 500ms on every text changed.

 new TextField(
         controller: _controller,
         decoration: new InputDecoration(
              hintText: 'Search here',
         ),
         onChanged: (str) {
            //need to implement debounce
         }
)
Harun
  • 1,137
  • 1
  • 9
  • 7

15 Answers15

219

Works on Android, iOS, Web, macOS, Windows and Linux

You can implement a custom TextInputFormatter

class UpperCaseTextFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    return TextEditingValue(
      text: newValue.text.toUpperCase(),
      selection: newValue.selection,
    );
  }
}

Usage:

TextField(
  inputFormatters: [
    UpperCaseTextFormatter(),
  ]
)

Full example

Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 10
    I don't know why this solution doesn't have more upvotes. From what I can tell, this is the correct way to implement automatic uppercase formatting (or any kind of text field formatting). – Abion47 Mar 18 '19 at 19:33
  • Hey you don't actually need to implement the textinputformater if you just need in one specific place, take a look at my answer on how to use it without extending TextInputFormatter – Diego Garcia Apr 09 '20 at 13:42
  • 2
    This answer causing an error when enabled AutoCorrect in the Keyboard (it is appending OldValue with NewValue). Ex: I wanted to type KEYBOARD: 1st letter type K, 2nd letter type E, now it replaces with KKE and so on letter by letter typing it is appending OldValue with NewValue. – rjkolli7 Mar 01 '21 at 19:57
  • @rjkolli I'm unable to reproduce your problem. This solution seems to work. – Ian Mar 25 '21 at 13:02
  • @rjkolli yeah looks like you are right, I am also facing the same issue on some android devices. – Anas Iqbal May 21 '21 at 10:46
  • 1
    Perfect. `textCapitalization: TextCapitalization.characters,` doesnt work on windows so this a great solution. – West Jul 27 '21 at 04:53
  • how about capitalize each word ? – Rohmatul Laily Jul 30 '21 at 07:53
  • and `textCapitalization` dosent work on other language keyboard @West – noveleven Aug 12 '21 at 09:47
  • after using this keyboard switching issue is happening. – satish Sep 21 '21 at 07:50
  • 2
    This solution is running up against a new Android keyboard issue. It's appending, not replacing. Needs an update. – jbryanh Oct 11 '21 at 20:02
  • The question was about "uppercase & debounce". This is a partial answer, that only addresses the uppercase, without a debounce. – tim-montague Dec 26 '21 at 01:55
  • I do this together with textCapitalization: TextCapitalization.characters - then it works on all platforms and also displays the keyboard with capital letters – Nils Tierecke Feb 23 '22 at 18:13
  • I have the same problem on Android using this solution @rjkolli. I had to go to the `textCapitalization: TextCapitalization.characters`solution for now and add a toUppercase to the value passed on my onChanged method. – Geoffrey Escobedo Apr 20 '22 at 13:09
  • 1
    Caution! This solution is not working correctly with backspace on newer Android devices. It allows removing only one char and then stops! This fixes it: https://stackoverflow.com/a/68556182/2734478 – Roval May 23 '22 at 06:07
110

Perhaps using textCapitalization: TextCapitalization.characters in the TextField could help you? Although this would capitalize the characters while something is being typed as well.

TextField(
    textCapitalization: TextCapitalization.sentences,
)
Hejazi
  • 16,587
  • 9
  • 52
  • 67
petras J
  • 2,538
  • 3
  • 16
  • 23
  • @praveenb does the textCapitalization.sentences does not work completely while typing in textfield or the value fails to be capitalized? p.s. Each sentence's first word only is capitalized and it's activated after each full stop ( . ) . – petras J Oct 26 '18 at 09:10
  • 1
    yes my mistake... I see if i Enter text in Textfield then its get capitalised. Previously, i prepopulated text for which capitalisation not worked. I thought it should. Thanks for clarification :) – praveenb Oct 30 '18 at 06:22
52

You can use textCapitalization property of a TextField widget. Also do take a reference for detailed API info here Text Capitalization Official API

Illustration as follow

Example 1

 TextField(
        initialValue: flutter code camp
        textCapitalization: TextCapitalization.characters,
    )// OUTPUT : FLUTTER CODE CAMP

Example 2

 TextField(
        initialValue: flutter code camp
        textCapitalization: TextCapitalization.words,
    )// OUTPUT : Flutter Code Camp

Example 3

 TextField(
        initialValue: flutter code camp
        textCapitalization: TextCapitalization.sentences,
    )// OUTPUT : Flutter code camp

Example 4

 TextField(
        initialValue: flutter code camp
        textCapitalization: TextCapitalization.none,
    )// OUTPUT : flutter code camp
Divyanshu Kumar
  • 1,272
  • 15
  • 15
28

Everything you need to do is:

After String put .toUpperCase()

Example: "Some text".toUpperCase()

This worked in my case. I am new too, so I hope I helped.

Grant Miller
  • 27,532
  • 16
  • 147
  • 165
  • 3
    this is about a text input field. there is no string that you could alter. the given text is retrieved via TextEditingController which should be then used to modify the text in the field at every keystroke. I dont think thats possible. – Daniel Leiszen Aug 13 '20 at 17:30
19

You can use TextCapitalization.characters to make all typed characters UPPERCASE

TextField(
    textCapitalization: TextCapitalization.characters,
)
felangga
  • 553
  • 8
  • 22
9

@Günter-Zöchbauer's solution works but when you switch into the numeric keyboard on Android, if you type one, it'll switch into the letters keyboard again.

This is because you're setting a new TextEditingValue every time.

Instead, if you copy the newest one and change the text, it works:

import 'package:flutter/services.dart';

class UpperCaseTextFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    return newValue.copyWith(text: newValue.text.toUpperCase());
  }
}
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
  • 1
    Although this solution still prints a `Composing region changed by the framework. Restarting the input method.` in the console, the issue with numeric keyboards (and also holding backspace) is resolved with this. Thanks! – Bruno Kinast Feb 14 '23 at 14:29
7

The easiest way to do it is to add the onChanged event of the TextField and convert to uppercase using the controller of the TextField just like the above:

TextField(
          controller: controllerReservation,
          onChanged: (value) {               
            controllerReservation.value = 
               TextEditingValue(
                                text: value.toUpperCase(), 
                                selection: controllerReservation.selection);
          },
        )
Diego Garcia
  • 1,134
  • 1
  • 12
  • 25
7

TextField has a textCapitalization property that you can use to capitalize words Sentences or characters

if you want to capitalize the entire value of your text input use

TextField(
  textCapitalization: TextCapitalization.characters,
 )
John Bryan
  • 151
  • 2
  • 4
  • Im not able to post full code in comments but if you have a simple flutter app and throw in a textfield you can easily verify this on flutter desktop – West Aug 09 '21 at 01:53
2

Here is how you achieve Debounce (or delay) effect on input text:

1) Import package

rxdart: ^0.18.1 (or whatever the version will be)

2) In your Stateful Widget declare following

final subject = new PublishSubject<String>();

3) In the same Stateful Widget, declare the following under initState method

subject.stream
    .debounce(new Duration(milliseconds: 500))
    .listen(_loadNewData);

4) In the same Stateful Widget, create the following method (that will be fired after 500 ms)

  void _loadNewData(String newData) {
    //do update here
  }

4) Add the following line to your Textfield Widget (you can get rid of Controller now)

onChanged: (string) => (subject.add(string)),
Robert J.
  • 2,631
  • 8
  • 32
  • 59
1
TextField(
  controller: textController,
    onChanged: (value) {
      if (textController.text != value.toUpperCase())
        textController.value = textController.value.copyWith(text: value.toUpperCase());
  },
)
David Araujo
  • 156
  • 2
  • 5
1

Add this to your TextFormField

 inputFormatters: [UpperCaseTextFormatter()],
 textCapitalization: TextCapitalization.characters,

Full code

  TextFormField(
      autofillHints: [AutofillHints.name],
      inputFormatters: [UpperCaseTextFormatter()],
      textCapitalization: TextCapitalization.characters,
      textInputAction: TextInputAction.next,
      style: TextStyle(fontSize: 20),
      decoration: InputDecoration(
      contentPadding: EdgeInsets.symmetric(
      horizontal: 0, vertical: 0),
      labelText: "Hello World",
      hintText: '',
    ),
 ),
Anand
  • 4,355
  • 2
  • 35
  • 45
0

Here's simple approach to type in CAPS ON

 textCapitalization: TextCapitalization.characters,

Easy!

Apoorv Pandey
  • 2,118
  • 2
  • 11
  • 13
0

Here we have Two method available for TextFormField widget

  1. Use textCapitalization sample code below (consider it is a common widget so, certain conditions there)
  textCapitalization: widget.isCapitalize == true
        ? TextCapitalization.characters
        : TextCapitalization.none,
  1. This method achieve with controller and onChanged(value) event (consider it is a common widget so, certain conditions there)
onChanged: (value) {
      if (widget.controller.text != value.toUpperCase() &&
          widget.isCapitalize == true) {
        widget.controller.value =
            widget.controller.value.copyWith(text: value.toUpperCase());
      }
    },
Rahul Raj
  • 1,010
  • 9
  • 10
-1

Here is a util class that can help with it:

 class TextCapitalizationFormatter extends TextInputFormatter {
      final TextCapitalization capitalization;

  TextCapitalizationFormatter(this.capitalization);

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    String text = '';

    switch (capitalization) {
      case TextCapitalization.words:
        text = capitalizeFirstofEach(newValue.text);
        break;
      case TextCapitalization.sentences:
        List<String> sentences = newValue.text.split('.');
        for (int i = 0; i < sentences.length; i++) {
          sentences[i] = inCaps(sentences[i]);
          print(sentences[i]);
        }
        text = sentences.join('.');
        break;
      case TextCapitalization.characters:
        text = allInCaps(newValue.text);
        break;
      case TextCapitalization.none:
        text = newValue.text;
        break;
    }

    return TextEditingValue(
      text: text,
      selection: newValue.selection,
    );
  }

  /// 'Hello world'
  static String inCaps(String text) {
    if (text.isEmpty) {
      return text;
    }
    String result = '';
    for (int i = 0; i < text.length; i++) {
      if (text[i] != ' ') {
        result += '${text[i].toUpperCase()}${text.substring(i + 1)}';
        break;
      } else {
        result += text[i];
      }
    }
    return result;
  }

  /// 'HELLO WORLD'
  static String allInCaps(String text) => text.toUpperCase();

  /// 'Hello World'
  static String capitalizeFirstofEach(String text) => text
      .replaceAll(RegExp(' +'), ' ')
      .split(" ")
      .map((str) => inCaps(str))
      .join(" ");
}

Usage:

TextField(
  inputFormatters: [
    TextCapitalizationFormatter(TextCapitalization.sentences),
  ]
)
Cícero Moura
  • 2,027
  • 1
  • 24
  • 36
-1

This works on every platform:

TextEditingController mytext = TextEditingController();
TextField(
  controller: mytext,
  onChanged: (value) {
    mytext.value = TextEditingValue(
      text: value.toUpperCase(), 
      selection: mytext.selection,
    );
  },
)