繁体   English   中英

使用 appcompat v7 更改 EditText 底线颜色

[英]Changing EditText bottom line color with appcompat v7

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

我试图定义一个自定义的android:editTextStyle (参见下面),但我只成功地改变了完整的背景颜色或文本颜色,而不是底线或强调色。 是否有要使用的特定属性值? 我是否必须通过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 最新版本的来源。

最后,我找到了解决方案。 它只包括在您的应用程序主题定义中覆盖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>

我觉得这需要一个答案,以防有人只想更改一个编辑文本。 我这样做:

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

虽然Laurents 解决方案是正确的,但它有一些缺点,如评论中所述,因为不仅EditText的底线被着色,而且Toolbar的后退按钮、 CheckBoxes等也被着色。

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

不推荐使用 app:theme 样式工具栏。 您现在可以将android:theme 用于所有 API 级别 7 和更高级别设备上的工具栏,并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"/>

这可以通过使用在 XML 中更改:

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

android:backgroundTint="@color/blue"

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

app: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
}

在此处输入图片说明

希望有帮助

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

如果您使用的是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"/>

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

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

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

这是支持设计库中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);
}

我也被这个问题困了太久了。

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

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

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

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

对我来说,我修改了 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 样式中。 当我尝试使用它时,颜色不会改变。

您可以将 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为您想要的颜色

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

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

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

经过 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);

我完全被这个问题搞糊涂了。 我已经尝试了这个线程和其他线程中的所有内容,但无论我做什么,我都无法将下划线的颜色更改为默认蓝色以外的任何颜色。

我终于明白是怎么回事了。 我在创建新实例时(错误地)使用了android.widget.EditText (但我的其余组件来自 appcompat 库)。 我应该使用android.support.v7.widget.AppCompatEditText 我用new AppCompatEditText(this)替换了new EditText(this) ,问题立即解决了。 事实证明,如果您实际使用AppCompatEditText ,它只会尊重您的主题中的accentColor (如上面的几条评论中所述),并且不需要额外的配置。

这是最简单和最有效/可重用/适用于所有 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 的 SO 答案很棒

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

您可以仅使用 backgroundTint 来更改编辑文本的底线颜色

 android:backgroundTint="#000000"

例子 :

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

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

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