public class OtpField

  1. Object
  2. Component
  3. Container
  4. OtpField

ImplementsAnimation, Editable, Iterable<Component>, StyleListener

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”.

Constructors

public OtpField()Builds a 6-digit numeric field – the common case.
public OtpField(int length)Builds a field of the given length, numeric only.
public OtpField(int length, boolean numericOnly)Full constructor.

Methods

public String getText()Returns the current value, in order from the first box to the last.
public void setText(String code)Sets the value, one character per box.
public void clear()Clears every box and puts the caret back in the first one, ready for a fresh code.
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.
public boolean isComplete()True when every box holds a character.
public void addCompleteListener(ActionListener l)Adds a listener fired on the edit that fills the last box.
public void removeCompleteListener(ActionListener l)Removes a previously-registered listener.
public void addDataChangedListener(DataChangedListener l)Adds a listener fired on every change to the value, not only on the one that completes it.
public void removeDataChangedListener(DataChangedListener l)Removes a previously-registered listener.
public TextField getBox(int index)Returns the box at index, which displays the character at that position.
public EditField getInputField()The field that actually holds the code and carries the one-time-code hint.
public int getLength()Returns the configured length (number of boxes).
public boolean isNumericOnly()True when the field accepts digits only.

Inherited fields

Inherited methods

From Container

encloseIn, encloseIn, initLaf, getUIManager, setUIManager, isSurface, add, addAll, add, add, add, add, add, getLeadComponent, setLeadComponent, getLeadParent, keyPressed, keyReleased, getLayout, setLayout, invalidate, setShouldLayout, setShouldCalcPreferredSize, getLayoutWidth, getLayoutHeight, applyRTL, constrainWidthWhenScrollable, constrainHeightWhenScrollable, addComponent, addComponent, addComponent, addComponent, replaceAndWait, replaceAndWait, replace, replaceAndWait, replace, createReplaceTransition, isEnabled, setEnabled, removeComponent, cancelRepaints, flushReplace, removeAll, revalidateWithAnimationSafety, revalidate, revalidateLater, forceRevalidate, clearClientProperties, paint, paintGlass, layoutContainer, isSafeArea, setSafeArea, isSafeAreaRoot, getSafeAreaRoot, setSafeAreaRoot, getComponentCount, getComponentAt, getComponentIndex, contains, scrollComponentToVisible, getClosestComponentTo, getResponderAt, getComponentAt, findDropTargetAt, pointerPressed, calcPreferredSize, paramString, refreshTheme, isScrollableX, setScrollableX, isScrollableY, setScrollableY, getSideGap, getBottomGap, setScrollable, setCellRenderer, getScrollIncrement, setScrollIncrement, findFirstFocusable, dragInitiated, fireClicked, isSelectableInteraction, getGridPosY, paintComponentBackground, getGridPosX, animateHierarchyAndWait, createAnimateHierarchy, animateHierarchy, animateHierarchyFadeAndWait, createAnimateHierarchyFade, animateHierarchyFade, animateLayoutFadeAndWait, createAnimateLayoutFadeAndWait, animateLayoutFade, createAnimateLayoutFade, animateLayoutAndWait, animateLayout, updateTabIndices, createAnimateLayout, drop, createAnimateMotion, morph, morphAndWait, animateUnlayout, animateUnlayoutAndWait, createAnimateUnlayout, getChildrenAsList, iterator, iterator

From Component

