I am trying to create PIN View by using 8 edittext. I have used a recursive function to addTextChangedListener for each and every edittext.
So my expectation here is when user type single digit in one edittext the focus should move to next edittext and so on. So the issue that I am facing is when user type digits too fast edittexts are not catching all digits.
For Example: I type 89898989 quickly It only fills up with 888888
Consider my following code
class FirstFragment : Fragment() {
private var _binding: FragmentFirstBinding? = null
private val binding get() = _binding!!
var count = 0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentFirstBinding.inflate(inflater, container, false)
val views = arrayListOf(
_binding!!.textView,
_binding!!.textView2,
_binding!!.textView3,
_binding!!.textView4,
_binding!!.textView5,
_binding!!.textView6,
_binding!!.textView7,
_binding!!.textView8
)
views.first().requestFocus()
someRecursiveFunction(views)
return binding.root
}
private fun someRecursiveFunction(view: ArrayList<EditText>) {
view[count].addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
if (view[count].text.toString().length == 1) {
if (count == view.size - 1) {
Toast.makeText(context, "Reached last digit", Toast.LENGTH_SHORT).show()
return
} else {
view[count].removeCallbacks {}
count++
view[count].requestFocus()
someRecursiveFunction(view)
}
}
}
override fun beforeTextChanged(
s: CharSequence, start: Int,
count: Int, after: Int
) {}
override fun onTextChanged(
s: CharSequence, start: Int,
before: Int, count: Int
) {}
})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Layout code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/textView"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:maxLength="1"
android:gravity="center"
android:inputType="number"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView2"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:maxLength="1"
android:gravity="center"
android:inputType="number"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView3"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView4"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView5"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView6"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView7"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
<EditText
android:id="@+id/textView8"
android:background="@android:color/white"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:focusable="true"
android:maxLines="1"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textColor="@color/black"
android:layout_width="40dp"
android:layout_height="40dp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

You do
view[count].removeCallbacks {}. This does absolutely nothing in your code. I suppose you think it removes the TextChangedListener, but it doesn't.There's also no need to wait with adding the listener to the next views. Just add them all, then you also don't need to make the function recursive. So I propose to just do something like this:
it should functionally work the same as your code, except that it already adds all listeners at once. Although I don't know if it helps with your problem, I do think it would be an improvement on your code.