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


310

Я использую 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 Android 21, EditTexts с материальным дизайном, кажется, используют colorControlActivatedи colorControlNormal. Поэтому я попытался переопределить эти свойства в предыдущем определении стиля, но это не имеет никакого эффекта. Вероятно, appcompat не использует его. К сожалению, я не могу найти источники для последней версии appcompat с дизайном материала.


определите свою тему для редактирования текста
Meenal

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

Ни один из этих ответов не работает для меня на 4.3. У вас есть рабочее решение?
Роберт Бейкер

Мне пришлось продлить AppCompatEditText, по-видимому.
EpicPandaForce

Ответы:


479

Наконец-то я нашел решение. Она просто состоит из перекрывая значение 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>

9
Я вижу, что цвет гамбургера, кнопки «Назад» и полосы прокрутки меню изменился на colorControlNormal.
арио

11
Это меняет цвет нижней строки, но также меняет все остальные элементы управления, такие как флажки, переключатели и т. Д., А также меняет каждый EditText во всем приложении / действии. Если вы хотите изменить нижнюю строку одного EditText (как я), вам нужно переопределить свойство android: background для этого EditText. Там нет другого пути AFAIK.
Эмануэль Меклин,

68
Если вы используете библиотеку поддержки v22 AppCompat, вы можете указать тему в EditText как: android:theme="@style/Theme.App.Base. Это гарантирует, что стиль также не повлияет на другие виды в ваших макетах, которые вы не хотите изменять.
Алекс Локвуд

8
Не работал над Jelly Bean (4.2), но работал над Lollipop
Mangesh

3
Деятельность должна наследоваться от AppCompatActivity. Это не будет работать, если он наследует от Activity.
Бхаратваадж

187

Я чувствовал, что для этого нужен ответ на случай, если кто-то захочет изменить только один текст редактирования Я делаю это так:

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

1
Но как я могу восстановить фон по умолчанию, у меня есть много ошибок после вызова editText.getBackground (). ResetColorFilter () на Lollipop?
ультрасон

Внимание! добавление этого может привести к изменению цвета editText во всем приложении. Протестировано на Nexus 5. ОС 6.0.1.
Алексей Перевозчиков

1
@AlexPerevozchykov Вы можете быть правы. Попробуйте добавить .mutate () после .getBackground (). Это должно сделать это.
hordurh

@hordurh да, это было, я получил это предложение немного раньше, рисованные объекты делят один пул, поэтому перед изменением нам нужно его мутировать
Алексей Перевозчиков

1
Если я использую edittext, это работает, но этот метод не работает с приложением compat edittext на леденце. Вы знаете, как я могу решить проблему?
Селин

145

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

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

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

Таким образом, вместо установки желаемого цвета в глобальной теме, мы создаем новую и назначаем ее только для 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"/>

1
Я не думаю, что это необходимо. colorControlNormalбез префикса android для подкрашивания виджетов используется метод appcompat, а с префиксом он откатывается к системному методу и доступен только на устройствах API 21+.
Пересмотрите

хм, я проверил на своем устройстве леденец, и он не будет подкрашивать пользовательский цвет, если вы не реализуете его в стилях v21 с пространством имен Android также.
user2968401

Я использую 22.2.0версию AppCompat, но этот трюк не работает :(
Shajeel Afzal

1
использование <item name = "colorAccent"> # 000000 </ item> работало для меня вместо colorControlNormal.
MikeOscarEcho

Идеально, чтобы изменить только один текст редактирования в приложении! (Именно то, что мне было нужно! Спасибо)
Ромен Барбье

99

Это можно изменить в XML с помощью:

Для справочного API> = 21 совместимость используйте:

android:backgroundTint="@color/blue"

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

app:backgroundTint="@color/blue"

10
Да, однако это работает только для Android версии 21+ (kitkat & lolipop). Можно было бы попытаться создать обратно совместимое решение.
DaMachk

12
Просто используйте backgroundTint="@color/blue"вместо android:backgroundTint="@color/blue"для обратно совместимой поддержки
Кишан Вагела

11
@KishanVaghela, вместо того, чтобы использовать android:backgroundTint="@color/blue", используйте app:backgroundTint="@color/blue"для поддержки устройств до Lollipop, спасибо за ваш комментарий!
голубой 27.09.16

2
@blueware Если вы хотите использовать его в стиле, тогда нам не нужно использовать «приложение».
Кишан Вагела

добавить, tools:ignore="MissingPrefix"если красный подчеркивание поп подapp:backgroundTint="<your color>"
Моисей Априко

47

Вот решение для 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
}

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

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


