Zmiana koloru dolnej linii EditText za pomocą appcompat v7

Używam appcompat v7, aby uzyskać spójny wygląd na Androidzie 5 i mniej. Działa dość dobrze. Jednak nie mogę dowiedzieć się, jak zmienić kolor dolnej linii i kolor akcentu dla Edittextów. Czy to możliwe?

Próbowałem zdefiniować zwyczaj android:editTextStyle (por. poniżej) ale udało mi się tylko zmienić Pełny kolor tła lub kolor tekstu, ale nie dolną linię ani kolor akcentu. Czy istnieje konkretna wartość nieruchomości do wykorzystania? Czy muszę używać niestandardowego rysowalnego obrazu przez android:background własność? czy nie można określić koloru w hexa?

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

Według źródeł android API 21, EditText Z material design wydają się używać colorControlActivated i colorControlNormal. Dlatego próbowałem nadpisać te właściwości w poprzedniej definicji stylu, ale nie ma to żadnego efektu. Prawdopodobnie appcompat go nie używa. Niestety, nie mogę znaleźć źródeł dla ostatniej wersji appcompat Z material design.

Author: l-l, 2014-10-26

23 answers

W końcu znalazłem rozwiązanie. Polega po prostu na nadpisaniu wartości dla colorControlActivated, colorControlHighlight i colorControlNormal w definicji motywu aplikacji, a nie w stylu edittext. Następnie pomyśl, aby użyć tego motywu do jakiejkolwiek aktywności, jakiej pragniesz. Poniżej przykład:

<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>
 463
Author: Laurent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-20 08:02:42

Czułem, że to wymaga odpowiedzi na wypadek, gdyby ktoś chciał zmienić tylko jeden edittext. Robię to tak:

editText.getBackground().mutate().setColorFilter(getResources().getColor(R.color.your_color), PorterDuff.Mode.SRC_ATOP);
 180
Author: hordurh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 10:41:17

Chociaż rozwiązanie Laurentsa jest poprawne, ma pewne wady opisane w komentarzach, ponieważ nie tylko dolna linia EditText jest przyciemniona, ale przycisk Wstecz Toolbar, CheckBoxes itd. też.

Na szczęście v22.1 z appcompat-v7 wprowadziło kilka nowych możliwości. Teraz Można przypisać konkretny motyw tylko do jednego widoku. Prosto z Changelog :

Przestarzałe użycie motywu app:do stylizacji paska narzędzi. Możesz teraz użyć android: theme for toolbars on all API level 7 and higher devices and Android:theme support for all widgets on API level 11 and higher devices.

Więc zamiast ustawiać żądany kolor w motywie globalnym, tworzymy nowy i przypisujemy go tylko do EditText.

Przykład:

<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"/>
 137
Author: reVerse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:43

W Celach Informacyjnych. Można to zmienić w xml używając:

android:backgroundTint="@color/blue"
 90
Author: l-l,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-01 20:59:05

Oto rozwiązanie dla API i powyżej

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
}

Tutaj wpisz opis obrazka

Hope it help

 45
Author: Phan Van Linh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-23 01:48:16

Akceptowana odpowiedź jest nieco bardziej zgodna ze stylem, ale najskuteczniejszą rzeczą do zrobienia jest dodanie atrybutu colorAccent w Twoim stylu AppTheme w następujący sposób:

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

Atrybut colorAccent jest używany do przyciemniania widgetów w całej aplikacji i dlatego powinien być używany do spójności

 34
Author: TanmayP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-05 22:30:07

Jeśli używasz appcompat-v7:22.1.0+ możesz użyć DrawableCompat do odcień widgetów

    public static void tintWidget(View view, int color) {
        Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground());
        DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color));
        view.setBackgroundDrawable(wrappedDrawable);
    }
 28
Author: Felipe Conde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-04 09:24:59

Użycie:

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

To będzie obsługiwać urządzenia pre-Lollipop nie tylko +21

 18
Author: blueware,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 12:24:02

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

 16
Author: Ashwin H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-20 08:50:31

Jednym z szybkich rozwiązań Twojego problemu jest zajrzenie do yourappspackage/build/intermediates/exploded-AAR / com.android.wsparcie / appcompat-v7 / res/ drawable / dla abc_edit_text_material.xml i skopiuj ten plik xml do folderu drawable. Następnie możesz zmienić kolor 9 plików łatek z poziomu tego selektora, aby dopasować je do swoich preferencji.

 12
Author: Peter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-28 08:46:58

Oto część kodu źródłowego TextInputLayout w bibliotece support design(zaktualizowano do wersji 23.2.0), który zmienia kolor linii dolnej EditText w prostszy sposób:

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));
    }
    ...
}

