TextInputLayout: как дать отступ или отступ для подсказки?

Я должен использовать TextInputLayout библиотеки поддержки дизайна в моем проекте. Я хочу дать пространство между hint а также EditText в TextInputLayout, Я устанавливаю поля и отступы в TextInputLayout и даже внутри EditText но оба не работают. Так как решить эту проблему. Здесь я прилагаю снимок экрана и мое кодирование.

==============================Style=================================

<style name="TextHint" parent="Base.TextAppearance.AppCompat">
    <item name="android:textSize">18sp</item>
    <item name="android:textColor">@color/green</item>
</style>



=============================XML===================================  
<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    app:hintTextAppearance="@style/TextHint"
    android:layout_marginTop="10dp"
    android:layout_marginLeft="30dp"
    android:layout_marginRight="30dp"
    android:layout_height="wrap_content">
<EditText
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:id="@+id/edttxtEmailAddress"
    android:singleLine="true"
    android:hint="@string/enter_valid_email"
    android:paddingLeft="20dp"
    android:textSize="20sp"
    android:background="@drawable/rounded_common"/>
</android.support.design.widget.TextInputLayout>

22 ответа

Решение

Решение, предложенное ganesh2shiv, работает по большей части, хотя я обнаружил, что оно также децентрирует текст подсказки, отображаемый внутри EditText, когда он не сфокусирован.

Лучший трюк - установить желаемое paddingTop к EditText, но также вставьте дополнительный отступ в фоновом режиме EditText. Довольно разумный способ сделать это, чтобы обернуть ваш оригинальный фон в <layer-list> и установить <item android:top="..."> атрибут, чтобы соответствовать paddingTop вашего EditText.

<android.support.design.widget.TextInputLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/floating_hint_margin"
    android:background="@drawable/bg_edit_text" />
</android.support.design.widget.TextInputLayout>

И bg_edit_text.xml файл для рисования:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:top="@dimen/floating_hint_margin">
    <your original background; can be <bitmap> or <shape> or whatever./>
  </item>
</layer-list>

Я сам искал решение этого вопроса в последние пару дней. После того, как я несколько часов рвал на себе волосы, я наконец нашел простой обходной путь. Что я заметил, так это то, что если у вас установлен пользовательский фон в EditText, то атрибут android: paddingTop simple не работает, чтобы изменить интервал между текстами подсказок и редактировать текст (я действительно не знаю, почему). Поэтому, если вы установили пользовательский фон для вашего EditText, вы можете использовать атрибут android: translationY в EditText.

Итак, вот ваше решение:

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="30dp"
    android:layout_marginRight="30dp"
    android:layout_marginTop="10dp"
    app:hintTextAppearance="@style/TextHint">

    <EditText
        android:id="@+id/edttxtEmailAddress"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/rounded_common"
        android:hint="@string/enter_valid_email"
        android:paddingLeft="20dp"

        android:translationY="10dp" 

        android:singleLine="true"
        android:textSize="20sp" />
</android.support.design.widget.TextInputLayout>

Надеюсь, поможет.:)


Обновление: мои искренние извинения за позднее обновление. Я был очень занят в последнее время. Если вы еще не поняли, позвольте мне сказать вам, что этот ответ прямо уродлив и неправильн. Оглядываясь назад, я думаю, что, вероятно, был пьян, когда писал это. Как уже упоминалось другими, это может обрезать нижнюю область фона editText, но есть и уродливое решение для этой проблемы - вы можете установить высоту (родительского) textInputLayout заметно больше (насколько большой? Вы должны найти ее пробным путем и ошибка, чёрт!) чем (дочерний) editText. Я надеюсь, вы все понимаете, что это было бы сумасшествием, поэтому, пожалуйста, не делайте этого. Проверьте ответ, написанный @Radu Topor, это, безусловно, лучшее и чистое решение этого вопроса. Благодарю.

Я попробовал изменения заполнения, но это не работает хорошо.

Простой обходной путь - изменить высоту TIL:

android:layout_height="wrap_content"

(например)

android:layout_height="50dp"

это может не дать тот же результат на всех размерах экрана.

И добавить

android:gravity="bottom" 

нажать свой текст вниз.

Ответ @RaduTopor хорош, но я думаю, что нам также нужно добавить android:bottom, иначе он также децентрирует текст подсказки, отображаемый внутри EditText, когда он не сфокусирован.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:top="@dimen/floating_hint_margin" android:bottom="@dimen/floating_hint_margin">
    <your original background; can be <bitmap> or <shape> or whatever./>
  </item>
</layer-list>

До (ответ RaduTopor):

не по центру

После:

в центре

После многих попыток я нашел еще одно решение (версия материала 1.2.1):

это образец макета:

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/textInputLayout"
            style="@style/CustomTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/textInputEditText"
                style="@style/CustomTextInputEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint" />

  </com.google.android.material.textfield.TextInputLayout>

