首页 > 解决方案 > 快速键入时将焦点从一个编辑文本更改为另一个编辑文本和另一个编辑文本时出现滞后问题

问题描述

我正在尝试使用 8 edittext 创建 PIN 视图。我使用递归函数为每个编辑文本添加TextChangedListener。

所以我的期望是当用户在一个编辑文本中键入单个数字时,焦点应该移到下一个编辑文本等等。所以我面临的问题是当用户输入数字太快时,编辑文本没有捕捉到所有数字。

例如:我快速输入 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>

在此处输入图像描述

标签: javaandroidkotlinandroid-edittextaddtextchangedlistener

解决方案


我认为你可以做这样的事情来提高性能。另外,我认为您应该尽可能避免递归。

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>

分段

您不需要也不需要count跟踪views您的视图

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

推荐阅读