Wydaje się, że cały powyższy kod staje się bezużyteczny teraz w 23.2.0, jeśli chcesz zmienić programowo kolor.

A jeśli chcesz wspierać wszystkie platformy, oto moja metoda:

/**
 * 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);
}
 7
Author: ywwynm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 11:10:19

Ja też zbyt długo tkwiłem w tym problemie.

Wymagałem rozwiązania, które działało zarówno dla wersji powyżej, jak i poniżej v21.

W końcu odkryłem bardzo proste, może nie idealne, ale skuteczne rozwiązanie: po prostu ustaw kolor tła na transparent we właściwościach EditText.

<EditText
    android:background="@android:color/transparent"/>
Mam nadzieję, że to zaoszczędzi komuś czasu.
 7
Author: Mtl Dev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-28 15:29:33

Dla mnie zmodyfikowałem zarówno Kolory AppTheme, jak i wartości.xml zarówno colorControlNormal, jak i colorAccent pomogły mi zmienić kolor obramowania EditText. Jak również kursor i"/", gdy wewnątrz 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>
Oto kolory.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="yellow">#B7EC2A</color>
</resources>

Wyjąłem atrybut android: textCursorDrawable na @null, który umieściłem wewnątrz stylu editText. Kiedy próbowałem tego użyć, Kolory się nie zmieniły.

 6
Author: Emily Alexandra Conroyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-22 16:59:08

To bardzo proste, wystarczy dodać android:backgroundTint atrybut w swoim 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"/>
 6
Author: Pacific P. Regmi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 11:19:45

Możesz ustawić tło edittext na prostokąt z minus padding na lewo, prawo i góra, aby to osiągnąć. Oto przykład 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>

Zastąp kształt selektorem, jeśli chcesz podać inną szerokość i kolor dla focused edittext.

 5
Author: Sfseyhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-07 11:28:26

Używam tej metody, aby zmienić kolor linii z PorterDuff, bez innych drawable.

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);
}
 5
Author: user2721167,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 14:17:59

Jeśli chcesz zmienić dolną linię bez używania kolorów aplikacji, użyj tych linii w motywie:

<item name="android:editTextStyle">@android:style/Widget.EditText</item>
<item name="editTextStyle">@android:style/Widget.EditText</item>
Nie znam innego rozwiązania.
 4
Author: rz0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-05 09:04:58

In Activit.XML Dodaj kod

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

Gdzie BackgroundTint=color dla pożądanego koloru

 4
Author: M.Zanella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-14 00:19:00

Wypracowałem rozwiązanie tego problemu po 2 dniach zmagań, poniżej rozwiązanie jest idealne dla tych, którzy chcą zmienić tylko kilka edycji tekstu, zmienić / przełączyć kolor za pomocą kodu java, i chcą przezwyciężyć problemy różnych zachowań na wersjach systemu operacyjnego ze względu na użycie metody 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();
    }
  }
}

Używa w 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"/>

Dodaj linie w stylu

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

Kod Javy do przełączania kolorów

myRqubeEditText.setErrorState(true);
myRqubeEditText.setErrorState(false);
 3
Author: RQube,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 12:49:01

Byłem absolutnie zdumiony tym problemem. Próbowałem wszystkiego w tym wątku i w innych, ale bez względu na to, co zrobiłem, nie mogłem zmienić koloru podkreślenia na cokolwiek innego niż domyślny niebieski.

W końcu zorientowałem się, co się dzieje. Podczas tworzenia nowej instancji używałem (niepoprawnie) android.widget.EditText (ale reszta moich komponentów pochodziła z biblioteki appcompat). Powinienem był użyć android.support.v7.widget.AppCompatEditText. Zamieniłem new EditText(this) na new AppCompatEditText(this) i problem został natychmiast rozwiązany. Okazuje się, że, jeśli rzeczywiście używasz AppCompatEditText, będzie to po prostu respektować {[5] } z Twojego motywu (jak wspomniano w kilku komentarzach powyżej) i nie jest konieczna dodatkowa konfiguracja.

 2
Author: mkasberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-15 04:05:41

Jest to najprostszy i najbardziej wydajny/wielokrotnego użytku / działa na wszystkich interfejsach API
Tworzenie niestandardowej klasy EditText w ten sposób:

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);
    }
}

Następnie użyj go w ten sposób:

 <company.com.app.EditText
        android:layout_width="200dp"
        android:layout_height="wrap_content"/>
 2
Author: Oliver Dixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-24 15:03:49

Aby dynamicznie zmieniać tło EditText, możesz użyć 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);

Napisy: Ta odpowiedź o ColorStateList jest Super .

 1
Author: Ankit Popli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:25

Proszę zmodyfikować tę metodę w zależności od potrzeb. To mi pomogło!

  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());
        }
 -2
Author: Shahid Sarwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 13:41:22