это образец стилей:

       <style name="CustomTextInputLayout">
        <item name="boxCollapsedPaddingTop">-16dp</item>
        <item name="android:paddingTop">16dp</item>
        <item name="boxBackgroundColor">@color/backgroundColorWhite</item>
        <item name="android:textColorHint">...</item>
        <item name="android:textAppearance">...</item>
        <item name="hintTextAppearance">...</item>
        <item name="hintTextColor">...</item>
        <item name="boxStrokeColor">...</item>
    </style>

    <style name="CustomTextInputEditText">
        <item name="android:textAppearance">...</item>
        <item name="android:paddingTop">@dimen/margin_12</item>
        <item name="android:paddingBottom">@dimen/margin_12</item>
        <item name="android:paddingStart">0dp</item>
        <item name="android:paddingEnd">0dp</item>
    </style>

эти 2 строки устанавливают вертикальное смещение для просмотра заголовка / подсказки в развернутом состоянии над свернутым состоянием:

        <item name="boxCollapsedPaddingTop">-16dp</item>
  <item name="android:paddingTop">16dp</item>
 

эти 2 строки - для поля между текстом и подчеркиванием:

        <item name="android:paddingTop">@dimen/margin_12</item>
  <item name="android:paddingBottom">@dimen/margin_12</item>

эта строка - для устранения ошибки тонирования фона:

       <item name="boxBackgroundColor">@color/backgroundColorWhite</item>

эти 2 строки - для удаления стандартных горизонтальных отступов

       <item name="android:paddingStart">0dp</item>
 <item name="android:paddingEnd">0dp</item>

Я создал специальный класс с целью добавления пустого представления над EditText, таким образом добавив отступ к подсказке. Вы можете использовать его как простой TextInputLayout.

public class PaddingTextInputLayout extends TextInputLayout {

public View paddingView;

public PaddingTextInputLayout(Context context) {
    super(context);
}

public PaddingTextInputLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public PaddingTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
    super.addView(child, index, params);
    refreshPaddingView();
}

public void addPaddingView(){
    paddingView = new View(getContext());
    int height = (int) getContext().getResources()
            .getDimension(R.dimen.edittext_text_input_layout_padding);
    ViewGroup.LayoutParams paddingParams = new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            height);
    super.addView(paddingView, 0, paddingParams);
}

public void refreshPaddingView(){
    if (paddingView != null) {
        removeView(paddingView);
        paddingView = null;
    }
    addPaddingView();
}
}

Эта реализация очень проста и глупа, вы можете ее значительно улучшить.

Чтобы отключить эффект сокращения нижней строки, я использовал поля, translationY и clipChildren="false"

<android.support.design.widget.TextInputLayout
        android:id="@+id/textinput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:clipChildren="false">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/et_profile_contact_name"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="3dp"
            android:background="@drawable/image_back"
            android:hint="Contact name"
            android:padding="5dp"
            android:translationY="3dp" />
    </android.support.design.widget.TextInputLayout>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="10dp"
          android:bottom="5dp">
        <shape>
            <!-- Background Color -->
            <solid android:color="#f1f1f1"/>
            <!-- Round Corners -->
            <corners android:radius="5dp"/>
        </shape>
    </item>
</layer-list>

<style name="text_input_edit_text_without_border_style">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">55dp</item>
    <item name="android:paddingTop">10dp</item>
    <item name="android:paddingBottom">5dp</item>
    <item name="android:gravity">left|center_vertical</item>
    <item name="android:paddingLeft">8dp</item>
    <item name="android:paddingRight">8dp</item>
    <item name="android:maxLines">1</item>
    <item name="android:singleLine">true</item>
    <item name="android:imeOptions">actionNext</item>
    <item name="android:textSize">@dimen/text_size_large</item>
    <item name="android:background">@drawable/bg_without_border_with_padding_top</item>
</style>

<style name="text_input_layout_style">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_marginBottom">@dimen/margin_medium</item>
</style>

Это то, что я сделал в своем проекте, чтобы получить достаточно места между edittext и hint

<android.support.design.widget.TextInputLayout
    android:id="@+id/til_full_name"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_marginStart="40dp"
    android:layout_marginEnd="40dp"
    android:layout_marginTop="30dp"
    android:gravity="bottom"
    android:textColorHint="#fff"
    app:layout_constraintTop_toBottomOf="@+id/welcome_til_email">

    <android.support.v7.widget.AppCompatEditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="#9a050505"
        android:hint="You email"
        android:inputType="textCapWords"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:singleLine="true"
        android:textAppearance="?android:textAppearanceSmall"
        android:textColor="#fff"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
</android.support.design.widget.TextInputLayout>

Если вы хотите установитьandroid:hintдополнение до 0 в фокусе, добавитьapp:boxCollapsedPaddingTop="0dp"на вашTextInputLayout.

