Android. TextInputLayout. Toggle password visibility event listener?

筅森魡賤 提交于 2019-12-12 20:58:31

问题


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 for this


回答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.

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;
}

An alternative implmentation of findTogglePasswordButton

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

@MikeM. thank you for id




回答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.
 */
public class TextInputLayoutEx extends TextInputLayout {

    public TextInputLayoutEx(Context context) {
        super(context);
    }

    public TextInputLayoutEx(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    public void setOnToggleShowPasswordListener(OnToggleShowPasswordListener listener) {
        if (listener != null) {
            initTogglePasswordShownListener(listener);
        }
    }

    @SuppressLint({"RestrictedApi"})
    private void initTogglePasswordShownListener(@NotNull OnToggleShowPasswordListener listener) {
        final View revealPasswordView = this.findViewById(R.id.text_input_password_toggle);
        if (revealPasswordView == null) {
            return;
        }
        if (!(revealPasswordView instanceof CheckableImageButton)) {
            return;
        }

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

    public interface OnToggleShowPasswordListener {
        void onToggleShowPasswordClicked(boolean isShown);
    }
}

In client code:

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



回答3:


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

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")
                }
            }
        }
    }
}



回答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(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
              // your code goes here
         }
     });


来源:https://stackoverflow.com/questions/45585854/android-textinputlayout-toggle-password-visibility-event-listener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!