Изменение цвета нижней строки EditText с помощью appcompat v7

Я использую appcompat v7, чтобы выглядеть на Android 5 и меньше. Он работает довольно хорошо. Однако я не могу понять, как изменить цвет нижней строки и цвет акцента для EditTexts. Является ли это возможным?

Я попытался определить пользовательский android:editTextStyle (см. ниже), но мне удалось изменить только цвет фона или цвет текста, но не нижнюю строку или цвет акцента. Существует ли конкретное значение свойства для использования? мне нужно использовать пользовательское изображение с возможностью рисования через свойство android:background? Невозможно указать цвет в гекса?

 <style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
     <item name="android:editTextStyle">@style/Widget.App.EditText</item>
 </style>

 <style name="Widget.App.EditText" parent="Widget.AppCompat.EditText">
     ???
 </style>

Согласно источникам API API 21, EditTexts с материальным дизайном, похоже, использует colorControlActivated и colorControlNormal. Поэтому я попытался переопределить эти свойства в предыдущем определении стиля, но это не имеет никакого эффекта. Вероятно, appcompat не использует его. К сожалению, я не могу найти источники для последней версии appcompat с материальным дизайном.

Ответ 1

Наконец, я нашел решение. Он просто состоит в переопределении значения для colorControlActivated, colorControlHighlight и colorControlNormal в определении темы приложения, а не в стиле edittext. Затем подумайте использовать эту тему для любой деятельности, которую вы желаете. Ниже приведен пример:

<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorControlNormal">#c5c5c5</item>
    <item name="colorControlActivated">@color/accent</item>
    <item name="colorControlHighlight">@color/accent</item>
</style>

Ответ 2

Мне казалось, что это необходимо для ответа, если кто-то захочет изменить только один edittext. Я делаю это так:

editText.getBackground().mutate().setColorFilter(getResources().getColor(R.color.your_color), PorterDuff.Mode.SRC_ATOP);

Ответ 3

В то время как решение Laurents верно, оно имеет некоторые недостатки, как описано в комментариях, так как не только нижняя строка EditText получает оттенок, но и кнопка "Назад" от Toolbar, CheckBoxes и т.д.

К счастью, v22.1 of appcompat-v7 представил несколько новых возможностей. Теперь можно назначить конкретную тему только одному виду. Прямо из Changelog:

Устаревшее использование приложения: тема для стилизации панели инструментов. Теперь вы можете использовать тему android: для панелей инструментов на всех устройствах уровня API 7 и выше и поддержка android: тема для всех виджетов на уровне API 11 и более высокие устройства.

Поэтому вместо того, чтобы задавать нужный цвет в глобальной теме, мы создаем новую и назначаем ее только EditText.

Пример:

<style name="MyEditTextTheme">
    <!-- Used for the bottom line when not selected / focused -->
    <item name="colorControlNormal">#9e9e9e</item>
    <!-- colorControlActivated & colorControlHighlight use the colorAccent color by default -->
</style>

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/MyEditTextTheme"/>

Ответ 4

Для справки. Это может быть изменено в XML с помощью:

android:backgroundTint="@color/blue"

Для обратной совместимости используйте:

app:backgroundTint="@color/blue"

Ответ 5

Вот решение для API < 21 и выше

Drawable drawable = yourEditText.getBackground(); // get current EditText drawable 
drawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); // change the drawable color

if(Build.VERSION.SDK_INT > 16) {
    yourEditText.setBackground(drawable); // set the new drawable to EditText
}else{
    yourEditText.setBackgroundDrawable(drawable); // use setBackgroundDrawable because setBackground required API 16
}

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

Надеюсь, что это поможет

Ответ 6

Принятый ответ немного больше по стилю, но наиболее эффективная вещь - добавить в свой стиль AppTheme colorAccent:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:editTextStyle">@style/EditTextStyle</item>
</style>

<style name="EditTextStyle" parent="Widget.AppCompat.EditText"/>

Атрибут colorAccent используется для подсвечивания виджета во всем приложении и, следовательно, его следует использовать для согласованности

Ответ 7

Если вы используете appcompat-v7:22.1.0+, вы можете использовать DrawableCompat, чтобы подкрасить ваши виджеты.

    public static void tintWidget(View view, int color) {
        Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground());
        DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color));
        view.setBackgroundDrawable(wrappedDrawable);
    }

Ответ 8

Использование:

<EditText
    app:backgroundTint="@color/blue"/>

Это будет поддерживать устройства до Lollipop не только +21

Ответ 9

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="colorControlNormal">@color/colorAccent</item>
    <item name="colorControlActivated">@color/colorAccent</item>
    <item name="colorControlHighlight">@color/colorAccent</item>

</style>

Ответ 10

