Android自定义TextInputLayout提示文本与占位文本重叠问题
自定义ABCTextInputLayout焦点状态下前后台切换导致Hint与Placeholder重叠问题解决方案
问题描述
使用自定义ABCTextInputLayout时出现异常:布局同时设置了hint和placeholder文本,正常场景下EditText获取焦点时hint会上浮,placeholder显示在输入框内;但当EditText处于焦点状态时,应用退至后台再回到前台,会出现hint与placeholder文本重叠的情况(效果如图:Hint与Placeholder重叠效果)。
对应的XML布局代码片段:
<com.deliverysdk.core.ui.ABCTextInputLayout android:id="@+id/et_mobile_input_layout" android:layout_width="match_parent" android:layout_height="56dp" android:layout_marginTop="16dp" android:clickable="true" android:focusable="true" android:hint="@string/app_global_user_info_profile_mobile_num_txt" app:hintTextAppearance="@style/TextInputLayoutHintText" app:hintTextColor="@color/global_mine_shaft_600" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:placeholderTextAppearance="@style/TextInputLayoutPlaceHolderText"> <com.deliverysdk.core.ui.GPEditText android:id="@+id/et_mobile" android:layout_width="match_parent" android:layout_height="wrap_content" android:imeOptions="actionSend" android:importantForAutofill="no" android:inputType="phone" android:nextFocusDown="@id/et_email" android:singleLine="true" app:glb_et_error_text_view="@id/tv_phone_error" app:glb_et_input_layout="@id/et_mobile_input_layout" app:glb_et_prefix_color="@color/global_mine_shaft_500" app:glb_et_type="clear_text" /> </com.deliverysdk.core.ui.ABCTextInputLayout>
解决方案
1. 重写ABCTextInputLayout的生命周期方法,恢复焦点状态UI逻辑
自定义View在前后台切换时,可能未正确恢复焦点状态下的UI状态。可以在ABCTextInputLayout中重写onWindowFocusChanged方法,判断EditText焦点状态并强制刷新布局逻辑:
@Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); if (hasWindowFocus && getEditText() != null && getEditText().hasFocus()) { // 调用内部hint上浮逻辑(需根据ABCTextInputLayout实际实现调整) updateHintState(true); // 刷新placeholder显示状态 updatePlaceholderVisibility(); } }
2. 宿主页面生命周期监听,手动触发状态刷新
若无法修改ABCTextInputLayout源码,可在宿主Activity/Fragment的onResume方法中,通过重新触发焦点来修复状态:
@Override protected void onResume() { super.onResume(); ABCTextInputLayout inputLayout = findViewById(R.id.et_mobile_input_layout); GPEditText editText = findViewById(R.id.et_mobile); if (editText.hasFocus()) { // 先清除再重新获取焦点,触发内部UI逻辑更新 editText.clearFocus(); editText.requestFocus(); } }
3. 完善ABCTextInputLayout的状态保存与恢复逻辑
检查自定义View的onSaveInstanceState和onRestoreInstanceState方法,确保hint位置、placeholder可见性等状态被正确保存和恢复:
@Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.isHintFloated = this.isHintFloated; // 假设内部存在该状态变量 savedState.isPlaceholderVisible = this.isPlaceholderVisible; return savedState; } @Override protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState savedState = (SavedState) state; super.onRestoreInstanceState(savedState.getSuperState()); // 恢复状态 this.isHintFloated = savedState.isHintFloated; this.isPlaceholderVisible = savedState.isPlaceholderVisible; // 根据恢复的状态更新UI updateHintAndPlaceholder(); } static class SavedState extends BaseSavedState { boolean isHintFloated; boolean isPlaceholderVisible; SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); isHintFloated = in.readByte() != 0; isPlaceholderVisible = in.readByte() != 0; } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeByte((byte) (isHintFloated ? 1 : 0)); out.writeByte((byte) (isPlaceholderVisible ? 1 : 0)); } public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; }
总结
该问题本质是自定义ABCTextInputLayout在前后台切换时,未正确恢复焦点状态下的UI布局逻辑。优先推荐修改自定义View源码完善生命周期状态处理;若无法修改源码,可通过宿主页面生命周期方法手动触发状态刷新。
内容的提问来源于stack exchange,提问作者Zafar Imam
相关产品推荐
相关产品推荐

