使用appcompat v7更改EditText底线颜色


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>

根据android API 21的来源,具有材料设计的EditTexts似乎使用colorControlActivatedcolorControlNormal。因此,我试图在以前的样式定义中覆盖这些属性,但没有效果。appcompat可能不使用它。不幸的是,我找不到与材料设计相关的最新版本的appcompat的资源。


定义您的主题以编辑文本
Meenal 2014年

谢谢您的建议,但我已经做到了。我已经更新了我的问题,以显示我已经尝试做的事情。我的问题是关于在主题样式中使用的属性来更改edittext底线颜色。理想情况下,我正在寻找一种可以直接在六边形中指定颜色的解决方案。
洛朗2014年

这些答案均不适用于4.3。您有可行的解决方案吗?
罗伯特·贝克

AppCompatEditText显然,我不得不延长。
EpicPandaForce

Answers:


479

最后,我找到了解决方案。它只是由覆盖的价值colorControlActivatedcolorControlHighlightcolorControlNormal在您的应用程序主题定义,而不是你的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。
2014年

11
这会更改底线的颜色,但也会更改其他所有控件,例如复选框,单选按钮等。它还会更改整个应用程序/活动中的每个EditText。如果要更改单个EditText的底行(就像我一样),则必须覆盖该EditText的android:background属性。AFAIK没有其他方法。
伊曼纽尔·莫克林

68
如果您使用的是AppCompat v22支持库,则可以在EditText中指定主题,例如:android:theme="@style/Theme.App.Base。这将确保样式也不会影响您不想更改的布局中的其他视图。
亚历克斯·洛克伍德

8
未在Jelly Bean(4.2)上工作,但在Lollipop上工作
Mangesh,2015年

3
活动应继承自AppCompatActivity。如果继承自,它将无法正常工作Activity
Bharathwaaj '16

187

我觉得这需要一个答案,以防有人只想更改一个edittext。我这样做是这样的:

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

1
但是我如何重置为默认背景,在Lollipop上调用editText.getBackground()。resetColorFilter()之后,我遇到了很多错误?
Ultraon

警告!添加此内容可能会导致在所有应用程序中更改editText的颜色。在Nexus 5上测试。OS 6.0.1。
Alex Perevozchykov

1
@AlexPerevozchykov你可能是正确的。尝试在.getBackground()之后添加.mutate()。那应该做。
hordurh's

@hordurh是的,就是这样,我早些时候就收到了这个建议,可绘制对象共享一个池,因此在更改之前我们需要对其进行更改
Alex Perevozchykov

1
如果我使用edittext,这是可行的,但此方法不适用于棒棒糖上的应用程序兼容的edittext。您知道我该如何解决该问题?
塞林

145

虽然Laurents的解决方案是正确的,它与作为,因为不仅是底线在评论中描述的一些缺点EditText被染色,但的后退按钮ToolbarCheckBoxes等也是如此。

幸运的v22.1appcompat-v7引入了一些新的可能性。现在可以仅将一个特定主题分配给一个视图。直接来自变更日志

不推荐使用app:theme来设置工具栏样式。现在,您可以在所有API级别7和更高版本的设备上使用 android:theme工具栏,并在API级别11和更高级别的设备上使用android:theme支持所有小部件

因此,我们无需在全局主题中设置所需的颜色,而是创建一种新的颜色并将其仅分配给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方法为小部件着色,而使用前缀则回退到system方法,并且仅在API 21+设备中可用。
2015年

嗯,我在棒棒糖设备上测试过,除非您也使用Android名称空间以v21样式实现它,否则它不会着色自定义颜色。
user2968401 2015年

