简体   繁体   中英

TextInputLayout Password Toggle Listener

I have a TextInputLayout for password. I have added passwordToggleEnabled=true to toggle the password visibility. I need to capture the event when user toggles password visibility. How can I do this.

<android.support.design.widget.TextInputLayout
    android:id="@+id/password_input_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="start|center"
    app:passwordToggleEnabled="true">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/password_edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/enter_new_password"
            android:inputType="textPassword"/>

</android.support.design.widget.TextInputLayout>

In the source of the TextInputLayout the type of the view of the toggle button is CheckableImageButton . You just need to find the view iterating recursively over children of the TextInputLayout View. And then setOnTouchListener .

View togglePasswordButton = findTogglePasswordButton(mTextInputLayoutView);
if (togglePasswordButton != null) {
    togglePasswordButton.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            // implementation
            return false;
        }
    });
}

private View findTogglePasswordButton(ViewGroup viewGroup) {
    int childCount = viewGroup.getChildCount();
    for (int ind = 0; ind < childCount; ind++) {
        View child = viewGroup.getChildAt(ind);
        if (child instanceof ViewGroup) {
            View togglePasswordButton = findTogglePasswordButton((ViewGroup) child);
            if (togglePasswordButton != null) {
                return togglePasswordButton;
            }
        } else if (child instanceof CheckableImageButton) {
            return child;
        }
    }
    return null;
}

Setting only the end icon click listener like proposed in another answer won't work, because doing so will remove the existing listener which is used to toggle the EditText transformation method.

So if you set a new listener, you need to change it yourself:

textInputLayout.setEndIconOnClickListener {
    // Toggle the EditText transformation method from nothing to password or vice versa.
    // Selection is lost in the process so make sure to restore it.
    val editText = textInputLayout.editText
    val oldSelection = editText.selectionEnd
    val hidePassword = editText.transformationMethod !is PasswordTransformationMethod
    passwordEdt.transformationMethod = PasswordTransformationMethod.getInstance().takeIf { hidePassword }
    if (oldSelection >= 0) {
        passwordEdt.setSelection(oldSelection)
    }

    // Do your own stuff here.
}

Please check this answer, if you are still looking for a complete solution about TextInputLayout Password Toggle Listener:

    public class SampleActivity extends AppCompatActivity {

    TextInputLayout password_input_layout;
    TextInputEditText password_edit_text;

    //textInputLayoutEndIconPressed will be tracked, EndIcon is pressed and toggled or not
    private boolean textInputLayoutEndIconPressed;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textInputLayoutEndIconPressed = false;
        password_input_layout = (TextInputLayout) findViewById(R.id.password_input_layout);
        password_edit_text = (TextInputEditText) findViewById(R.id.password_edit_text);

        password_input_layout.setEndIconOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(!textInputLayoutEndIconPressed)
                    textInputLayoutEndIconPressed = true;
                else
                    textInputLayoutEndIconPressed = false;

                if(textInputLayoutEndIconPressed){
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //Changing Drawable file
                            password_input_layout.setEndIconDrawable(getResources().getDrawable(R.drawable.ic_visibility_on));
                            //Changing TextInputEditText password text to open
                            password_edit_text.setTransformationMethod(null);
                        }
                    });
                }else{
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //Changing Drawable file
                            password_input_layout.setEndIconDrawable(getResources().getDrawable(R.drawable.ic_visibility_off));
                            //Changing TextInputEditText password text to hide
                            password_edit_text.setTransformationMethod(new PasswordTransformationMethod());
                        }
                    });
                }
            }
        });

    }
}

When you set a EndIconOnClickListener, then you need to check both TextInputEditText text status and TextInputLayout EndIcon Drawable file. So you can manage this scenario like this.

Please see my answer here , but in short you can do the following since Material Components v1.1.0 (Kotlin):

textInputLayout.setEndIconOnClickListener {
    // do something here
}

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