首页 文章

使用appcompat v7更改EditText底线颜色

提问于
浏览
284

我正在使用appcompat v7在Android 5及更低版本上获得一致的外观 . 它工作得很好 . 但是我无法弄清楚如何更改EditTexts的底线颜色和重点颜色 . 可能吗?

我试图定义一个自定义 android:editTextStyle (参见下文),但我只是成功更改了完整的背景颜色或文本颜色,但没有更改底线和强调颜色 . 是否有特定的 property Value ?我必须通过 android:background 属性使用自定义可绘制图像吗?是不是可以用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>

根据android API 21的消息,使用材质设计的EditTexts似乎使用 colorControlActivatedcolorControlNormal . 因此,我试图在先前的样式定义中覆盖这些属性,但它没有任何效果 . 可能appcompat不使用它 . 不幸的是,我找不到最后一个版本的appcompat的材料设计来源 .

23 回答

  • 138

    最后,我找到了解决方案 . 它只是覆盖了应用主题定义中 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>
    
  • 1

    我觉得这需要一个答案,以防有人想改变一个编辑文本 . 我是这样做的:

    editText.getBackground().mutate().setColorFilter(getResources().getColor(R.color.your_color), PorterDuff.Mode.SRC_ATOP);
    
  • 34

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

    如果要为聚焦的edittext提供不同的宽度和颜色,请使用选择器替换形状 .

  • 2

    虽然Laurents solution是正确的,但它有一些缺点,如评论中所述,因为不仅 EditText 的底线有色,而且 Toolbar 的后退按钮, CheckBoxes 等也是如此 .

    幸运的是 v22.1appcompat-v7 引入了一些新的可能性 . 现在可以仅将特定主题分配给一个视图 . 直接从Changelog

    已弃用app:主题用于样式工具栏 . 现在,您可以在所有API级别7及更高版本的设备上使用android:theme进行工具栏,对API级别11及更高版本的设备上的所有小部件使用android:theme支持 .

    因此,我们不是在全局主题中设置所需的颜色,而是创建一个新的颜色并仅将其分配给 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"/>
    
  • 180

    以供参考 . 这可以通过使用以下方式在xml中更改:

    android:backgroundTint="@color/blue"
    
  • 2

    这是 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
    }
    

    enter image description here

    希望它有所帮助

  • 5

    接受的答案是每个样式基础更多一点,但最有效的方法是在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属性用于整个应用程序中的窗口小部件着色,因此应该用于一致性

  • 90

    如果您使用 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);
        }
    
  • 19

    使用:

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

    这将支持前Lollipop设备不仅21

  • 4
    <!-- 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>
    
  • 465

    解决问题的一个快速解决方案是查看yourappspackage / build / intermediates / explosion-aar / com.android.support / appcompat -v7 / res / drawable / for abc_edit_text_material.xml并将该xml文件复制到drawable文件夹中 . 然后,您可以从此选择器内更改9个补丁文件的颜色,以匹配您的首选项 .

  • 12

    以下是支持设计库( UPDATED for version 23.2.0 )中 TextInputLayout 的源代码的一部分,它以更简单的方式更改 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);
    }
    
  • 16

    我也被困在这个问题上太久了 .

    我需要一个适用于v21以上和以下版本的解决方案 .

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

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

    我希望这能节省一些时间 .

  • 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属性取出到了我放在editText样式中的@null . 当我尝试使用它时,颜色不会改变 .

  • 4

    只需在 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"/>
    
  • -2

    我使用这种方法来改变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);
    }
    
  • 7

    如果您想在不使用app颜色的情况下更改底线,请在主题中使用以下行:

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

    我不知道另一个解决方案 .

  • 6

    经过2天的努力,我找到了解决这个问题的有效方案,下面的解决方案非常适合他们只想改变一些编辑文本,通过java代码更改/切换颜色,并希望克服由于使用setColorFilter()方法而在OS版本上出现的不同行为问题 .

    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);
    
  • 45

    在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 为您所需的颜色

  • 6

    我对这个问题感到非常困惑 . 我已经尝试了这个线程中的所有内容,而在其他线程中,但无论我做了什么,我都无法将下划线的颜色更改为默认蓝色以外的任何其他颜色 .

    我终于弄清楚发生了什么 . 在制作新实例时我(错误地)使用了 android.widget.EditText (但我的其他组件来自appcompat库) . 我本应该用 android.support.v7.widget.AppCompatEditText . 我用 new AppCompatEditText(this) 替换 new EditText(this) ,问题立即得到解决 . 事实证明,如果你实际上正在使用 AppCompatEditText ,它只会尊重你主题的 accentColor (如上面的几条评论所述),不需要额外的配置 .

  • 6

    这是最简单,最有效/可重用/适用于所有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"/>
    
  • 28

    要动态更改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);
    

    致谢:This SO answer about ColorStateList is awesome .

  • 4

    请根据您的需要修改此方法 . 这对我有用!

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

相关问题