EditText嵌套TextInputLayout在API25报错:getTextBeforeCursor异常
TextInputLayout嵌套EditText在API 25上焦点丢失并报InputConnection错误
问题现象
- 在API 28及上下2个版本(API 26-30)中运行正常
- 在API 25版本中,EditText会突然失去焦点,焦点切换至
android.viewpager2.widget.ViewPager2$RecyclerViewImpl{738f416 VFED..... .F...... 0,0-1028,846 #1} - 同时Logcat输出以下警告日志:
W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection W/IInputConnectionWrapper: finishComposingText on inactive InputConnection W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
可能的解决方案
1. 阻止ViewPager2的RecyclerView自动获取焦点
在ViewPager2的布局中添加android:descendantFocusability="blocksDescendants"属性,阻止内部RecyclerView自动抢夺焦点:
<androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager2" android:layout_width="match_parent" android:layout_height="match_parent" android:descendantFocusability="blocksDescendants" />
或者直接在RecyclerView布局中禁用焦点获取:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:focusableInTouchMode="false" />
2. 自定义EditText修复InputConnection兼容性问题
API 25的输入法框架对InputConnection管理存在兼容缺陷,自定义EditText重写onCreateInputConnection方法,确保连接状态判断逻辑正确:
class FixedEditText @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.editTextStyle ) : androidx.appcompat.widget.AppCompatEditText(context, attrs, defStyleAttr) { override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? { val inputConnection = super.onCreateInputConnection(outAttrs) return inputConnection?.let { ActiveInputConnectionWrapper(it, this) } } private class ActiveInputConnectionWrapper( target: InputConnection, private val editText: EditText ) : InputConnectionWrapper(target, true) { override fun finishComposingText(): Boolean { return if (editText.isInputMethodTarget) super.finishComposingText() else false } override fun getTextBeforeCursor(length: Int, flags: Int): CharSequence? { return if (editText.isInputMethodTarget) super.getTextBeforeCursor(length, flags) else "" } } }
布局中替换为该自定义EditText:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content"> <your.package.name.FixedEditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入内容" /> </com.google.android.material.textfield.TextInputLayout>
3. 手动控制EditText焦点
监听EditText焦点变化,强制保持焦点并唤起输入法:
editText.setOnFocusChangeListener { v, hasFocus -> if (hasFocus) { v.post { v.requestFocus() val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT) } } }
同时在页面生命周期中补充焦点恢复逻辑:
override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (hasFocus && editText != null && !editText.hasFocus()) { editText.requestFocus() } }
4. 调整TextInputLayout焦点属性
确保TextInputLayout和EditText都配置正确的焦点属性:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" android:focusableInTouchMode="true"> <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" android:focusableInTouchMode="true" android:hint="输入内容" /> </com.google.android.material.textfield.TextInputLayout>
内容的提问来源于stack exchange,提问作者MrKiller1779
相关产品推荐
相关产品推荐

