如何实现TextInputLayout密码按住切换键显示明文、松开隐藏?
按住显示明文、松开恢复密文的密码输入框实现方案
当然可以实现这个需求!其实只需要给TextInputLayout自带的密码切换按钮添加触摸事件监听,监听按下和抬起/取消的动作,就能精准控制密码的显示状态了。下面是具体的实现步骤和代码示例:
1. 布局准备
首先确保你的布局里使用的是Material Components库的TextInputLayout,并开启密码切换按钮:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/passwordInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:passwordToggleEnabled="true"> <!-- 开启密码切换按钮 --> <com.google.android.material.textfield.TextInputEditText android:id="@+id/passwordEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="请输入密码"/> </com.google.android.material.textfield.TextInputLayout>
2. 触摸事件监听实现
核心逻辑是给密码切换按钮设置OnTouchListener,在不同触摸动作下切换输入类型:
Kotlin 代码示例
import android.view.MotionEvent import android.view.inputmethod.InputType import android.widget.AppCompatImageView import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout // 获取布局控件 val passwordInputLayout = findViewById<TextInputLayout>(R.id.passwordInputLayout) val passwordEditText = findViewById<TextInputEditText>(R.id.passwordEditText) // 获取TextInputLayout内部的密码切换按钮(ID为design_password_toggle) val passwordToggleBtn = passwordInputLayout.findViewById<AppCompatImageView>(R.id.design_password_toggle) // 设置触摸监听 passwordToggleBtn.setOnTouchListener { _, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // 按下按钮时:保存光标位置,切换为明文显示 val cursorPos = passwordEditText.selectionStart passwordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD passwordEditText.setSelection(cursorPos) // 恢复光标位置,避免跳转到开头 true } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // 抬起按钮/触摸取消时:保存光标位置,切换回密文显示 val cursorPos = passwordEditText.selectionStart passwordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD passwordEditText.setSelection(cursorPos) true } else -> false } }
Java 代码示例
import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.InputType; import android.widget.AppCompatImageView; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; // 获取控件 TextInputLayout passwordInputLayout = findViewById(R.id.passwordInputLayout); TextInputEditText passwordEditText = findViewById(R.id.passwordEditText); // 获取密码切换按钮 AppCompatImageView passwordToggleBtn = passwordInputLayout.findViewById(R.id.design_password_toggle); // 设置触摸监听 passwordToggleBtn.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下时切换明文 int cursorPos = passwordEditText.getSelectionStart(); passwordEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); passwordEditText.setSelection(cursorPos); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 抬起/取消时切换回密文 int cursorPos2 = passwordEditText.getSelectionStart(); passwordEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); passwordEditText.setSelection(cursorPos2); return true; default: return false; } } });
关键注意事项
- 确保你的项目依赖了Material Components库,否则
design_password_toggle这个ID不会存在,触摸事件也无法绑定。 - 一定要处理
ACTION_CANCEL事件:如果用户按住按钮后滑动到按钮外部再松开,这个事件会触发,此时也需要恢复密文显示,避免密码一直处于明文状态。 - 保存并恢复光标位置是提升用户体验的细节,否则切换输入类型时光标会自动跳到文本开头,影响输入流畅度。
内容的提问来源于stack exchange,提问作者Afshin