Спасибо @Erkan заapp:boxCollapsedPaddingTop(если установлено вTextInputLayout).

      <com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingHorizontal="16dp"
    android:paddingVertical="8dp"
    android:background="@drawable/rounded_corners"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp"
    app:boxCollapsedPaddingTop="8dp">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="0dp"
        android:paddingVertical="8dp"
        android:hint="Hint" />

</com.google.android.material.textfield.TextInputLayout>

Но если вы установитеbackgroundвTextInputEditText, больше ничего не требуется. Это даже хорошо работает для состояния ошибки.

      <com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/rounded_corners"
        android:hint="Hint" />

</com.google.android.material.textfield.TextInputLayout>

Просто добавьте в свой EditText пользовательский фон

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
        <shape android:shape="rectangle">
            <padding
                android:top="4dp"/> // your padding value
        </shape>
    </item>
// customize your background items if you need
</layer-list>
<android.support.design.widget.TextInputLayout
 ...>
    <android.support.design.widget.TextInputEditText
        ...
        android:background="@style/your_custom_background"/>

затем примените его к вашему EditText и увеличьте высоту вашего EditText со значением отступа, если вы используете фиксированную высоту

Попробуйте использовать paddingStart вместо заполнения влево или вправо. Это сработало для меня.

      android:paddingStart="8dp"

Просто используйте padding-bottom

<com.google.android.material.textfield.TextInputLayout



             app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                >

                <com.google.android.material.textfield.TextInputEditText

                   ....
                    android:paddingBottom="@dimen/dp_25"
...
                   />
            </com.google.android.material.textfield.TextInputLayout>

Это поздний ответ, но надеюсь, что это поможет, и я думаю, что это немного лучшее решение. Вместо того, чтобы дать фон вашей editText Дайте этот фон вашему TextInputLayout, И установить edittext макет прозрачный.

<android.support.design.widget.TextInputLayout
                android:id="@+id/tinput_phone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="05dp"
                android:background="@drawable/send_email_screen_element_bg"
                android:padding="05dp"
                android:theme="@style/grey_control_style">

                <android.support.v7.widget.AppCompatEditText
                    android:id="@+id/edt_phone"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/transparent"
                    android:ems="10"
                    android:hint="@string/phone_hint_str"
                    android:inputType="text"
                    android:paddingStart="10dp"
                    android:paddingTop="10dp"
                    android:paddingBottom="10dp"
                    android:singleLine="true"
                    android:textColor="@color/black"
                    android:textSize="14sp" />
            </android.support.design.widget.TextInputLayout>

Рабочее решение:

Вы должны указать нестандартную высоту для TextInputEditText и сделать собственный рисунок, после чего вы получите свое решение, НАДЕЮСЬ, ОНО БУДЕТ РАБОТАЕТ 100%

1-й шаг:

       <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/tilStart"
    android:layout_width="match_parent"
    android:textColorHint="@color/darkgreen"
    android:layout_marginTop="@dimen/_20sdp"
    android:layout_height="wrap_content"
    app:errorEnabled="true"
    android:layout_below="@+id/labelDescription">

  <com.google.android.material.textfield.TextInputEditText
      android:id="@+id/tietStart"
      android:layout_width="match_parent"
      android:layout_height="@dimen/_30sdp"
      android:hint="@string/start_offset"
      android:fontFamily="@font/gilroysemibold"
      android:background="@drawable/customedittext"
      android:text="@string/zero"
      android:gravity="bottom"
      android:paddingLeft="@dimen/_10sdp"
      android:textColor="@color/darkgreen"
      android:inputType="number"
      android:typeface="monospace"
      android:digits="0123456789."
      android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>

2-й шаг:

      <?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="@dimen/_10sdp">
    <shape >
        <solid android:color="@color/activitycolor"/>
        <corners android:radius="@dimen/_10sdp"/>
    </shape>
</item>
</layer-list>

макет xml

<com.google.android.material.textfield.TextInputLayout
    style="@style/TextInputLayout"
    android:layout_marginTop="10dp"
    android:gravity="center"
    android:theme="@style/TextInputLayoutHint">

    <androidx.appcompat.widget.AppCompatEditText
        style="@style/TextInputEditText"
        android:hint="Email ID"
        android:inputType="textEmailAddress"
        android:maxLines="1" />

</com.google.android.material.textfield.TextInputLayout>

styles.xml

<style name="TextInputLayout">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_marginStart">15dp</item>
    <item name="android:layout_marginLeft">15dp</item>
    <item name="android:layout_marginTop">10dp</item>
    <item name="android:layout_marginEnd">15dp</item>
    <item name="android:layout_marginRight">15dp</item>
</style>

