Android 安卓文本输入布局。切换密码可见性事件侦听器?

Android 安卓文本输入布局。切换密码可见性事件侦听器?,android,android-textinputlayout,Android,Android Textinputlayout,在InputType textPassword的TextInputLayout中有一个密码可见性切换按钮 是否有可能捕获切换事件 我找不到任何用于此的公共方法我查看了TextInputLayout的源代码,以找到切换按钮的视图类型。它的CheckableImageButton。其他一切都很简单。您需要找到在TextInputLayout视图的子级上递归迭代的视图。然后按照@MikeM在评论中的建议设置TouchListener View togglePasswordButton = findTo

在InputType textPassword的TextInputLayout中有一个密码可见性切换按钮

是否有可能捕获切换事件


我找不到任何用于此的公共方法

我查看了TextInputLayout的源代码,以找到切换按钮的视图类型。它的CheckableImageButton。其他一切都很简单。您需要找到在TextInputLayout视图的子级上递归迭代的视图。然后按照@MikeM在评论中的建议设置TouchListener

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;
}
@米肯。感谢您的id

您可以使用此:

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);
    }
}
在客户端代码中:

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

使用布局检查器分析视图层次结构后,我可以看到以下内容:

因此,您可以:

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

我在这里使用绑定

这是layout-regPasswordlayout的id 密码切换的默认id-文本\输入\密码\切换

binding.regPasswordlayout.findViewById(R.id.text_input_password_toggle)
.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
              // your code goes here
         }
     });

您可以从(Kotlin)开始执行以下操作:


不是真的。嗯,反正没有现成的。该
视图
上设置了一个匿名的
OnClickListener
,它只调用包私有切换方法。我可以想出几种方法来伪装它。最简单的方法可能是获取对该
视图的引用,并在其上设置一个
OnTouchListener
,因为您可以将其设置为不干扰
OnClickListener
。如果您能找到访问
mPasswordToggleView
的方法,您可以找到解决方案。@K.Sopheak我想,也许有一个官方的解决方案:)是的,这就是我现在尝试的方式,
CheckableImageButton
有一个ID,显然,如果你愿意这样做的话。名称为
text\u input\u password\u toggle
,您可以使用
Resources\getIdentifier()
方法获取
int
值。“仅供参考。”米凯姆说。很高兴知道。想想如果他们换了身份证怎么办?!他们不太可能会这样做,但是,不管怎样,它都是打包在应用程序中的资源,您可以控制支持库的版本。也就是说,只要您拥有编译时使用的库版本的正确ID,就可以了。它不会依赖于不同设备之间可能存在差异的系统资源。替代方案对我有效,但是,我必须继续寻找正确的id,上面描述的id不起作用。对我来说,有效的是
val passwordToggleButton=textInputLayout.findViewById(R.id.text\u input\u end\u icon)passwordToggleButton?.setOnTouchListener{view,event->if(event.action==MotionEvent.action\u DOWN)//您的代码false}
// 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")
                }
            }
        }
    }
}
binding.regPasswordlayout.findViewById(R.id.text_input_password_toggle)
.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
              // your code goes here
         }
     });
textInputLayout.setEndIconOnClickListener {
    // do something here
}