TextInputLayout中的错误文本由键盘覆盖

TextInputLayout包含一个EditText,它依次接收来自用户的input。 随着Androiddevise支持库中引入的TextInputLayout,我们应该将错误设置为保持EditText而不是EditText本身的TextInputLayout。 在编写UI时,将只关注EditText而不关注可能导致键盘覆盖错误的整个TextInputLayout。 在下面的GIF通知中,用户必须首先删除键盘才能看到错误消息。 这与设置IME操作以结合使用键盘的结合导致了令人困惑的结果。

示例错误

布局xml代码:

<android.support.design.widget.TextInputLayout android:id="@+id/uid_text_input_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:errorEnabled="true" android:layout_marginTop="8dp"> <EditText android:id="@+id/uid_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:hint="Cardnumber" android:imeOptions="actionDone"/> </android.support.design.widget.TextInputLayout> 

Java代码将错误设置为TextInputLayout:

 uidTextInputLayout.setError("Incorrect cardnumber"); 

如何确保错误信息在用户看不到的情况下可见? 是否有可能移动焦点?

Solutions Collecting From Web of "TextInputLayout中的错误文本由键盘覆盖"

你应该把所有东西放在ScrollView容器中,这样用户至less可以滚动并看到错误信息。 这是唯一对我有用的东西。

 <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > ... other views ... </LinearLayout> </ScrollView> 

为了确保错误消息在用户看不到的情况下可见,我将TextInputLayout并放置在ScrollView 。 这可以让我滚动下来,如果需要显示错误消息,在每一次的错误信息设置。 在使用它的activity / fragment类中没有需要的更改。

在这里输入图像说明

 /** * [TextInputLayout] subclass that handles error messages properly. */ class SmartTextInputLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : TextInputLayout(context, attrs, defStyleAttr) { private val scrollView by lazy { findParentOfType<ScrollView>() } private val nestedScrollView by lazy { findParentOfType<NestedScrollView>() } private fun scrollIfNeeded() { // Wait a bit (like 10 frames) for other UI changes to happen postDelayed({ scrollView?.scrollDownTo(this) nestedScrollView?.scrollDownTo(this) }, 160) } override fun setError(error: CharSequence?) { super.setError(error) // work around https://stackoverflow.com/q/34242902/1916449 isErrorEnabled = error != null // work around https://stackoverflow.com/q/31047449/1916449 scrollIfNeeded() } } 

以下是辅助方法:

 private inline fun <reified T> View.findParentOfType(): T? { var p = parent while (p != null && p !is T) p = p.parent return p as T? } private fun ScrollView.scrollDownTo(descendant: View) { howFarDownIs(descendant)?.let { smoothScrollBy(0, it) } } private fun NestedScrollView.scrollDownTo(descendant: View) { howFarDownIs(descendant)?.let { smoothScrollBy(0, it) } } /** * Calculate how many pixels below the visible portion of [this] layout is the * bottom of [descendant]. * * In other words, how much you need to scroll down, to make [descendant]'s bottom * visible. */ private fun FrameLayout.howFarDownIs(descendant: View): Int? { return Rect().also { // See https://stackoverflow.com/a/36740277/1916449 descendant.getDrawingRect(it) offsetDescendantRectToMyCoords(descendant, it) }.bottom.minus(height).minus(scrollY).takeIf { it > 0 } } 

我也修正了TextInputLayout.setError()在清除同一个类中的错误后留下了空的空间 。

这是hacky,但这是我做了什么来解决这个问题:

由于在这种情况下,我的TextInputLayout / EditText组合生活在一个RecyclerView,我只是向上滚动时,我设置错误:

 textInputLayout.setError(context.getString(R.string.error_message)) recyclerView.scrollBy(0, context.convertDpToPixel(24f)) 

它的工作,但绝对不是理想的。 如果Google能够解决这个问题,那真是太好了,因为这绝对是一个bug。

我只是发现,如果你把容器固定的高度,键盘留下错误文本的空间

 <FrameLayout android:layout_width="match_parent" android:layout_height="75dp" android:layout_alignParentBottom="true"> <android.support.design.widget.TextInputLayout android:id="@+id/text_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" app:errorEnabled="true" app:errorTextAppearance="@style/ErrorText"> <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:imeOptions="actionGo" android:inputType="textPersonName" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> </FrameLayout>