Class OtpField

All Implemented Interfaces:
Animation, Editable, StyleListener, Iterable<Component>

public class OtpField extends Container

Segmented one-time-code input -- one box per digit, with a caret that walks from box to box as the code is typed. The standard entry screen for an SMS or authenticator code, and the second half of phone number verification.

Example
OtpField otp = new OtpField(6);
otp.addCompleteListener(e -> verify(otp.getText()));
form.add(otp);
Receiving the code from the SMS

The field carries TextArea#ONE_TIME_CODE, so the platform offers the code from the incoming message by itself: on iOS the keyboard's suggestion bar shows it above the keys, on Android the autofill service offers it on the field. Accepting it fills every box at once. The application reads no messages and asks for no messaging permission -- it only says what the field is for, and the platform does the rest. A platform that cannot offer the code is unaffected, and the code is typed.

This is why the boxes are drawn rather than being separate editors. A code arrives as one value, and a row of one-character fields can only receive one character of it. Behind the boxes is a single field holding the whole code, so an offered code, a paste and a keyboard all land the same way.

Styling

Each box uses the UIID "OtpDigit" and the field itself uses "OtpField".

  • Constructor Details

    • OtpField

      public OtpField()
      Builds a 6-digit numeric field -- the common case.
    • OtpField

      public OtpField(int length)

      Builds a field of the given length, numeric only.

      Parameters
      • length: number of digits / characters (e.g. 4, 6, 8)
    • OtpField

      public OtpField(int length, boolean numericOnly)

      Full constructor.

      Parameters
      • length: number of digits / characters

      • numericOnly: true to restrict input to digits; false to allow any character (alphanumeric codes are sometimes used)

  • Method Details

    • getText

      public String getText()
      Returns the current value, in order from the first box to the last. A partial entry returns a shorter string.
    • setText

      public void setText(String code)

      Sets the value, one character per box. Excess characters are dropped, as are characters this field does not accept; a shorter string leaves the remaining boxes empty.

      Parameters
      • code: the value, or null to clear
    • clear

      public void clear()
      Clears every box and puts the caret back in the first one, ready for a fresh code.
    • startEditing

      public void startEditing()
      Focuses the field and opens the keyboard, so a verification screen can put the user straight into the code without a tap.
    • isComplete

      public boolean isComplete()
      True when every box holds a character.
    • addCompleteListener

      public void addCompleteListener(ActionListener l)

      Adds a listener fired on the edit that fills the last box. Useful to verify the code without a submit button.

      Parameters
      • l: the listener
    • removeCompleteListener

      public void removeCompleteListener(ActionListener l)

      Removes a previously-registered listener.

      Parameters
      • l: the listener
    • addDataChangedListener

      public void addDataChangedListener(DataChangedListener l)

      Adds a listener fired on every change to the value, not only on the one that completes it.

      Parameters
      • l: the listener
    • removeDataChangedListener

      public void removeDataChangedListener(DataChangedListener l)

      Removes a previously-registered listener.

      Parameters
      • l: the listener
    • getBox

      public TextField getBox(int index)

      Returns the box at index, which displays the character at that position. Useful for theming an individual box; the value itself is read and written through #getText() / #setText(String), since a code is entered into the field as a whole rather than box by box.

      Parameters
      • index: the box position, from 0
      Returns

      the box at that position

    • getInputField

      public EditField getInputField()
      The field that actually holds the code and carries the one-time-code hint. It spans the boxes and draws only the caret. Exposed for the cases the boxes cannot serve: adding a done listener, or reading the caret.
    • getLength

      public int getLength()
      Returns the configured length (number of boxes).
    • isNumericOnly

      public boolean isNumericOnly()
      True when the field accepts digits only.