简体   繁体   中英

How to change color of the password toggle in TextInputLayout?

I need to change color of the password toggle in TextInputLayout if EditText is focused or not. I've done it this way but it's not working. The color is always equals color light grey (from state focused = false)

layout

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleEnabled="true"
        app:passwordToggleDrawable="@drawable/password_toggle_selector"
        app:passwordToggleTint="@color/color_password_toggle">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>

color_password_toggle

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/color_green" android:state_checked="true"  />
    <item android:color="@color/color_grey" android:state_focused="true" />
    <item android:color="@color/color_light_grey" android:state_focused="false" />

password_toggle_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_eye" android:state_checked="true />
    <item android:drawable="@drawable/ic_eye_off" />

With the TextInputLayout included in Material Components library the passwordToggleTint attribute (the icon to use for the password input visibility toggle) is deprecated .

Now just use the endIconTint attribute.

<com.google.android.material.textfield.TextInputLayout
    ...
    app:endIconMode="password_toggle"
    android:hint="Password"
    style="@style/FilledBoxEndIconTint">

    <com.google.android.material.textfield.TextInputEditText
         ...
         android:inputType="textPassword"/>

</com.google.android.material.textfield.TextInputLayout>

with:

  <style name="FilledBoxEndIconTint" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
    <item name="endIconTint">@color/my_selector_color</item>
  </style>

You can use a color or a selector.

在此处输入图像描述

You can also use the app:endIconTint attribute in the layout:

 <com.google.android.material.textfield.TextInputLayout
            ...
            app:endIconMode="password_toggle"
            android:hint="Password"
            app:endIconTint="@color/my_selector_color">

The default selector is:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="?attr/colorPrimary" android:state_activated="true"/>
  <item android:alpha="0.38" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
  <item android:alpha="0.6" android:color="?attr/colorOnSurface"/>
</selector>

I used: app:passwordToggleTint="@android:color/black" inside TextInputLayout

Create color_password_toggle.xml in res/color directory:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_green" android:state_checked="true"  />
<item android:color="@color/color_light_grey" android:state_checked="false" />

And you can remove the custom icon to use the default eye icon:

<android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/color_password_toggle">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>

It seems that when TextInputEditText gains focus, it does not set TextInputLayout state to state_activated .

However, it is easy to achieve that if you create your own version of TextInputEditText .

class MyTextInputEditText : TextInputEditText {
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context) : super(context)

    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        getTextInputLayout()?.setEndIconActivated(focused)
    }

    //copied from TextInputEditText (why this is private?)
    private fun getTextInputLayout(): TextInputLayout? {
        var parent = parent
        while (parent is View) {
            if (parent is TextInputLayout) {
                return parent
            }
            parent = parent.getParent()
        }
        return null
    }
}

And basically just do what @gabriele-mariotti recommended, create a selector combining android:state_activated , android:state_enabled and android:state_checked for your needs.

I've suggested a change in the Material library, check the PR on GitHub.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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