Текст ошибки в TextInputLayout покрывается клавиатурой

TextInputLayout содержит EditText, который, в свою очередь, получает вход от пользователя. С TextInputLayout, представленным в Библиотеке поддержки дизайна Android, мы должны установить ошибку в TextInputLayout, где находится EditText, а не сам EditText. При написании пользовательского интерфейса будет сфокусирован только на 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, чтобы пользователь мог, по крайней мере, прокручивать и видеть сообщение об ошибке. Это единственное, что сработало для меня.

 <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 . Это позволяет мне прокручивать вниз, если необходимо, чтобы показать сообщение об ошибке, при каждом появлении сообщения об ошибке. В классе активности / фрагмента нет изменений, которые его используют.

Введите описание изображения здесь

 /** * [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 (), оставляя пустое пространство после устранения ошибки в том же классе.

Я просто узнаю, что если вы поместите контейнер в фиксированную высоту, клавиатура оставляет место для текста ошибки

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