简体   繁体   English

使用 appcompat v7 更改 EditText 底线颜色

[英]Changing EditText bottom line color with appcompat v7

I am using appcompat v7 to get the look consistent on Android 5 and less.我正在使用 appcompat v7 在 Android 5 及更低版本上获得一致的外观。 It works rather well.它工作得很好。 However I cannot figure out how to change the bottom line color and the accent color for EditTexts.但是我无法弄清楚如何更改 EditTexts 的底线颜色和强调色。 Is it possible?是否可以?

I have tried to define a custom android:editTextStyle (cf. below) but I only succeeded to change the full background color or text color but not the bottom line nor the accent color.我试图定义一个自定义的android:editTextStyle (参见下面),但我只成功地改变了完整的背景颜色或文本颜色,而不是底线或强调色。 Is there a specific property value to use?是否有要使用的特定属性值? do I have to use a custom drawable image through the android:background property?我是否必须通过android:background属性使用自定义可绘制图像? is it not possible to specify a color in hexa?不能在 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>

According to android API 21 sources, EditTexts with material design seem to use colorControlActivated and colorControlNormal .根据 android API 21 来源,具有材料设计的 EditTexts 似乎使用colorControlActivatedcolorControlNormal Therefore, I have tried to override these properties in the previous style definition but it has no effect.因此,我尝试在之前的样式定义中覆盖这些属性,但没有效果。 Probably appcompat does not use it.可能 appcompat 不使用它。 Unfortunately, I cannot find the sources for the last version of appcompat with material design.不幸的是,我找不到带有材料设计的 appcompat 最新版本的来源。

Finally, I have found a solution.最后,我找到了解决方案。 It simply consists of overriding the value for colorControlActivated , colorControlHighlight and colorControlNormal in your app theme definition and not your edittext style.它只包括在您的应用程序主题定义中覆盖colorControlActivatedcolorControlHighlightcolorControlNormal的值,而不是您的 edittext 样式。 Then, think to use this theme for whatever activity you desire.然后,考虑将此主题用于您想要的任何活动。 Below is an example:下面是一个例子:

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

I felt like this needed an answer in case somebody wanted to change just a single edittext.我觉得这需要一个答案,以防有人只想更改一个编辑文本。 I do it like this:我这样做:

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

While Laurents solution is correct, it comes with some drawbacks as described in the comments since not only the bottom line of the EditText gets tinted but the Back Button of the Toolbar , CheckBoxes etc. as well.虽然Laurents 解决方案是正确的,但它有一些缺点,如评论中所述,因为不仅EditText的底线被着色,而且Toolbar的后退按钮、 CheckBoxes等也被着色。

Luckily v22.1 of appcompat-v7 introduced some new possibilities.幸运的是v22.1appcompat-v7引入了一些新的可能性。 Now it's possible to assign a specific theme only to one view.现在可以仅将特定主题分配给一个视图。 Straight from the Changelog :直接来自更新日志

Deprecated use of app:theme for styling Toolbar.不推荐使用 app:theme 样式工具栏。 You can now use 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.您现在可以将android:theme 用于所有 API 级别 7 和更高级别设备上的工具栏,并API 级别 11 和更高级别设备上的所有小部件使用android:theme支持。

So instead of setting the desired color in a global theme, we create a new one and assign it only to the EditText .因此,我们不是在全局主题中设置所需的颜色,而是创建一个新颜色并将其仅分配给EditText

Example:例子:

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

This can be changed in XML by using:这可以通过使用在 XML 中更改:

For Reference API >= 21 compatibility use:对于参考 API >= 21 兼容性使用:

android:backgroundTint="@color/blue"

For backward API < 21 compatibility use:对于向后 API < 21 兼容性使用:

app:backgroundTint="@color/blue"

Here is the solution for API < 21 and above这是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
}

在此处输入图片说明

Hope it help希望有帮助

The accepted answer is a bit more per style basis thing, but the most efficient thing to do is to add the colorAccent attribute in your AppTheme style like this:接受的答案是基于样式的更多内容,但最有效的做法是在 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"/>

The colorAccent attribute is used for widget tinting throughout the app and thus should be used for consistency colorAccent 属性用于整个应用程序的小部件着色,因此应用于一致性

If you are using appcompat-v7:22.1.0+ you can use the DrawableCompat to tint your widgets如果您使用的是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>

Use:用:

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

This will support pre-Lollipop devices not only +21这将不仅支持棒棒糖之前的设备 +21

One quick solution for your problem is to look in yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/ for abc_edit_text_material.xml and copy that xml file in your drawable folder.您的问题的一种快速解决方案是在 yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/ 中查找 abc_edit_text_material.xml 并将该 xml 文件复制到您的 drawable 文件夹中。 Then you can change the colour of the 9 patch files from inside this selector, in order to match your preferences.然后您可以在此选择器中更改 9 个补丁文件的颜色,以匹配您的偏好。

It's very easy just add android:backgroundTint attribute in your EditText .只需在EditText添加android:backgroundTint属性就很容易了。

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

