Skip to content Skip to sidebar Skip to footer

Android. Textinputlayout. Toggle Password Visibility Event Listener?

There is a password visibility toggle button within TextInputLayout for InputType textPassword. Is it somehow possible to catch toggle events? I couldn't find any public methods fo

Solution 1:

I looked at the source code of the TextInputLayout to find the type of the view of the toggle button. Its CheckableImageButton. Everything else is easy. You need to find the view iterating recursively over children of the TextInputLayout View. And then setOnTouchListener as @MikeM suggested in the comments.

ViewtogglePasswordButton= findTogglePasswordButton(mTextInputLayoutView);
if (togglePasswordButton != null) {
    togglePasswordButton.setOnTouchListener(newView.OnTouchListener() {
        @OverridepublicbooleanonTouch(View view, MotionEvent motionEvent) {
            // implementationreturnfalse;
        }
    });
}

private View findTogglePasswordButton(ViewGroup viewGroup) {
    intchildCount= viewGroup.getChildCount();
    for (intind=0; ind < childCount; ind++) {
        Viewchild= viewGroup.getChildAt(ind);
        if (child instanceof ViewGroup) {
            ViewtogglePasswordButton= findTogglePasswordButton((ViewGroup) child);
            if (togglePasswordButton != null) {
                return togglePasswordButton;
            }
        } elseif (child instanceof CheckableImageButton) {
            return child;
        }
    }
    returnnull;
}

An alternative implmentation of findTogglePasswordButton

private View findTogglePasswordButton() {
    return findViewById(R.id.text_input_password_toggle);
}

@MikeM. thank you for id

Solution 2:

You can use this:

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.design.widget.CheckableImageButton;
import android.support.design.widget.TextInputLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.ctm.core.ui.R;

import org.jetbrains.annotations.NotNull;

/**
 * Extended {@link TextInputLayout} allowing setting a listener when the user toggles the visibility
 * of the password.
 */publicclassTextInputLayoutExextendsTextInputLayout {

    publicTextInputLayoutEx(Context context) {
        super(context);
    }

    publicTextInputLayoutEx(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    publicTextInputLayoutEx(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    publicvoidsetOnToggleShowPasswordListener(OnToggleShowPasswordListener listener) {
        if (listener != null) {
            initTogglePasswordShownListener(listener);
        }
    }

    @SuppressLint({"RestrictedApi"})privatevoidinitTogglePasswordShownListener(@NotNull OnToggleShowPasswordListener listener) {
        finalViewrevealPasswordView=this.findViewById(R.id.text_input_password_toggle);
        if (revealPasswordView == null) {
            return;
        }
        if (!(revealPasswordView instanceof CheckableImageButton)) {
            return;
        }

        finalCheckableImageButtonrevealPasswordCheckableImageButton= (CheckableImageButton) revealPasswordView;
        revealPasswordView.setOnTouchListener((view, motionEvent) -> {
            if (MotionEvent.ACTION_UP == motionEvent.getAction()) {
                listener.onToggleShowPasswordClicked(!revealPasswordCheckableImageButton.isChecked());
                return view.performClick();
            }
            returnfalse;
        });
    }

    publicinterfaceOnToggleShowPasswordListener {
        voidonToggleShowPasswordClicked(boolean isShown);
    }
}

In client code:

TextInputLayoutExlayoutPassword= (TextInputLayoutEx) findByById(...)
layoutPassword.setPasswordVisibilityToggleEnabled(true);
        layoutPassword.setOnToggleShowPasswordListener(isShown -> Toast.makeText(SignInActivity.this, "Password shown: " + isShown, Toast.LENGTH_SHORT).show());

Solution 3:

After analyzing the View hierarchy with Layout Inspector I can see the following:

View Hierarchy screenshot

So you can either do:

val toggle = password.findViewById<CheckableImageButton?>(R.id.text_input_password_toggle)
toggle?.setOnClickListener {
    println("clicked on toggle")
}

or manually:

// Assuming you have AndroidKTX
val views = password.children
for (v in views) {
    if (v is FrameLayout) {
        val innerViews = v.children
        for (iv in innerViews) {
            if (iv is CheckableImageButton) {
                iv.setOnClickListener { 
                    println("clicked on toggle")
                }
            }
        }
    }
}

Solution 4:

I'm using binding here.

This is the id of the layout - regPasswordlayout default id of the password toggle - text_input_password_toggle

binding.regPasswordlayout.findViewById(R.id.text_input_password_toggle)
.setOnClickListener(newView.OnClickListener() {
         @OverridepublicvoidonClick(View v) {
              // your code goes here
         }
     });

Solution 5:

You can do the following since Material Components v1.1.0 (Kotlin):

textInputLayout.setEndIconOnClickListener {
    //do something here
}

Post a Comment for "Android. Textinputlayout. Toggle Password Visibility Event Listener?"