<style name="TextInputLayoutHint" parent="">
    <item name="android:textColorHint">@color/colorHintNormal</item>
    <item name="colorControlActivated">@color/colorOrange</item>
    <item name="android:textSize">11dp</item>
</style>

<style name="TextInputEditText" parent="">
    <item name="android:translationY">10dp</item>
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:background">@null</item>
    <item name="android:paddingBottom">15dp</item>
    <item name="android:textColor">@color/colorBlack</item>
    <item name="android:textColorHint">@color/colorHintActive</item>
    <item name="android:textSize">13sp</item>
</style>    

Вы можете попробовать это решение и редактировать TextStyle только в стиле TextInputLayout. Например:

      <com.google.android.material.textfield.TextInputLayout
    ...
    android:layout_width="@dimen/element_width"
    android:layout_height="@dimen/element_height"
    ...
    style="@style/EditTextField.Container"
    ...
    android:hint="@string/you_hint_resource">

    <com.google.android.material.textfield.TextInputEditText
        ...
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        ... />

</com.google.android.material.textfield.TextInputLayout>

В разделе вашего стиля

      <style name="EditTextField"/>

<style name="EditTextField.Container" parent="Widget.MaterialComponents.TextInputLayout.FilledBox.Dense">
    <item name="android:textColorHint">@color/edit_text_hint_color</item>
    <item name="hintTextColor">@color/edit_text_hint_color</item>
    <item name="hintTextAppearance">@style/PasswordInput.HintTextAppearance</item>
    <item name="materialThemeOverlay">@style/PasswordInput.MaterialThemeOverlayStyle</item>
</style>

<style name="EditTextField.HintTextAppearance">
    <item name="android:paddingBottom">20dp</item>
    <item name="android:paddingTop">10dp</item>
    <item name="android:textSize">12sp</item>
</style>

<style name="EditTextField.MaterialThemeOverlayStyle">
    <item name="editTextStyle">@style/EditTextStyle</item>
</style>

<style name="EditTextStyle" parent="@style/Widget.MaterialComponents.TextInputEditText.FilledBox.Dense">
    <item name="android:background">@drawable/edittext_body_container</item>
    <item name="android:paddingBottom">@dimen/input_text_bottom_padding</item>
    <item name="android:paddingStart">@dimen/input_text_padding_start</item>
    <item name="android:paddingTop">@dimen/input_text_top_padding</item>
    <item name="android:textCursorDrawable">@drawable/cursor_white_drawable</item>
    <item name="android:textSize">16sp</item>
    <item name="lineHeight">20sp</item>
</style>

Вы можете использовать startIconDrawableк TextInputLayoutи убедитесь, что вы установили какой-то фиктивный прозрачный значок (ширина значка будет начальным значением заполнения). так что вы получите заполнение с самого начала. Примечание: это взлом, а не прямое решение

Если требуется добавить пробел между курсором и подсказкой, вы можете попробовать

editTextComment.setHint("  "+getString(R.string.add_a_comment));

Я думаю, вы должны рассмотреть это:

Библиотека дизайна использует интересный подход к настройке EditText: это не меняет это напрямую. Вместо этого TextInputLayout используется, чтобы обернуть EditText и предоставить улучшения.

Первый, отображающий плавающую метку, когда пользователь вводит что-то в поле, выполняется автоматически. TextInputLayout находит EditText среди своих детей и присоединяется как TextWatcherТаким образом, он может определить, когда поле было изменено, и анимирует движение подсказки от его обычного места в EditText в плавающей позиции над ним.

Второе улучшение, отображающее сообщение об ошибке, требует небольшого изменения кода. Вместо установки ошибки на EditText, ошибка должна быть установлена ​​на TextInputLayout, Это потому, что не существует автоматического способа TextInputLayout получать уведомление, когда ошибка установлена ​​на EditText, Вот как может выглядеть макет:

<android.support.design.widget.TextInputLayout
    android:id="@+id/username_text_input_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <EditText
        android:id="@+id/username_edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/username_hint"/>
</android.support.design.widget.TextInputLayout>

Обратите внимание, что оба EditText а также TextInputLayout нужны идентификаторы макета. Во фрагменте нам нужно настроить TextInputLayout чтобы включить отображение ошибок:

TextInputLayout usernameTextInputLayout = (TextInputLayout) view.findViewById(R.id.username_text_input_layout);
usernameTextInputLayout.setErrorEnabled(true);
...
usernameTextInputLayout.setError(R.string.username_required);

Я думаю, проще, чем вы думаете, работать с размерами исправлений, если вам не нужно использовать wrap_content по какой-то причине, в противном случае принятый подход работает должным образом.

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:gravity="bottom">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"/>

        </com.google.android.material.textfield.TextInputLayout>

Следуя этому примеру, у вас есть пространство 20dp для размещения метки подсказки, как вы хотите, играя с layout_marginTop свойство.

Другие вопросы по тегам