Edit text for OTP with Each letter in separate positions

After all of these answers, I didn’t find what I wanted as considering the UI/UX, the deletion of element was flawed in such a way that to go back to previous EditText, current EditText should not be empty.

Here’s the solution I’ve implemented in Kotlin which works for Deletion by the Delete Key, pressed on the keyboard. Also, the delete function is implemented as such that when the current EditText is empty and Delete key is pressed, it switches back to previous EditText and delete its element also.

GIF showing the implementation

  1. Call the functions as such:

    //GenericTextWatcher here works only for moving to next EditText when a number is entered
    //first parameter is the current EditText and second parameter is next EditText
    editText1.addTextChangedListener(GenericTextWatcher(editText1, editText2))
    editText2.addTextChangedListener(GenericTextWatcher(editText2, editText3))
    editText3.addTextChangedListener(GenericTextWatcher(editText3, editText4))
    editText4.addTextChangedListener(GenericTextWatcher(editText4, null))
    
    //GenericKeyEvent here works for deleting the element and to switch back to previous EditText
    //first parameter is the current EditText and second parameter is previous EditText
    editText1.setOnKeyListener(GenericKeyEvent(editText1, null))
    editText2.setOnKeyListener(GenericKeyEvent(editText2, editText1))
    editText3.setOnKeyListener(GenericKeyEvent(editText3, editText2))
    editText4.setOnKeyListener(GenericKeyEvent(editText4,editText3))
    
  2. Now, paste these two classes in your current class

    class GenericKeyEvent internal constructor(private val currentView: EditText, private val previousView: EditText?) : View.OnKeyListener{
        override fun onKey(p0: View?, keyCode: Int, event: KeyEvent?): Boolean {
            if(event!!.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_DEL && currentView.id != R.id.editText1 && currentView.text.isEmpty()) {
                //If current is empty then previous EditText's number will also be deleted
                previousView!!.text = null 
                previousView.requestFocus()
                return true
            }
            return false
        }
    
    
    }
    
    class GenericTextWatcher internal constructor(private val currentView: View, private val nextView: View?) : TextWatcher {
        override fun afterTextChanged(editable: Editable) { // TODO Auto-generated method stub
            val text = editable.toString()
            when (currentView.id) {
                R.id.editText1 -> if (text.length == 1) nextView!!.requestFocus()
                R.id.editText2 -> if (text.length == 1) nextView!!.requestFocus()
                R.id.editText3 -> if (text.length == 1) nextView!!.requestFocus()
                //You can use EditText4 same as above to hide the keyboard
            }
        }
    
        override fun beforeTextChanged(
            arg0: CharSequence,
            arg1: Int,
            arg2: Int,
            arg3: Int
        ) { // TODO Auto-generated method stub
        }
    
        override fun onTextChanged(
            arg0: CharSequence,
            arg1: Int,
            arg2: Int,
            arg3: Int
        ) { // TODO Auto-generated method stub
        }
    
    }
    

Further, to disable the visible cursor, you can either use android:cursorVisible="false" in your EditText tag in the Layout or can use the java function setCursorVisible(false).

Edit: I’m using stock widget EditTexts so if you want to display a box around them, just create a drawable layout and set it as background of EditTexts and give them a padding of 5dp. This will create a box and will make it look cooler.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)