Одним из быстрых решений для вашей проблемы является просмотр в файле yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/для abc_edit_text_material.xml и копирование этого XML файла в вашу папку с возможностью переноса, Затем вы можете изменить цвет 9 файлов патчей внутри этого селектора, чтобы соответствовать вашим предпочтениям.

Ответ 11

Это очень просто, просто добавьте атрибут android:backgroundTint в ваш EditText.

android:backgroundTint="@color/blue"
android:backgroundTint="#ffffff"
android:backgroundTint="@color/red"


 <EditText
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:backgroundTint="#ffffff"/>

Ответ 12

Я слишком долго задерживался на этой проблеме.

Мне понадобилось решение, которое работало для версий выше и ниже v21.

Наконец, я обнаружил очень простое, но не идеальное, но эффективное решение: просто установите цвет фона transparent в свойствах EditText.

<EditText
    android:background="@android:color/transparent"/>

Надеюсь, это немного сэкономит время.

Ответ 13

Вот часть исходного кода TextInputLayout в библиотеке поддержки дизайна (ОБНОВЛЕНО для версии 23.2.0), которая изменяет цвет EditText нижнего цвета более простым способом:

private void updateEditTextBackground() {
    ensureBackgroundDrawableStateWorkaround();

    final Drawable editTextBackground = mEditText.getBackground();
    if (editTextBackground == null) {
        return;
    }

    if (mErrorShown && mErrorView != null) {
        // Set a color filter of the error color
        editTextBackground.setColorFilter(
                AppCompatDrawableManager.getPorterDuffColorFilter(
                        mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
    }
    ...
}

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

И если вы хотите поддерживать все платформы, вот мой метод:

/**
 * Set backgroundTint to {@link View} across all targeting platform level.
 * @param view the {@link View} to tint.
 * @param color color used to tint.
 */
public static void tintView(View view, int color) {
    final Drawable d = view.getBackground();
    final Drawable nd = d.getConstantState().newDrawable();
    nd.setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
            color, PorterDuff.Mode.SRC_IN));
    view.setBackground(nd);
}

Ответ 14

Для меня я модифицировал как AppTheme, так и значение colors.xml И colorControlNormal, и colorAccent помогли мне изменить цвет границы EditText. Как и курсор, и "|" когда внутри EditText.

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorControlNormal">@color/yellow</item>
    <item name="colorAccent">@color/yellow</item>
</style>

Вот цвет .xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="yellow">#B7EC2A</color>
</resources>

Я достал атрибут android: textCursorDrawable для @null, который я разместил внутри стиля editText. Когда я попытался использовать это, цвета не изменились бы.

Ответ 15

Вы можете установить фон edittext в прямоугольник с минусом padding слева, справа и сверху, чтобы достичь этого. Вот пример xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="-1dp"
        android:left="-1dp"
        android:right="-1dp"
        android:bottom="1dp"
        >
        <shape android:shape="rectangle">
            <stroke android:width="1dp" android:color="#6A9A3A"/>
        </shape>
    </item>
</layer-list>

Замените фигуру селектором, если вы хотите предоставить различную ширину и цвет для сфокусированного edittext.

Ответ 16

Я использую этот метод, чтобы изменить цвет линии с помощью PorterDuff, без других доступных.

public void changeBottomColorSearchView(int color) {
    int searchPlateId = mSearchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
    View searchPlate = mSearchView.findViewById(searchPlateId);
    searchPlate.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}

Ответ 17

Если вы хотите изменить нижнюю строку без использования цветов приложения, используйте эти строки в своей теме:

<item name="android:editTextStyle">@android:style/Widget.EditText</item>
<item name="editTextStyle">@android:style/Widget.EditText</item>

Я не знаю другого решения.

Ответ 18

Я разработал рабочее решение этой проблемы через 2 дня борьбы, ниже решение идеально подходит для тех, кто хочет изменить только текст редактирования, изменить/переключить цвет через Java-код и захотеть преодолеть проблемы различного поведения на версиях ОС из-за использования метода setColorFilter().

    import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatDrawableManager;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import com.newco.cooltv.R;

public class RqubeErrorEditText extends AppCompatEditText {

  private int errorUnderlineColor;
  private boolean isErrorStateEnabled;
  private boolean mHasReconstructedEditTextBackground;

  public RqubeErrorEditText(Context context) {
    super(context);
    initColors();
  }

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

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

  private void initColors() {
    errorUnderlineColor = R.color.et_error_color_rule;

  }

