Изменение цвета нижней строки 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 Android 21, EditTexts с дизайном материала, кажется, используют colorControlActivated
а также colorControlNormal
, Поэтому я попытался переопределить эти свойства в предыдущем определении стиля, но это не имеет никакого эффекта. Вероятно, appcompat не использует его. К сожалению, я не могу найти источники для последней версии appcompat с дизайном материала.
23 ответа
Наконец-то я нашел решение. Это просто состоит в переопределении значения для colorControlActivated
, colorControlHighlight
а также colorControlNormal
в определении темы вашего приложения, а не в стиле редактирования текста. Затем подумайте, чтобы использовать эту тему для любой деятельности, которую вы хотите. Ниже приведен пример:
<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>
Я чувствовал, что для этого нужен ответ на случай, если кто-то захочет изменить только один текст редактирования. Я делаю это так:
editText.getBackground().mutate().setColorFilter(getResources().getColor(R.color.your_color), PorterDuff.Mode.SRC_ATOP);
Хотя решение Laurents является правильным, оно имеет некоторые недостатки, как описано в комментариях, поскольку не только нижняя строка EditText
тонируется, но кнопка "Назад" Toolbar
, CheckBoxes
и т. д.
к счастью v22.1
из appcompat-v7
представил некоторые новые возможности. Теперь можно назначить конкретную тему только одному представлению. Прямо из журнала изменений:
Устаревшее использование app: тема для оформления панели инструментов. Теперь вы можете использовать android:theme для панелей инструментов на всех устройствах уровня API 7 и выше, а также android:theme theme для всех виджетов на устройствах уровня 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"/>
Для справки. Это может быть изменено в XML с помощью:
android:backgroundTint="@color/blue"
Вот решение для 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
}
Надеюсь, это поможет
Принятый ответ немного больше для каждого стиля, но наиболее эффективный способ - добавить атрибут 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 используется для тонирования виджетов во всем приложении и, следовательно, должен использоваться для согласованности
Если вы используете 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);
}
<!-- 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>
Использование:
<EditText
app:backgroundTint="@color/blue"/>
Это будет поддерживать устройства pre-Lollipop не только +21
Одним из быстрых решений вашей проблемы является поиск в yourappspackage/build/ промежуточные /exploded-aar/com.android.support/appcompat-v7/res/drawable/ для abc_edit_text_material.xml и копирование этого XML-файла в папку для рисования. Затем вы можете изменить цвет 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"/>
Я тоже застрял на этой проблеме слишком долго.
Мне нужно решение, которое работало для версий выше и ниже v21.
Наконец, я обнаружил очень простое, возможно, не идеальное, но эффективное решение: просто установите цвет фона на transparent
в свойствах EditText.
<EditText
android:background="@android:color/transparent"/>
Надеюсь, это сэкономит кому-то время.
Вот часть исходного кода 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);
}
Для меня я изменил и 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. Когда я попытался использовать это, цвета не изменились.
Вы можете установить фон редактируемого текста в прямоугольник с минусовой заливкой слева, справа и сверху, чтобы добиться этого. Вот пример 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>
Замените фигуру селектором, если вы хотите предоставить другую ширину и цвет для сфокусированного текста редактирования.
Я использую этот метод, чтобы изменить цвет линии с помощью 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);
}
В 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
для вашего желаемого цвета
Я разработал рабочее решение этой проблемы после 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);
Если вы хотите изменить нижнюю строку без использования цветов приложения, используйте эти строки в своей теме:
<item name="android:editTextStyle">@android:style/Widget.EditText</item>
<item name="editTextStyle">@android:style/Widget.EditText</item>
Я не знаю другого решения.
Это самый простой и эффективный / многократно используемый / работает на всех 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"/>
Для динамического изменения фона 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 является удивительным.
Я был совершенно сбит с толку этой проблемой. Я пробовал все в этой теме и в других, но что бы я ни делал, я не мог изменить цвет подчеркивания на что-либо, кроме синего по умолчанию.
Я наконец понял, что происходит. Я (неправильно) пользуюсь android.widget.EditText
при создании нового экземпляра (но остальные мои компоненты были из библиотеки appcompat). Я должен был использовать android.support.v7.widget.AppCompatEditText
, Я заменил new EditText(this)
с new AppCompatEditText(this)
и проблема была мгновенно решена. Оказывается, если вы на самом деле используете AppCompatEditText
Буду уважать accentColor
из вашей темы (как уже упоминалось в нескольких комментариях выше), и никаких дополнительных настроек не требуется.
Вы можете использовать только backgroundTint для изменения цвета нижней строки редактируемого текста
android:backgroundTint="#000000"
пример:
<EditText
android:id="@+id/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#000000" />
Добавлять app:backgroundTint
для уровня API ниже 21. В противном случае используйте 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"/>
Для более высоких уровней API 21.
<EditText
android:id="@+id/edt_name"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="#0012ff"
android:backgroundTint="#0012ff"/>
Пожалуйста, измените этот метод в соответствии с вашими потребностями. Это сработало для меня!
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());
}