我使用的22.2.0是AppCompat版本,但此技巧不起作用:(
Shajeel Afzal

1
使用<item name =“ colorAccent”>#000000 </ item>对我有用,而不是colorControlNormal。
MikeOscarEcho

完美地更改应用程序中的一个编辑文本!(正是我需要的!谢谢)
Romain Barbier

99

可以使用以下方法在XML中进行更改:

对于参考API> = 21兼容性,请使用:

android:backgroundTint="@color/blue"

对于<21的向后API兼容性,请使用:

app:backgroundTint="@color/blue"

10
是的,但这仅适用于21+版本的Android API(kitkat和lolipop)。人们可能会尝试创建一种向后兼容的解决方案。
DaMachk

12
只是使用它backgroundTint="@color/blue"而不是android:backgroundTint="@color/blue"为了向后兼容支持
Kishan Vaghela '16

11
@KishanVaghela,而不是使用android:backgroundTint="@color/blue",使用app:backgroundTint="@color/blue"以支持预棒棒糖设备,为您的评论的感谢!
blueware's

2
@blueware如果您想以样式使用它,那么我们不需要使用“ app”。
Kishan Vaghela

tools:ignore="MissingPrefix"如果下划线出现红色下划线,请添加app:backgroundTint="<your color>"
Moses Aprico'Mar 13'13

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.125.1.125.2.0以用于设备<21和> 21,它仍然可以正常工作。请检查此简单的演示drive.google.com/file/d/0B_poNaia6t8kSzU3bDFVazRSSDA/…。我不知道为什么此代码对您不起作用,所以请告诉我。谢谢
Phan Van Linh

@Renjith对不起您的延迟回复,请检查上面的评论
Phan Van Linh

如何使用此代码将颜色重置为默认值?
Neph

35

对于每个样式,可接受的答案要多一些,但是最有效的方法是在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属性用于整个应用程序中的小部件着色,因此应用于保持一致性


8
@Tomasz它不需要API 21+,因为父主题是AppCompat,它下降到了API 7
TanmayP'5

Ughhh。谢谢,我使用的是name="android:colorAccent"错误的
Jules

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

这真是个救命棒,可惜的是它并不
为人所知

请向下移动,查看我对设计库23.2.0的回答。此方法目前无用。
ywwynm '16

21

采用:

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

这不仅支持+21的棒棒糖之前的设备


@ powder366,您可以发布您的应用主题吗?
blueware

1
<style name =“ AppTheme” parent =“ Theme.AppCompat.Light.DarkActionBar”>
powder366 2016年

2
@ powder366,请尝试以下方法:<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">它应该可以工作
blueware's

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,

如果不同的控件需要不同的颜色,这将带来不便。
Julius

12

解决此问题的一种快速解决方案是,在yourappspackage / build / intermediates / 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
API等级21上方的背景色
Ashwin H

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

1
app:backgroundTint="@color/blue"适用于所有api级别。.尽管出于任何原因,在选择XD时它仍会变成不同的颜色
EpicPandaForce

8

这是的部分源代码 TextInputLayout支持设计库(对于版本23.2.0为UPDATED)该库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需要
API16。– CoolMind

8

我也在这个问题上停留了太长时间。

我需要一个适用于高于和低于v21的版本的解决方案。

我终于找到了一个非常简单的也许不是理想的但有效的解决方案:只需transparent在EditText属性中将背景颜色设置为即可。

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

我希望这可以节省一些时间。


1
这将改变整个背景颜色,而我们只想更改下划线颜色。
shahzain ali

@shahzain ali EditText的下划线是背景。如果将其设置为null,它将消失。那就是为什么backgroundTint可以工作的原因(但是激活后它不会改变颜色)
nyconing

7

对我来说,我同时修改了AppTheme和一个values.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
这应该是答案
Mina Samy

像魅力一样工作。谢谢
丹麦夏尔马

6

您可以将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>

如果要为焦点编辑文本提供不同的宽度和颜色,请用选择器替换形状。


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的底行?
雷米P

4

如果要更改底线而不使用应用程序颜色,请在主题中使用以下几行:

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

我不知道另一种解决方案。


4

经过2天的努力,我为这个问题制定了一个可行的解决方案,下面的解决方案非常适合那些只希望更改少量编辑文本,通过Java代码更改/切换颜色并希望克服OS版本上不同行为的问题的人。由于使用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?它需要
API21。– CoolMind

setSupportBackgroundTintList用于较旧的API版本。
Ankit Popli'2

0

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

-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());
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.