  public void setErrorColor() {
    ensureBackgroundDrawableStateWorkaround();
    getBackground().setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
        ContextCompat.getColor(getContext(), errorUnderlineColor), PorterDuff.Mode.SRC_IN));
  }

  private void ensureBackgroundDrawableStateWorkaround() {
    final Drawable bg = getBackground();
    if (bg == null) {
      return;
    }
    if (!mHasReconstructedEditTextBackground) {
      // This is gross. There is an issue in the platform which affects container Drawables
      // where the first drawable retrieved from resources will propogate any changes
      // (like color filter) to all instances from the cache. We'll try to workaround it...
      final Drawable newBg = bg.getConstantState().newDrawable();
      //if (bg instanceof DrawableContainer) {
      //  // If we have a Drawable container, we can try and set it constant state via
      //  // reflection from the new Drawable
      //  mHasReconstructedEditTextBackground =
      //      DrawableUtils.setContainerConstantState(
      //          (DrawableContainer) bg, newBg.getConstantState());
      //}
      if (!mHasReconstructedEditTextBackground) {
        // If we reach here then we just need to set a brand new instance of the Drawable
        // as the background. This has the unfortunate side-effect of wiping out any
        // user set padding, but I'd hope that use of custom padding on an EditText
        // is limited.
        setBackgroundDrawable(newBg);
        mHasReconstructedEditTextBackground = true;
      }
    }
  }

  public boolean isErrorStateEnabled() {
    return isErrorStateEnabled;
  }

  public void setErrorState(boolean isErrorStateEnabled) {
    this.isErrorStateEnabled = isErrorStateEnabled;
    if (isErrorStateEnabled) {
      setErrorColor();
      invalidate();
    } else {
      getBackground().mutate().clearColorFilter();
      invalidate();
    }
  }
}

Используется в xml

<com.rqube.ui.widget.RqubeErrorEditText
            android:id="@+id/f_signup_et_referral_code"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toEndOf="@+id/referral_iv"
            android:layout_toRightOf="@+id/referral_iv"
            android:ems="10"
            android:hint="@string/lbl_referral_code"
            android:imeOptions="actionNext"
            android:inputType="textEmailAddress"
            android:textSize="@dimen/text_size_sp_16"
            android:theme="@style/EditTextStyle"/>

Добавить строки в стиле

<style name="EditTextStyle" parent="android:Widget.EditText">
    <item name="android:textColor">@color/txt_color_change</item>
    <item name="android:textColorHint">@color/et_default_color_text</item>
    <item name="colorControlNormal">@color/et_default_color_rule</item>
    <item name="colorControlActivated">@color/et_engagged_color_rule</item>
  </style>

java-код для переключения цвета

myRqubeEditText.setErrorState(true);
myRqubeEditText.setErrorState(false);

Ответ 19

В Activit.XML добавьте код

<EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:ems="10"
        android:id="@+id/editText"
        android:hint="Informe o usuário"
        android:backgroundTint="@android:color/transparent"/>

Где BackgroundTint=color для нужного цвета

Ответ 20

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

Наконец я понял, что происходит. Я был (неправильно) с помощью android.widget.EditText при создании нового экземпляра (но остальные мои компоненты были из библиотеки appcompat). Я должен был использовать android.support.v7.widget.AppCompatEditText. Я заменил new EditText(this) на new AppCompatEditText(this)  и проблема была мгновенно решена. Оказывается, если вы на самом деле используете AppCompatEditText, он будет просто уважать accentColor от вашей темы (как упоминалось в нескольких комментариях выше), и дополнительная настройка не требуется.

Ответ 21

Это самый простой и эффективный/многоразовый/работает на всех API-интерфейсах
Создайте собственный класс EditText, например:

public class EditText extends android.widget.EditText {
    public EditText(Context context) {
        super(context);
        init();
    }

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

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

    private void init() {
        getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
    }
}

Затем используйте его следующим образом:

 <company.com.app.EditText
        android:layout_width="200dp"
        android:layout_height="wrap_content"/>

Ответ 22

Чтобы изменить динамический фон EditText, вы можете использовать ColorStateList.

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList colorStateList = new ColorStateList(states, colors);

Кредиты: Этот SO-ответ о ColorStateList является потрясающим.

Ответ 23

Пожалуйста, измените этот метод в соответствии с вашими потребностями. Это сработало для меня!

  private boolean validateMobilenumber() {
        if (mobilenumber.getText().toString().trim().isEmpty() || mobilenumber.getText().toString().length() < 10) {
            input_layout_mobilenumber.setErrorEnabled(true);
            input_layout_mobilenumber.setError(getString(R.string.err_msg_mobilenumber));
           // requestFocus(mobilenumber);
            return false;
        } else {
            input_layout_mobilenumber.setError(null);
            input_layout_mobilenumber.setErrorEnabled(false);
            mobilenumber.setBackground(mobilenumber.getBackground().getConstantState().newDrawable());
        }