Here is a part of source code of TextInputLayout in support design library( UPDATED for version 23.2.0 ), which changes EditText 's bottom line color in a simpler way:这是支持设计库中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));
    }
    ...
}

It seems that all of above code become useless right now in 23.2.0 if you want to change the color programatically.如果您想以编程方式更改颜色,似乎上述所有代码现在在 23.2.0 中都变得无用了。

And if you want to support all platforms, here is my method:如果你想支持所有平台,这是我的方法:

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

I too was stuck on this problem for too long.我也被这个问题困了太久了。

I required a solution that worked for versions both above and below v21.我需要一个适用于 v21 以上和以下版本的解决方案。

I finally discovered a very simple perhaps not ideal but effective solution: Simply set the background colour to transparent in the EditText properties.我终于发现了一个非常简单的可能并不理想但有效的解决方案:只需在 EditText 属性中将背景颜色设置为transparent即可。

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

I hope this saves someone some time.我希望这可以节省一些时间。

For me I modified both the AppTheme and a value colors.xml Both the colorControlNormal and the colorAccent helped me change the EditText border color.对我来说,我修改了 AppTheme 和一个值 colors.xml colorControlNormal 和 colorAccent 都帮助我更改了 EditText 边框颜色。 As well as the cursor, and the "|"以及光标和“|” when inside an 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>

Here is the colors.xml这是colors.xml

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

I took out the android:textCursorDrawable attribute to @null that I placed inside the editText style.我将 android:textCursorDrawable 属性取出到 @null 中,我放置在 editText 样式中。 When I tried using this, the colors would not change.当我尝试使用它时,颜色不会改变。

You can set background of edittext to a rectangle with minus padding on left, right and top to achieve this.您可以将 edittext 的背景设置为在左侧、右侧和顶部带有减号填充的矩形以实现此目的。 Here is the xml example:这是 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>

Replace the shape with a selector if you want to provide different width and color for focused edittext.如果您想为焦点编辑文本提供不同的宽度和颜色,请用选择器替换该形状。

I use this method to change the color of the line with PorterDuff, with no other drawable.我使用此方法通过 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);
}

In Activit.XML add the code在 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"/>

Where BackgroundTint=color for your desired colour其中BackgroundTint=color为您想要的颜色

If you want change bottom line without using app colors, use these lines in your theme:如果您想在不使用应用颜色的情况下更改底线,请在您的主题中使用以下几行:

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

I don't know another solution.我不知道另一种解决方案。

I worked out a working solution to this problem after 2 days of struggle, below solution is perfect for them who want to change few edit text only, change/toggle color through java code, and want to overcome the problems of different behavior on OS versions due to use setColorFilter() method.经过 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();
    }
  }
}

Uses in xml在 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"/>

Add lines in style在样式中添加线条

<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 code to toggle color切换颜色的java代码

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

I was absolutely baffled by this problem.我完全被这个问题搞糊涂了。 I had tried everything in this thread, and in others, but no matter what I did I could not change the color of the underline to anything other than the default blue.我已经尝试了这个线程和其他线程中的所有内容,但无论我做什么,我都无法将下划线的颜色更改为默认蓝色以外的任何颜色。

I finally figured out what was going on.我终于明白是怎么回事了。 I was (incorrectly) using android.widget.EditText when making a new instance (but the rest of my components were from the appcompat library).我在创建新实例时(错误地)使用了android.widget.EditText (但我的其余组件来自 appcompat 库)。 I should have used android.support.v7.widget.AppCompatEditText .我应该使用android.support.v7.widget.AppCompatEditText I replaced new EditText(this) with new AppCompatEditText(this) and the problem was instantly solved.我用new AppCompatEditText(this)替换了new EditText(this) ,问题立即解决了。 It turns out, if you are actually using AppCompatEditText , it will just respect the accentColor from your theme (as mentioned in several comments above) and no additional configuration is necessary.事实证明,如果您实际使用AppCompatEditText ,它只会尊重您的主题中的accentColor (如上面的几条评论中所述),并且不需要额外的配置。

This is the easiest and most efficient/reusable/works on all APIs这是最简单和最有效/可重用/适用于所有 API 的方法
Create a custom EditText class like so:创建一个自定义 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);
    }
}

Then use it like this:然后像这样使用它:

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

To change the EditText background dynamically, you can use ColorStateList .要动态更改 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);

Credits: This SO answer about ColorStateList is awesome .积分:这个关于 ColorStateList 的 SO 答案很棒

Add app:backgroundTint for below api level 21. Otherwise use android:backgroundTint .添加app:backgroundTint低于 api 级别 21。否则使用android:backgroundTint

For below api level 21.对于低于 api 级别 21。

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

For higher than api level 21.对于高于 api 级别 21。

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

You can use just backgroundTint for change bottom line color of edit text您可以仅使用 backgroundTint 来更改编辑文本的底线颜色

 android:backgroundTint="#000000"

example :例子 :

 <EditText
          android:id="@+id/title1"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:backgroundTint="#000000" />

Please modify this method according to your need.请根据您的需要修改此方法。 This worked for me!这对我有用!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM