从一个EditText到另一个EditText快速输入时,存在延迟问题

3
我正在尝试使用8个edittext创建PIN视图。我使用了递归函数为每个edittext添加addTextChangedListener。
我的期望是当用户在一个edittext中输入单个数字时,焦点应该移到下一个edittext,以此类推。但问题是当用户快速输入数字时,edittexts没有捕获到所有数字。
例如:我快速输入89898989,它只填充了888888。
请参考以下代码:
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
  }
}

布局代码:

<?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>

enter image description here

3个回答

2

我认为你可以像这样做来提高性能。此外,我认为你应该尽可能避免递归。

当你已经在LinearLayout中拥有所有视图时,无需保留所有视图的列表,尝试使用LinearLayout已经具有的属性,如children

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <LinearLayout
            android:id="@+id/editTextContainer" <--- added this line
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/editText"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText2"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText3"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText4"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText5"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText6"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText7"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />

            <EditText
                android:id="@+id/editText8"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:background="@android:color/white"
                android:focusable="true"
                android:gravity="center"
                android:inputType="number"
                android:maxLength="1"
                android:maxLines="1"
                android:textColor="@color/black" />
        </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

片段

您不需要使用countviews来跟踪您的视图。

class FirstFragment : Fragment() {

    private var _binding: FragmentFirstBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentFirstBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        binding.editTextContainer.children.first().requestFocus()
        setAfterTextChangedListener(binding.editTextContainer)
    }

    private fun setAfterTextChangedListener(editTextContainer: ViewGroup) {
        val editTexts = editTextContainer.children.toList()
        editTexts.forEachIndexed { index, view ->
            if (view is EditText) {
                view.doAfterTextChanged {
                    if (it?.isNotEmpty() == true && index + 1 != editTexts.size) {
                        editTexts[index + 1].requestFocus()
                    }
                }
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

0

你执行了 view[count].removeCallbacks {}。在你的代码中,这完全没有任何作用。我猜你认为它会移除 TextChangedListener,但实际上并不会。

而且,没有必要等待下一个视图再添加监听器。只需将它们全部添加,那么你也不需要使函数递归。因此,我建议只需像这样做:

private fun someRecursiveFunction(view: ArrayList<EditText>) {
    view.forEach {
        it.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 {
                        count++
                        view[count].requestFocus()
                    }
                }
            }

            override fun beforeTextChanged(
                s: CharSequence, start: Int,
                count: Int, after: Int
            ) {}

            override fun onTextChanged(
                s: CharSequence, start: Int,
                before: Int, count: Int
            ) {}
        })
    }
}

它在功能上应该与您的代码相同,只是它已经一次性添加了所有的监听器。虽然我不知道它是否有助于解决您的问题,但我认为这将是对您的代码的改进。


-1

不必创建那么多的editText,你可以使用这个库


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接