Android Java登录页EditText仅显单个字符问题排查求助
Android 9/8设备EditText输入异常问题分析
问题现象
- 部分Android 9和8设备上,用户名输入框仅能显示单个字符,输入第二个字符时第一个会消失
- 光标移至左侧输入时,字符串反转显示(如输入hello显示olleh)
- 密码输入框功能完全正常
布局与代码示例
用户名输入框布局
<com.google.android.material.textfield.TextInputLayout android:id="@+id/userWrapper" style="@style/MessageError" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_marginTop="2dp" android:textAlignment="center" android:layout_marginBottom="5dp" android:gravity="center_horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:layout_width="300dp" android:layout_height="wrap_content" android:id="@+id/user_edit_text" android:hint="Name" android:background="@drawable/custom_input" android:padding="10dp" android:paddingStart="20dp" /> <ImageButton android:id="@+id/clean" android:layout_width="35dp" android:layout_height="35dp" android:layout_alignParentRight="true" android:src="@drawable/ic_baseline_cancel_24" android:layout_centerVertical="true" android:layout_marginTop="2dp" android:layout_marginLeft="-40dp" android:background="@color/white_with_alpha" android:onClick="cleanText" android:visibility="gone" android:text="Button"/> </LinearLayout> </com.google.android.material.textfield.TextInputLayout>
密码输入框布局
<com.google.android.material.textfield.TextInputLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/passwordWrapper" style="@style/MessageError" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:gravity="center_horizontal" android:textAlignment="center" android:layout_marginTop="0dp" app:passwordToggleDrawable="@drawable/ic_password_visibility_selector" app:passwordToggleEnabled="true" app:passwordToggleTint="@color/grey" > <EditText android:layout_width="300dp" android:layout_height="wrap_content" android:id="@+id/password_edit_text" android:layout_below="@+id/login" android:layout_marginTop="-10dp" android:hint="mot de passe" android:inputType="numberPassword" android:drawableEnd="@drawable/ic_eye_password" android:background="@drawable/custom_input_v3" android:padding="10dp" android:paddingStart="15dp" /> </com.google.android.material.textfield.TextInputLayout>
字符处理的TextWatcher代码
class myTextWatcher implements TextWatcher { int first = 0; int second; @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void afterTextChanged(Editable editable) { second = first; first = editable.length(); if(TextUtils.isEmpty(editable.toString())){ clean.setVisibility(View.GONE); }else{ clean.setVisibility(View.VISIBLE); } if(editable.length() == 5 && first>second){ user_edit_text.append("."); } if(editable.length() == 5 && second>first){ String newString = editable.toString(); user_edit_text.setText(newString.substring(0,newString.length()-1)); } } }
问题根源
- TextWatcher循环回调导致文本状态混乱
在afterTextChanged里直接调用user_edit_text.append()或setText(),会再次触发TextWatcher的回调,形成循环。Android 8/9的EditText系统实现对这种循环的兼容性较差,会引发字符覆盖、光标位置计算错误,最终出现输入字符消失、文本反转的问题。 - 状态判断逻辑不严谨
用first和second两个变量判断输入/删除操作的逻辑太粗糙,无法应对光标位置变化的场景,比如用户在文本中间输入或删除时,会错误触发文本修改逻辑,导致显示异常。 - 布局对齐属性冲突
用户名输入框嵌套在LinearLayout中,同时TextInputLayout设置了textAlignment="center"和gravity="center_horizontal",这些属性和EditText自身的文本对齐逻辑冲突,在部分系统版本中干扰了光标位置的计算,加重了输入异常。
修复建议
1. 重构TextWatcher,避免循环回调
直接操作Editable对象,添加锁防止循环触发,同时优化操作判断逻辑:
class myTextWatcher implements TextWatcher { private boolean isUpdating = false; private int lastLength = 0; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void afterTextChanged(Editable editable) { if (isUpdating) return; isUpdating = true; // 控制清除按钮显示 clean.setVisibility(TextUtils.isEmpty(editable) ? View.GONE : View.VISIBLE); int currentLength = editable.length(); // 输入时添加点 if (currentLength == 5 && currentLength > lastLength) { editable.append("."); // 手动设置光标到末尾 user_edit_text.setSelection(editable.length()); } // 删除时移除点 else if (currentLength == 4 && currentLength < lastLength) { if (editable.length() > 0 && editable.charAt(editable.length() - 1) == '.') { editable.delete(editable.length() - 1, editable.length()); } } lastLength = currentLength; isUpdating = false; } }
2. 调整布局,移除冲突属性
移除嵌套的LinearLayout,把EditText直接放在TextInputLayout内,同时去掉TextInputLayout上的对齐属性,改用EditText自身的gravity设置文本对齐:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/userWrapper" style="@style/MessageError" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_marginTop="2dp" android:layout_marginBottom="5dp"> <EditText android:id="@+id/user_edit_text" android:layout_width="300dp" android:layout_height="wrap_content" android:hint="Name" android:background="@drawable/custom_input" android:padding="10dp" android:paddingStart="20dp" android:gravity="start"/> <ImageButton android:id="@+id/clean" android:layout_width="35dp" android:layout_height="35dp" android:layout_alignParentRight="true" android:src="@drawable/ic_baseline_cancel_24" android:layout_centerVertical="true" android:layout_marginTop="2dp" android:layout_marginLeft="-40dp" android:background="@color/white_with_alpha" android:onClick="cleanText" android:visibility="gone" android:text="Button"/> </com.google.android.material.textfield.TextInputLayout>
内容的提问来源于stack exchange,提问作者Sed9dn
相关产品推荐
相关产品推荐