@CoolMind извините за поздний ответ. У меня проверить этот код еще раз в библиотеке поддержки 24.2.1, 25.1.1, 25.2.0для устройства <21 и> 21 , и он все еще работает. Пожалуйста, проверьте это простое демо drive.google.com/file/d/0B_poNaia6t8kSzU3bDFVazRSSDA/… . Я не знаю, почему этот код не работает для вас, поэтому, пожалуйста, дайте мне знать. спасибо
Фан Ван Линь

@Renjith извините за поздний ответ, пожалуйста, проверьте мой комментарий выше
Фан Ван Линь

Как вы сбрасываете цвет по умолчанию с этим кодом?
Неф

35

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

<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 используется для тонирования виджетов во всем приложении и поэтому должен использоваться для обеспечения согласованности


8
@ Tomasz это не требует API 21+, потому что родительской темой является AppCompat, который переходит к API 7
TanmayP

Ughhh. Спасибо за это, я использовал по name="android:colorAccent"ошибке
Жюль

29

Если вы используете, 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);
    }

что за спасатель, это круто, позор, это не очень хорошо известно
pt123

Пожалуйста, переместитесь вниз и посмотрите мой ответ для библиотеки дизайна 23.2.0. Этот метод сейчас бесполезен.
ywwynm

21

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

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

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


@ powder366, вы можете опубликовать основную тему своего приложения?
blueware

1
<style name = "AppTheme" parent = "Theme.AppCompat.Light.DarkActionBar">
powder366

2
@ powder366, попробуйте это: <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">и это должно сработать
blueware

19

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


Оно работает! Поскольку вопрос спрашивает, это должно быть решено в стиле / теме, это должно быть правильным ответом.
ниндзя

Я согласен. это должен быть правильный ответ, так как это глобальное решение
Santacrab

Это неудобно, если разные элементы управления требуют разных цветов.
Юлий

12

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


9

Это очень просто, просто добавьте свой 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"/>

2
backgroundTint выше API уровня 21
Эшвин H

ViewCompat.setBackgroundTintList (editText, ColorStateList.valueOf (Color.YELLOW))
Arst

1
app:backgroundTint="@color/blue"работает на всех уровнях API .. хотя по какой-то причине он по-прежнему
меняется

8

Вот часть исходного кода 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);
}

Что такое AppCompatDrawableManager? setBackground требует API 16.
CoolMind

8

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

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

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

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

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


1
Это меняет цвет фона целиком, и мы хотим изменить только цвет подчеркивания.
Шахзайн Али

@shahzain ali Подчеркивание EditText - это фон. Его нет, если вы установите его на ноль. И вот почему backgroundTint будет работал (но это не изменит цвет при активации)
nyconing

7

Для меня я изменил и 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>

Вот это colors.xml

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

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


2
Это должен быть ответ
Мина Сэми

Работал как шарм. Спасибо
Даниш Шарма

6

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

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


5

В 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для вашего желаемого цвета


5

Я использую этот метод, чтобы изменить цвет линии с помощью 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);
}

Существует ли подобный идентификатор для доступа к нижней строке простого EditText?
Реми П

4

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

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

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


4

Я разработал рабочее решение этой проблемы после 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's 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);

2

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

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


2

Это самый простой и эффективный / многократно используемый / работает на всех 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"/>

2

Для динамического изменения фона 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);

Кредиты: Этот ТАК ответ о ColorStateList потрясающий .


И какой метод использовать? setBackgroundTintList? Это требует API 21.
CoolMind

setSupportBackgroundTintList для старых версий API.
Анкит Попли

0

Добавьте app:backgroundTintниже 21 уровня API. В противном случае используйтеandroid:backgroundTint .

Для ниже уровня API 21.

<EditText
     android:id="@+id/edt_name"
     android:layout_width="300dp"
     android:layout_height="wrap_content"
     android:textColor="#0012ff"
     app:backgroundTint="#0012ff"/>

Для уровня выше 21 API.

<EditText
     android:id="@+id/edt_name"
     android:layout_width="300dp"
     android:layout_height="wrap_content"
     android:textColor="#0012ff"
     android:backgroundTint="#0012ff"/>

-2

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

  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());
        }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.