Building a Custom OTP Input Field in Jetpack Compose
Tags: jetpack, otp, tutorial, learning
Published: 2024-05-07 13:19:02

A one-time password (OTP), a dynamic password, a one-time PIN, or OTAC, is a unique code valid for a single login session. A 4- or 6-digit code is typically sent via SMS; OTPs are central to implementing two-factor authentication. 

Adding OTP support to mobile apps means creating a specialized UI input field to handle these codes.  

Since Jetpack Compose is Android's modern UI toolkit, exploring how to build a custom OTP input field using **BasicTextField** offers valuable insights. 

![OTP Verification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vci725ynp7pcjawkxszp.png)
## Custom OTP Input with Compose UI 
Compose UI simplifies creating input fields. While the built-in TextField adheres to Material Design for convenience, it lacks customization flexibility. For a custom OTP input, the lower-level BasicTextField component is ideal. This offers the freedom to tailor the input field to your specific requirements. 
### Implementation 
To create a BasicTextField that accepts only numerical input, follow these steps: 
First, we must configure the **keyboardOptions** parameter: Set the **keyboardType** property within **keyboardOptions** to **KeyboardType.NumberPassword.** This ensures that the keyboard displays only digits. 
### Explanation 
**KeyboardType.NumberPassword** is used instead of **KeyboardType.Number** to prevent the inclusion of non-numeric characters (like periods, commas, and dashes) in the input field, simplifying the user experience for scenarios like OTP entry. 

![Custom OTP feild](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xj19eypm2ukxlctvis3.gif)
The next task on our agenda is to tighten the restrictions on our input field. Since our OTP needs to consist of precisely six digits, we must ensure that the input field can only accept a maximum of six digits and prevent users from entering more than that. 

To enforce this restriction, we'll need to modify our **onValueChange** behavior to include an additional check for the length of the new string. If the new string exceeds six characters, we won't update our **otpValue.** This way, any attempt by the user to input a seventh character will be disregarded. 


![Custom OTP Coding - Tapp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22l0co9md5ohe8nlqk5j.gif)

While the initial implementation provides basic functionality, the OTP input field lacks visual clarity. To guide the user, we'll create the appearance of six distinct input boxes, enhancing usability during this crucial authorization step. 

One might consider using six individual **TextField** elements, but this approach is overly complex and would hinder smooth cursor transitions. Instead, we'll leverage the **decorationBox** parameter of **BasicTextField**. This allows us to customize the input field's appearance extensively. 

The **decorationBox** provides access to the **innerTextField**, enabling us to modify its visual representation directly. We'll replace the standard **BasicTextField** with a custom design tailored to the OTP format. 
##OTP decorationBox
The core idea is to use the **decorationBox** to customize the appearance of our **OTP** input field. In this example, we'll create six Text composables with rounded borders to display individual **OTP** characters. 

We'll employ a Row composable with the repeat function six times to generate the six **Text** components. Spacers will be inserted between them to match a typical six-digit OTP format. 

Additionally, we must ensure that the correct **OTP** digits are displayed within their corresponding **Text** components. We'll use the index information from the repeat function to extract the appropriate character from the input string. So, to handle cases where the input string is less than six characters, we'll pass empty strings to the unfilled **Text** components.  

![OTP DecorationBox](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fqylldl7sjg99atk2td.gif)
The current solution is effective, but we can enhance it with a visual indicator highlighting the active input field. Here's how: 

- **Determine the focused field:** The index of the currently focused field corresponds to the length of the existing OTP input. 
- **Emphasize the field:** To indicate focus visually, adjust the border of the active field. Increase its width and/or darken its color to clearly distinguish it. 

**Key Considerations: **
- **Visual consistency:** Ensure the highlighting style aligns with your overall UI design. 
- **Accessibility: **Consider users with visual impairments and provide alternative cues if necessary. 


**_It's done! _**

### Final Words 
Our goal was to demonstrate how to create a custom OTP input field. We hope you found the explanations helpful and can apply these concepts to tailor your OTP input solutions. 

Please find the complete and refactored source code in this GitHub repository
{% embed https://github.com/banmarkovic/OtpTextField %}