Android-全屏6位密码输入框优化布局与功能实现
Android 全屏6位密码输入框:优化布局与功能实现
功能概述 自动验证 :输入第6位密码后自动验证。 删除键优化 :按下删除键时,如果当前输入框为空,则回退到上一个输入框并清空内容。 密码可见性切换 :点击“显示密码”按钮,可以切换密码的可见性。 **震动反馈:**密码错误时提供震动反馈。 输入框抖动动画 :密码错误时,输入框抖动提示用户。 实现步骤 布局文件 :定义主界面和弹框布局,调整输入框间隙为 3dp。 **样式文件:**为输入框添加边框样式。 动画文件 :实现输入框抖动动画。 **逻辑处理:**优化删除键逻辑、自动验证、密码可见性切换等功能。 代码结构 布局文件: activity_my_number_edit.xml :主界面布局。 dialog_password.xml :密码输入弹框布局。 样式文件 : edittext_border.xml :输入框边框样式。 动画文件: shake.xml :输入框抖动动画。 逻辑处理: MyNumberEditActivity.java :实现弹框显示、密码验证、删除键优化等功能。 1 主界面布局文件 (activity_my_number_edit.xml) 主界面只有一个按钮,点击后弹出密码输入框:
2 密码输入框布局文件 (dialog_password.xml) 弹框布局,密码输入框之间的间隙为 3dp,并支持全屏显示:
3 输入框边框样式 (edittext_border.xml) 在 res/drawable 目录下创建 edittext_border.xml ,用于设置输入框的边框样式:
4 抖动动画 (res/anim/shake.xml) 在 res/anim 目录下创建 shake.xml ,用于实现输入框抖动动画: 5 逻辑处理 (MyNumberEditActivity.java) 以下是完整的逻辑处理代码: import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.os.Vibrator; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MyNumberEditActivity extends AppCompatActivity { private final String CORRECT_PASSWORD = “123456”; // 正确的密码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_number_edit); findViewById(R.id.btnShowPasswordDialog).setOnClickListener(v -> showPasswordDialog()); } private void showPasswordDialog() { // 创建Dialog final Dialog dialog = new Dialog(this, android.R.style.Theme_NoTitleBar_Fullscreen); // 全屏样式 dialog.setContentView(R.layout.dialog_password); dialog.setCancelable(true); // 自动弹出软键盘 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); // 获取Dialog中的控件 EditText[] etPassword = new EditText[6]; etPassword[0] = dialog.findViewById(R.id.et1); etPassword[1] = dialog.findViewById(R.id.et2); etPassword[2] = dialog.findViewById(R.id.et3); etPassword[3] = dialog.findViewById(R.id.et4); etPassword[4] = dialog.findViewById(R.id.et5); etPassword[5] = dialog.findViewById(R.id.et6); Button btnToggleVisibility = dialog.findViewById(R.id.btnToggleVisibility); // 清空输入框 for (EditText et : etPassword) { et.setText(""); } // 设置输入监听 setupTextWatchers(etPassword, dialog); // 切换密码可见性 btnToggleVisibility.setOnClickListener(v -> togglePasswordVisibility(etPassword, btnToggleVisibility)); // 显示Dialog dialog.show(); } private void setupTextWatchers(EditText[] etPassword, Dialog dialog) { for (int i = 0; i < etPassword.length; i++) { final int currentIndex = i; etPassword[i].addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.length() == 1 && currentIndex < etPassword.length - 1) { etPassword[currentIndex + 1].requestFocus(); // 自动跳到下一个输入框 } // 当第6位输入完成时,自动验证密码 if (currentIndex == etPassword.length - 1 && s.length() == 1) { String inputPassword = getPassword(etPassword); if (inputPassword.equals(CORRECT_PASSWORD)) { Toast.makeText(MyNumberEditActivity.this, “密码正确,进入下一步”, Toast.LENGTH_SHORT).show(); dialog.dismiss(); // 这里可以跳转到下一步 } else { Toast.makeText(MyNumberEditActivity.this, “密码错误,请重试”, Toast.LENGTH_SHORT).show(); vibrate(); // 震动反馈 shakeInputs(etPassword); // 输入框抖动动画 clearInput(etPassword); // 清空输入框 etPassword[0].requestFocus(); // 焦点回到第一个输入框 } } } @Override public void afterTextChanged(Editable s) {} }); // 处理删除键 etPassword[i].setOnKeyListener((v, keyCode, event) -> { if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) { if (etPassword[currentIndex].getText().length() == 0 && currentIndex > 0) { etPassword[currentIndex - 1].requestFocus(); // 回退到上一个输入框 etPassword[currentIndex - 1].setText(""); // 清空上一个输入框的内容 return true; // 拦截删除键事件 } } return false; }); } } private String getPassword(EditText[] etPassword) { StringBuilder password = new StringBuilder(); for (EditText et : etPassword) { password.append(et.getText().toString()); } return password.toString(); } private void clearInput(EditText[] etPassword) { for (EditText et : etPassword) { et.setText(""); } } private void vibrate() { Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { vibrator.vibrate(200); // 震动200毫秒 } } private void shakeInputs(EditText[] etPassword) { Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake); for (EditText et : etPassword) { et.startAnimation(shake); } } private void togglePasswordVisibility(EditText[] etPassword, Button btnToggleVisibility) { boolean isVisible = etPassword[0].getInputType() == (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); for (EditText et : etPassword) { if (isVisible) { et.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD); } else { et.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); } } btnToggleVisibility.setText(isVisible ? “显示密码” : “隐藏密码”); } } 运行效果 点击主界面的“输入密码”按钮,弹出全屏密码输入框。 依次输入6位数字,输入内容显示为圆点。 当输入第6位时,自动验证密码: 如果密码正确,提示“密码正确,进入下一步”,并关闭弹框。 如果密码错误,提示“密码错误,请重试”,清空输入框并震动反馈,同时输入框抖动。 支持删除键回退到上一个输入框,并清空上一个输入框的内容。 点击“显示密码”按钮,可以切换密码的可见性。