Android 使用EditText的连续OTP输入
这里有4个EditText用于输入数字密码。我希望它是这样的,若第一个EditText由1个数字填充,那个么焦点应该转到下一个EditText,并且应该以相反的方式工作。所以用户可以从最左边继续输入密码,也可以从最右边以同样的方式删除密码 有人能建议什么是最好的继续进行的方法吗 如果您熟悉RxJava,那么这可能是满足您需求的最简单方法。 下面是Kotlin代码的示例 同样的方法,你也可以写反向。长度为零时,将焦点放在上一个编辑文本上。您可以使用该库 或者,您可以使用addTextChangedListener添加一个TextWatcher,每当此EditTextView的文本发生变化时,就会调用该TextWatcher,然后您可以调用View.requestFocus对下一个EditText进行聚焦,以聚焦它Android 使用EditText的连续OTP输入,android,android-layout,android-edittext,android-input-method,Android,Android Layout,Android Edittext,Android Input Method,这里有4个EditText用于输入数字密码。我希望它是这样的,若第一个EditText由1个数字填充,那个么焦点应该转到下一个EditText,并且应该以相反的方式工作。所以用户可以从最左边继续输入密码,也可以从最右边以同样的方式删除密码 有人能建议什么是最好的继续进行的方法吗 如果您熟悉RxJava,那么这可能是满足您需求的最简单方法。 下面是Kotlin代码的示例 同样的方法,你也可以写反向。长度为零时,将焦点放在上一个编辑文本上。您可以使用该库 或者,您可以使用addTextChanged
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<EditText
android:id="@+id/otpET1"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textSize="20sp"/>
<EditText
android:id="@+id/otpET2"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textSize="20sp"/>
<EditText
android:id="@+id/otpET3"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textSize="20sp"/>
<EditText
android:id="@+id/otpET4"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textSize="20sp"/>
<EditText
android:id="@+id/otpET5"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:maxLength="1"
android:gravity="center"
android:textSize="20sp"/>
<EditText
android:id="@+id/otpET6"
android:layout_width="30dp"
android:layout_height="30dp"
android:inputType="number"
android:gravity="center"
android:maxLength="1"
android:textSize="20sp"/>
</LinearLayout>
最后,
String code = Helpers.rS(otpETs[0]) + Helpers.rS(otpETs[1]) +
Helpers.rS(otpETs[2]) + Helpers.rS(otpETs[3]) + Helpers.rS(otpETs[4])
+ Helpers.rS(otpETs[5]);
或者只需使用一个简单的for/while循环。在Kotlin中,您可以使用以下命令:
仅使用addTextChangedListener无法完成此操作。您可能需要同时设置onKeyListener。以下是您的代码:
//6 EditTexts are otpEt[0], otpEt[1],...otpEt[5]
private EditText[] otpEt = new EditText[6];
otpEt[0] = (EditText) findViewById(R.id.otpEt1);
otpEt[1] = (EditText) findViewById(R.id.otpEt2);
otpEt[2] = (EditText) findViewById(R.id.otpEt3);
otpEt[3] = (EditText) findViewById(R.id.otpEt4);
otpEt[4] = (EditText) findViewById(R.id.otpEt5);
otpEt[5] = (EditText) findViewById(R.id.otpEt6);
setOtpEditTextHandler();
private void setOtpEditTextHandler () { //This is the function to be called
for (int i = 0;i < 6;i++) { //Its designed for 6 digit OTP
final int iVal = i;
otpEt[iVal].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) {
}
@Override
public void afterTextChanged(Editable s) {
if(iVal == 5 && !otpEt[iVal].getText().toString().isEmpty()) {
otpEt[iVal].clearFocus(); //Clears focus when you have entered the last digit of the OTP.
} else if (!otpEt[iVal].getText().toString().isEmpty()) {
otpEt[iVal+1].requestFocus(); //focuses on the next edittext after a digit is entered.
}
}
});
otpEt[iVal].setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return false; //Dont get confused by this, it is because onKeyListener is called twice and this condition is to avoid it.
}
if(keyCode == KeyEvent.KEYCODE_DEL &&
otpEt[iVal].getText().toString().isEmpty() && iVal != 0) {
//this condition is to handel the delete input by users.
otpEt[iVal-1].setText("");//Deletes the digit of OTP
otpEt[iVal-1].requestFocus();//and sets the focus on previous digit
}
return false;
}
});
}
}
如果您觉得这段代码很难,只需将其粘贴到您的项目中,然后尝试重新安排。你会很容易得到它的
public class Helpers {
public static String rS(EditText editText) {
return editText.getText().toString().trim();
}
}
String code = Helpers.rS(otpETs[0]) + Helpers.rS(otpETs[1]) +
Helpers.rS(otpETs[2]) + Helpers.rS(otpETs[3]) + Helpers.rS(otpETs[4])
+ Helpers.rS(otpETs[5]);
txtOTP_1.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (txtOTP_1.text.toString().length == 1) {
txtOTP_1.clearFocus()
txtOTP_2.requestFocus()
txtOTP_2.setCursorVisible(true)
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
if (txtOTP_1.text.toString().length == 0) {
txtOTP_1.requestFocus()
}
}
})
txtOTP_2.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (txtOTP_2.text.toString().length == 1) {
txtOTP_2.clearFocus()
txtOTP_3.requestFocus()
txtOTP_3.setCursorVisible(true)
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
if (txtOTP_2.text.toString().length == 0) {
txtOTP_2.requestFocus()
}
}
})
txtOTP_3.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (txtOTP_3.text.toString().length == 1) {
txtOTP_3.clearFocus()
txtOTP_4.requestFocus()
txtOTP_4.setCursorVisible(true)
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
if (txtOTP_3.text.toString().length == 0) {
txtOTP_3.requestFocus()
}
}
})
txtOTP_4.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (txtOTP_4.text.toString().length == 1) {
txtOTP_4.clearFocus()
txtOTP_5.requestFocus()
txtOTP_5.setCursorVisible(true)
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
if (txtOTP_4.text.toString().length == 0) {
txtOTP_4.requestFocus()
}
}
})
txtOTP_5.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (txtOTP_5.text.toString().length == 1) {
txtOTP_5.requestFocus()
txtOTP_5.setCursorVisible(true)
}
}
})
//6 EditTexts are otpEt[0], otpEt[1],...otpEt[5]
private EditText[] otpEt = new EditText[6];
otpEt[0] = (EditText) findViewById(R.id.otpEt1);
otpEt[1] = (EditText) findViewById(R.id.otpEt2);
otpEt[2] = (EditText) findViewById(R.id.otpEt3);
otpEt[3] = (EditText) findViewById(R.id.otpEt4);
otpEt[4] = (EditText) findViewById(R.id.otpEt5);
otpEt[5] = (EditText) findViewById(R.id.otpEt6);
setOtpEditTextHandler();
private void setOtpEditTextHandler () { //This is the function to be called
for (int i = 0;i < 6;i++) { //Its designed for 6 digit OTP
final int iVal = i;
otpEt[iVal].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) {
}
@Override
public void afterTextChanged(Editable s) {
if(iVal == 5 && !otpEt[iVal].getText().toString().isEmpty()) {
otpEt[iVal].clearFocus(); //Clears focus when you have entered the last digit of the OTP.
} else if (!otpEt[iVal].getText().toString().isEmpty()) {
otpEt[iVal+1].requestFocus(); //focuses on the next edittext after a digit is entered.
}
}
});
otpEt[iVal].setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return false; //Dont get confused by this, it is because onKeyListener is called twice and this condition is to avoid it.
}
if(keyCode == KeyEvent.KEYCODE_DEL &&
otpEt[iVal].getText().toString().isEmpty() && iVal != 0) {
//this condition is to handel the delete input by users.
otpEt[iVal-1].setText("");//Deletes the digit of OTP
otpEt[iVal-1].requestFocus();//and sets the focus on previous digit
}
return false;
}
});
}
}