修改 EditText 下划线及被激活后的颜色

6,034 阅读4分钟

继承自 AppCompatActivity

在开发中,我们经常用到 EditText,一般 EditText 默认样式不能满足我们的需求。下面说下常用的两种修改方法。

  • android:theme 方式修改
  • 自定义样式

android:theme 方式修改

<style name="EditTextStyle">
    <!--表示控件默认的颜色-->
    <item name="android:colorControlNormal">#ccc</item>
    <!--表示控件被激活时的颜色-->
    <item name="android:colorControlActivated">#ccc</item>
</style>

在 EditText 上加上 android:theme="@style/EditTextStyle" 属性。请记住是 android:theme 而不是 style

自定义样式

EditText 有一个属性:android:textCursorDrawable ,它就是用来设置光标样式的。如果将 textCursorDrawable 设置为 @null ,表示去除系统默认的样式,但我们都记得隐藏光标的属性是 android:cursorVisible , 那么这时光标会是什么样子的呢?这是我们给文字(android:textColor)和提示文字(android:textColorHint属性)设置不同的颜色,运行之后就会发现此时光标的颜色是跟文字的保持一致的。

设置光标的样式

在drawable资源文件夹下新建一个 cursor_color.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:width="2dp" />
    <solid android:color="@android:color/holo_blue_light" />
</shape>

在 EditText 中使用

<EditText
    android:textCursorDrawable="@drawable/cursor_color"
    android:hint="自定义光标颜色"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

EditText 取消背景

我们发现将 EditText android:textCursorDrawable 设置为"@null"之后,光标的样式会变得跟文字的颜色一样,如果我们将整个EditText的背景设置为"@null"之后,再给EditText添加 android:background="@null",如果EditText没有获取焦点看上去跟TextView效果一样。

全局修改EditText颜色

我们可以直接修改 Style.xml 中样式,来实现全局修改EditText颜色。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <!--标题栏的颜色-->
    <item name="colorPrimary">@color/colorPrimary</item>
    <!--状态栏的颜色-->
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <!--EditText默认颜色-->
    <item name="colorAccent">@color/colorAccent</item>
</style>

如果继承自Activity时自定义下划线

如果继承 Activity,上面的方式,虽然光标的颜色虽然还能修改,但是下划线的颜色却改不了。

EditText是一个输入框,我们可以这样理解:下划线无非就是给输入框的下边框加一条线。这个用Android中的layer-list(图层)就可以做到。新建两个xml文件:et_underline_unselected.xmlet_underline_selected.xml,前者是EditText被选中时的背景,后者则是未被选中时的背景:

et_underline_unselected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="0dp"
        android:left="-2dp"
        android:right="-2dp"
        android:top="-2dp">
        <shape>
            <solid android:color="@android:color/transparent" />
            <stroke
                android:width="1dp"
                android:color="@android:color/darker_gray" />
            <padding android:bottom="4dp" />
        </shape>
    </item>

</layer-list>

et_underline_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:bottom="0dp"
        android:left="-2dp"
        android:right="-2dp"
        android:top="-2dp">
        <shape>
            <solid android:color="@android:color/transparent" />
            <stroke
                android:color="@android:color/holo_green_light"
                android:width="2dp" />
            <padding android:bottom="4dp" />

        </shape>
    </item>

</layer-list>

我将layer-list理解成一个图层列表,shape就是列表中的一个item,由于我们只需要下边框有横线,所以除了shape在列表中的下边距外都设为负值。光标和下划线之间要有点距离,所以shape的下方内边距设为4dp。当然,被选中时的下划线宽度要大一点。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.lindroid.edittext.SecondActivity">

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="3dp"
        android:background="@null"
        android:hint="自定义EditText下划线1"
        android:textCursorDrawable="@drawable/cursor_color" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="3dp"
        android:background="@null"
        android:hint="自定义EditText下划线2"
        android:textCursorDrawable="@drawable/cursor_color" />
</LinearLayout>
/**初始化EditText,默认都为未选中状态**/
editText1.setBackgroundResource(R.drawable.et_underline_unselected);
editText2.setBackgroundResource(R.drawable.et_underline_unselected);
/**第一个EditText的焦点监听事件**/
editText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            Log.e(TAG, "EditText1获得焦点");
            editText1.setBackgroundResource(R.drawable.et_underline_selected);

        } else {
            Log.e(TAG, "EditText1失去焦点");
            editText1.setBackgroundResource(R.drawable.et_underline_unselected);
        }
    }
});
/**第二个EditText的焦点监听事件**/
editText2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            Log.e(TAG, "EditText2获得焦点");
            editText2.setBackgroundResource(R.drawable.et_underline_selected);

        } else {
            Log.e(TAG, "EditText2失去焦点");
            editText2.setBackgroundResource(R.drawable.et_underline_unselected);
        }
    }
});

我们可以将选中和未选中的状态封装到状态选择器中。在drawable文件夹下新建一个et_underline_selector.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:drawable="@drawable/et_underline_unselected"/>
    <item android:state_focused="true" android:drawable="@drawable/et_underline_selected"/>
</selector>

android:state_focused 表示控件是否获得焦点。然后在布局文件中设置 android:background="@drawable/et_underline_selector" ,Activity的焦点监听代码删去就可以了。






About Me