setSameSize, isSetCursorSupported, parsePreferredSize, getDefaultDragTransparency, setDefaultDragTransparency, getEditingDelegate, setEditingDelegate, getCursor, setCursor, showNativeOverlay, hideNativeOverlay, updateNativeOverlay, getNativeOverlay, getAllStyles, getSameWidth, setSameWidth, getSameHeight, setSameHeight, getX, setX, getOuterX, getInnerX, getY, setY, getOuterY, getInnerY, isVisible, setVisible, getClientProperty, stripMarginAndPadding, putClientProperty, getDirtyRegion, setDirtyRegion, isOpaque, setOpaque, getWidth, setWidth, getOuterWidth, getInnerWidth, getHeight, setHeight, getOuterHeight, getInnerHeight, isDragRegion, getDragRegionStatus, getBaseline, getBaselineResizeBehavior, getPreferredSizeStr, setPreferredSizeStr, getPreferredSize, setPreferredSize, getScrollDimension, calcScrollSize, setScrollSize, getPreferredW, setPreferredW, getPreferredH, setPreferredH, getOuterPreferredH, getInnerPreferredH, getOuterPreferredW, getInnerPreferredW, setSize, getUIID, setUIID, setUIIDFinal, setUIID, getInlineAllStyles, setInlineAllStyles, getInlineSelectedStyles, setInlineSelectedStyles, getInlineUnselectedStyles, setInlineUnselectedStyles, getInlineDisabledStyles, setInlineDisabledStyles, getInlinePressedStyles, setInlinePressedStyles, remove, getParent, getOwner, setOwner, isOwnedBy, containsOrOwns, addFocusListener, removeFocusListener, addScrollListener, removeScrollListener, getSelectCommandText, setSelectCommandText, getLabelForComponent, setLabelForComponent, focusGained, focusLost, paintBackgrounds, paintShadows, getAbsoluteX, getAbsoluteY, isInClippingRegion, paintIntersectingComponentsAbove, paintScrollbars, paintScrollbarX, getScrollOpacity, getSelectedRect, paintScrollbarY, paintComponent, paintComponent, getBorder, getScrollable, paintBackground, isScrollable, getScrollX, setScrollX, getScrollY, setScrollY, onScrollX, onScrollY, getDraggedx, getDraggedy, contains, visibleBoundsContains, hasFixedPreferredSize, getBounds, getBounds, getVisibleBounds, getVisibleBounds, isFocusable, setFocusable, onSetFocusable, resetFocusable, getTabIndex, setTabIndex, getPreferredTabIndex, setPreferredTabIndex, isTraversable, setTraversable, handlesInput, setHandlesInput, consumesRawTextInput, hasFocus, setFocus, getComponentForm, getTopLevelContainer, repaint, repaint, longKeyPress, keyRepeated, registerForAnimation, deregisterFromAnimation, getAnimationManager, getScrollAnimationSpeed, setScrollAnimationSpeed, isBlockLead, setBlockLead, isIgnorePointerEvents, setIgnorePointerEvents, isRippleEffect, setRippleEffect, getInlineStylesTheme, setInlineStylesTheme, shouldRenderComponentSelection, isHideInLandscape, setHideInLandscape, createStyleAnimation, isSmoothScrolling, setSmoothScrolling, pointerHover, stopScrollMomentum, pointerHoverReleased, pointerHoverPressed, pinch, pinchReleased, pinch, rotation, isPinchBlocksDragAndDrop, setPinchBlocksDragAndDrop, pointerDragged, getDragImage, getDragTransparency, setDragTransparency, toImage, drawDraggedImage, draggingOver, dragEnter, dragExit, addPullToRefresh, setPullToRefresh, respondsToPointerEvents, pointerDragged, isStickyDrag, pointerPressed, isDragAndDropOperation, pointerReleased, longPointerPress, pointerReleased, setVerticalScrollBounds, setHorizontalScrollBounds, isVScrollThumbGrabbed, isHScrollThumbGrabbed, isVScrollThumbHover, isHScrollThumbHover, isTensileDragEnabled, setTensileDragEnabled, getTextSelectionSupport, addDropListener, removeDropListener, addDragOverListener, removeDragOverListener, isNativeDragSource, setNativeDragSource, getNativeDragOperation, setNativeDragOperation, createNativeDragOperation, isNativeDropTarget, setNativeDropTarget, getAcceptedDropMimeTypes, setAcceptedDropMimeTypes, getAcceptedDropActions, setAcceptedDropActions, canAcceptNativeDrop, nativeDragEnter, nativeDragOver, nativeDragExit, nativeDrop, addNativeDropListener, removeNativeDropListener, addNativeDragOverListener, removeNativeDragOverListener, dragFinished, addDragFinishedListener, addStateChangeListener, removeStateChangeListener, addPointerPressedListener, addLongPressListener, addContextMenuListener, removeContextMenuListener, addMouseWheelListener, removeMouseWheelListener, addStylusListener, removeStylusListener, mouseWheel, paintRippleOverlay, removePointerPressedListener, removeLongPressListener, removeDragFinishedListener, addPointerReleasedListener, removePointerReleasedListener, addPointerDraggedListener, removePointerDraggedListener, getDragSpeed, getStyle, getPressedStyle, setPressedStyle, initUnselectedStyle, initPressedStyle, initDisabledStyle, initSelectedStyle, getUnselectedStyle, setUnselectedStyle, getSelectedStyle, setSelectedStyle, getDisabledStyle, setDisabledStyle, installDefaultPainter, requestFocus, toString, refreshTheme, refreshTheme, isDragActivated, animate, scrollRectToVisible, scrollRectToVisible, paintBorder, paintBorderBackground, isCellRenderer, isScrollVisible, setScrollVisible, setIsScrollVisible, startEditingAsync, stopEditing, isEditing, isEditable, laidOut, deinitialize, initComponent, isInitialized, setInitialized, styleChanged, getNextFocusDown, setNextFocusDown, getNextFocusUp, setNextFocusUp, getNextFocusLeft, setNextFocusLeft, getNextFocusRight, setNextFocusRight, getName, setName, initCustomStyle, deinitializeCustomStyle, isRTL, setRTL, isTactileTouch, isTactileTouch, setTactileTouch, getPropertyNames, getPropertyTypes, getPropertyTypeNames, getPropertyValue, setPropertyValue, paintLockRelease, paintLock, isSnapToGrid, setSnapToGrid, shouldBlockSideSwipe, shouldBlockSideSwipeLeft, shouldBlockSideSwipeRight, blocksSideSwipe, isFlatten, setFlatten, getTensileLength, setTensileLength, isGrabsPointerEvents, setGrabsPointerEvents, getScrollOpacityChangeSpeed, setScrollOpacityChangeSpeed, growShrink, isAlwaysTensile, setAlwaysTensile, isDraggable, setDraggable, isDropTarget, setDropTarget, isChildOf, isHideInPortrait, setHideInPortrait, getBindablePropertyNames, getBindablePropertyTypes, bindProperty, unbindProperty, getBoundPropertyValue, setBoundPropertyValue, getCloudBoundProperty, setCloudBoundProperty, getCloudDestinationProperty, setCloudDestinationProperty, getComponentState, setComponentState, setHidden, isHidden, setHidden, isHidden, announceForAccessibility, getAccessibilityText, setAccessibilityText, getSemantics, getAccessibilityNode, accessibilityChanged, accessibilityChanged, getTooltip, setTooltip

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 int
number of digits / characters (e.g. 4, 6, 8)

OtpField

public OtpField(int length, boolean numericOnly)
Full constructor.

Parameters

length int
number of digits / characters
numericOnly boolean
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 String
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 ActionListener
the listener

removeCompleteListener

public void removeCompleteListener(ActionListener l)
Removes a previously-registered listener.

Parameters

l ActionListener
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 DataChangedListener
the listener

removeDataChangedListener

public void removeDataChangedListener(DataChangedListener l)
Removes a previously-registered listener.

Parameters

l DataChangedListener
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 int
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.