ฉันจะตรวจจับเหตุการณ์สำคัญลบ (backspace) สำหรับ editText ได้อย่างไร ฉันได้ลองใช้ TextWatcher แล้ว แต่เมื่อ editText ว่างเปล่าเมื่อฉันกดปุ่มลบไม่มีอะไรเกิดขึ้น ฉันต้องการตรวจจับปุ่มลบกดศัตรูแก้ไขข้อความแม้ว่าจะไม่มีข้อความก็ตาม
ฉันจะตรวจจับเหตุการณ์สำคัญลบ (backspace) สำหรับ editText ได้อย่างไร ฉันได้ลองใช้ TextWatcher แล้ว แต่เมื่อ editText ว่างเปล่าเมื่อฉันกดปุ่มลบไม่มีอะไรเกิดขึ้น ฉันต้องการตรวจจับปุ่มลบกดศัตรูแก้ไขข้อความแม้ว่าจะไม่มีข้อความก็ตาม
คำตอบ:
หมายเหตุ: ใช้onKeyListener
ไม่ได้กับคีย์บอร์ดแบบนิ่ม
คุณสามารถตั้งค่าOnKeyListener
สำหรับคุณeditText
เพื่อให้คุณสามารถตรวจสอบใด ๆ กดปุ่ม
แก้ไข: ข้อผิดพลาดทั่วไปที่เรากำลังตรวจสอบKeyEvent.KEYCODE_BACK
สำหรับbackspace
แต่จริงๆมันเป็นKeyEvent.KEYCODE_DEL
(จริงเหรอว่าชื่อจะทำให้เกิดความสับสนมาก!)
editText.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
//You can identify which key pressed buy checking keyCode value with KeyEvent.KEYCODE_
if(keyCode == KeyEvent.KEYCODE_DEL) {
//this is for backspace
}
return false;
}
});
event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_DEL
ถ้าคุณไม่ต้องการให้เหตุการณ์ยิงสองครั้งต่อการกด backspace
เป็นเวลานานแล้วที่คุณถาม แต่ฉันเพิ่งมีปัญหาเดียวกัน ดังที่ได้กล่าวไปแล้วโดย Estel ปัญหาเกี่ยวกับผู้ฟังหลักคือใช้งานได้กับแป้นพิมพ์ฮาร์ดแวร์เท่านั้น หากต้องการทำสิ่งนี้ด้วยIME (แป้นพิมพ์แบบอ่อน)วิธีแก้ปัญหานั้นซับซ้อนกว่าเล็กน้อย
วิธีเดียวที่เราต้องการจริงแทนที่เป็นsendKeyEvent
ในEditText
's InputConnection
ระดับ วิธีนี้เรียกว่าเมื่อเหตุการณ์สำคัญเกิดขึ้นใน IME แต่เพื่อที่จะลบล้างสิ่งนี้เราจำเป็นต้องใช้แบบกำหนดเองEditText
ซึ่งจะแทนที่onCreateInputConnection
เมธอดโดยการตัดInputConnection
อ็อบเจ็กต์เริ่มต้นในคลาสพร็อกซี! : |
ฟังดูซับซ้อน แต่นี่เป็นตัวอย่างที่ง่ายที่สุดที่ฉันสามารถทำได้:
public class ZanyEditText extends EditText {
private Random r = new Random();
public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ZanyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZanyEditText(Context context) {
super(context);
}
public void setRandomBackgroundColor() {
setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
.nextInt(256)));
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class ZanyInputConnection extends InputConnectionWrapper {
public ZanyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
ZanyEditText.this.setRandomBackgroundColor();
// Un-comment if you wish to cancel the backspace:
// return false;
}
return super.sendKeyEvent(event);
}
}
}
บรรทัดที่มีการเรียกไปที่setRandomBackgroundColor
คือที่ที่การกระทำ backspace พิเศษของฉันเกิดขึ้น ในกรณีนี้ให้เปลี่ยนEditText
สีพื้นหลัง
หากคุณกำลังขยายสิ่งนี้จาก XML อย่าลืมใช้ชื่อแพ็กเกจแบบเต็มเป็นแท็ก:
<cc.buttfu.test.ZanyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/somefield"
></cc.buttfu.test.ZanyEditText>
นี่เป็นเพียงส่วนเสริมของคำตอบของ Idris โดยเพิ่มในการแทนที่เพื่อ deleteSurroundingText ด้วย ฉันพบข้อมูลเพิ่มเติมที่นี่: Android: Backspace ใน WebView / BaseInputConnection
package com.elavon.virtualmerchantmobile.utils;
import java.util.Random;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.widget.EditText;
public class ZanyEditText extends EditText {
private Random r = new Random();
public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ZanyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZanyEditText(Context context) {
super(context);
}
public void setRandomBackgroundColor() {
setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
.nextInt(256)));
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class ZanyInputConnection extends InputConnectionWrapper {
public ZanyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
ZanyEditText.this.setRandomBackgroundColor();
// Un-comment if you wish to cancel the backspace:
// return false;
}
return super.sendKeyEvent(event);
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
if (beforeLength == 1 && afterLength == 0) {
// backspace
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
}
deleteSurroundingText
บิตได้รับสิ่งที่ฉันต้องการหลังจากที่พยายามแก้ปัญหาอื่น ๆ นับไม่ถ้วน
นี่คือวิธีง่ายๆของฉันซึ่งใช้ได้กับ API ทั้งหมด:
private int previousLength;
private boolean backSpace;
// ...
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
previousLength = s.length();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
backSpace = previousLength > s.length();
if (backSpace) {
// do your stuff ...
}
}
อัพเดท 17.04.18 .
ตามที่ระบุไว้ในความคิดเห็นโซลูชันนี้จะไม่ติดตามการกด backspace หาก EditText ว่างเปล่า (เช่นเดียวกับโซลูชันอื่น ๆ ส่วนใหญ่)
อย่างไรก็ตามก็เพียงพอสำหรับกรณีการใช้งานส่วนใหญ่
ปล. ถ้าวันนี้ต้องสร้างสิ่งที่คล้ายกันฉันจะทำ:
public abstract class TextWatcherExtended implements TextWatcher {
private int lastLength;
public abstract void afterTextChanged(Editable s, boolean backSpace);
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
lastLength = s.length();
}
@Override
public void afterTextChanged(Editable s) {
afterTextChanged(s, lastLength > s.length());
}
}
จากนั้นใช้เป็น TextWatcher ปกติ:
editText.addTextChangedListener(new TextWatcherExtended() {
@Override
public void afterTextChanged(Editable s, boolean backSpace) {
// Here you are! You got missing "backSpace" flag
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Do something useful if you wish.
// Or override it in TextWatcherExtended class if want to avoid it here
}
});
ฉันส่ง 2 วันเพื่อค้นหาวิธีแก้ปัญหาและฉันพบวิธีที่ใช้งานได้ :) (บนซอฟต์คีย์)
public TextWatcher textWatcher = 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 (count == 0) {
//Put your code here.
//Runs when delete/backspace pressed on soft key (tested on htc m8)
//You can use EditText.getText().length() to make if statements here
}
}
@Override
public void afterTextChanged(Editable s) {
}
}
หลังจากเพิ่ม textwatcher ใน EditText ของคุณ:
yourEditText.addTextChangedListener(textWatcher);
ฉันหวังว่ามันจะใช้งานได้กับอุปกรณ์ Android อื่น ๆ เช่นกัน (samsung, LG ฯลฯ )
วิธีง่ายๆของฉันที่ทำงานได้อย่างสมบูรณ์ คุณควรเพิ่มธง ข้อมูลโค้ดของฉัน:
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (after < count) {
isBackspaceClicked = true;
} else {
isBackspaceClicked = false;
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public void afterTextChanged(Editable s) {
if (!isBackspaceClicked) {
// Your current code
} else {
// Your "backspace" handling
}
}
ตัวอย่างการสร้าง EditText ด้วย TextWatcher
EditText someEdit=new EditText(this);
//create TextWatcher for our EditText
TextWatcher1 TW1 = new TextWatcher1(someEdit);
//apply our TextWatcher to EditText
someEdit.addTextChangedListener(TW1);
TextWatcher ที่กำหนดเอง
public class TextWatcher1 implements TextWatcher {
public EditText editText;
//constructor
public TextWatcher1(EditText et){
super();
editText = et;
//Code for monitoring keystrokes
editText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DEL){
editText.setText("");
}
return false;
}
});
}
//Some manipulation with text
public void afterTextChanged(Editable s) {
if(editText.getText().length() == 12){
editText.setText(editText.getText().delete(editText.getText().length() - 1, editText.getText().length()));
editText.setSelection(editText.getText().toString().length());
}
if (editText.getText().length()==2||editText.getText().length()==5||editText.getText().length()==8){
editText.setText(editText.getText()+"/");
editText.setSelection(editText.getText().toString().length());
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
สำหรับบางคนที่ใช้ Kotlin
addOnTextChanged
ไม่มีความยืดหยุ่นเพียงพอที่จะจัดการกับบางกรณี (เช่นตรวจสอบว่าผู้ใช้กดลบเมื่อแก้ไขข้อความว่างเปล่า)
setOnkeyListener
ทำงานได้แม้กระทั่งแป้นพิมพ์ที่อ่อนนุ่มหรือแป้นพิมพ์ยาก! แต่เพียงบนอุปกรณ์บางอย่าง ในกรณีของฉันมันใช้งานได้กับ Samsung s8 แต่ใช้กับ Xiaomi mi8 se ไม่ได้
หากคุณใช้ kotlin คุณสามารถใช้ฟังก์ชัน crossline doOnTextChanged
ได้เช่นเดียวกับaddOnTextChanged
แต่การเรียกกลับจะถูกทริกเกอร์แม้ข้อความแก้ไขจะว่างเปล่า
หมายเหตุ: doOnTextChanged เป็นส่วนหนึ่งของไลบรารี Android KTX
doOnTextChanged
ฟังก์ชั่นการขยายสามารถเข้าถึงได้ในห้องสมุด Android KTX
EditText
ไหม ขอบคุณล่วงหน้า
มีคำถามที่คล้ายกันใน Stackoverflow คุณต้องลบล้างEditText
เพื่อเข้าถึงInputConnection
วัตถุที่มีdeleteSurroundingText
เมธอด จะช่วยให้คุณตรวจจับเหตุการณ์การลบ (backspace) โปรดดูวิธีแก้ปัญหาที่ฉันให้ไว้ที่Android - ไม่สามารถจับภาพ backspace / ลบกดแบบซอฟต์ แป้นพิมพ์
ดูเหมือนว่าจะได้ผลสำหรับฉัน:
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (before - count == 1) {
onBackSpace();
} else if (s.subSequence(start, start + count).toString().equals("\n")) {
onNewLine();
}
}
ฉันยังประสบปัญหาเดียวกันใน Dialog .. เพราะฉันใช้ setOnKeyListener .. แต่ฉันตั้งค่าผลตอบแทนเริ่มต้นเป็นจริง หลังจากการเปลี่ยนแปลงเช่นโค้ดด้านล่างมันใช้งานได้ดีสำหรับฉัน ..
mDialog.setOnKeyListener(new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mDialog.dismiss();
return true;
}
return false;//this line is important
}
});
ขึ้นอยู่กับ @Jiff ZanyEditText
นี่คือWiseEditText
ด้วยsetSoftKeyListener(OnKeyListener)
package com.locopixel.seagame.ui.custom;
import java.util.Random;
import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
public class WiseEditText extends AppCompatEditText {
private Random r = new Random();
private OnKeyListener keyListener;
public WiseEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WiseEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WiseEditText(Context context) {
super(context);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class MyInputConnection extends InputConnectionWrapper {
public MyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (keyListener != null) {
keyListener.onKey(WiseEditText.this,event.getKeyCode(),event);
}
return super.sendKeyEvent(event);
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
if (beforeLength == 1 && afterLength == 0) {
// backspace
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
public void setSoftKeyListener(OnKeyListener listener){
keyListener = listener;
}
}
ปัญหาของฉันเป็นที่ฉันมีกำหนดเองTextwatcher
ดังนั้นฉันไม่ต้องการที่จะเพิ่มOnKeyListener
ไปยังเช่นเดียวกับฉันไม่ได้ต้องการที่จะสร้างที่กำหนดเองEditText
EditText
ฉันต้องการตรวจสอบว่ามีการกด Backspace หรือไม่ในafterTextChanged
วิธีของฉันดังนั้นฉันจึงไม่ควรเรียกเหตุการณ์ของฉัน
นี่คือวิธีที่ฉันแก้ไขปัญหานี้ หวังว่าคงจะเป็นประโยชน์สำหรับใครบางคน
public class CustomTextWatcher extends AfterTextChangedTextWatcher {
private boolean backspacePressed;
@Override
public void afterTextChanged(Editable s) {
if (!backspacePressed) {
triggerYourEvent();
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
super.onTextChanged(s, start, before, count);
backspacePressed = count == 0; //if count == 0, backspace is pressed
}
}
ฉันได้ทดสอบโซลูชันของ @ Jeff ในเวอร์ชัน 4.2, 4.4, 6.0 แล้ว บน 4.2 และ 6.0 ทำงานได้ดี แต่ใน 4.4 มันไม่ทำงาน
ฉันพบวิธีง่ายๆในการแก้ไขปัญหานี้ ประเด็นสำคัญคือการแทรกอักขระที่มองไม่เห็นลงในเนื้อหาของ EditText ตั้งแต่เริ่มต้นและอย่าให้ผู้ใช้เลื่อนเคอร์เซอร์ก่อนอักขระนี้ วิธีของฉันคือการแทรกอักขระเว้นวรรคสีขาวที่มี ImageSpan ของ Zero Width นี่คือรหัสของฉัน
@Override
public void afterTextChanged(Editable s) {
String ss = s.toString();
if (!ss.startsWith(" ")) {
int selection = holder.editText.getSelectionEnd();
s.insert(0, " ");
ss = s.toString();
holder.editText.setSelection(selection + 1);
}
if (ss.startsWith(" ")) {
ImageSpan[] spans = s.getSpans(0, 1, ImageSpan.class);
if (spans == null || spans.length == 0) {
s.setSpan(new ImageSpan(getResources().getDrawable(R.drawable.zero_wdith_drawable)), 0 , 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
และเราต้องการ EditText แบบกำหนดเองซึ่งมี SelectionChangeListener
public class EditTextSelectable extends android.support.v7.widget.AppCompatEditText {
public interface OnSelectChangeListener {
void onSelectChange(int start, int end);
}
private OnSelectChangeListener mListener;
public void setListener(OnSelectChangeListener listener) {
mListener = listener;
}
...constructors...
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
if (mListener != null) {
mListener.onSelectChange(selStart, selEnd);
}
super.onSelectionChanged(selStart, selEnd);
}
}
และขั้นตอนสุดท้าย
holder.editText.setListener(new EditTextSelectable.OnSelectChangeListener() {
@Override
public void onSelectChange(int start, int end) {
if (start == 0 && holder.editText.getText().length() != 0) {
holder.editText.setSelection(1, Math.max(1, end));
}
}
});
และตอนนี้เราทำเสร็จแล้ว ~ เราสามารถตรวจจับเหตุการณ์สำคัญของ backspace ได้เมื่อ EditText ไม่มีเนื้อหาจริงและผู้ใช้จะไม่รู้อะไรเลยเกี่ยวกับกลอุบายของเรา
คำถามนี้อาจจะเก่า แต่คำตอบนั้นง่ายมากเมื่อใช้ TextWatcher
int lastSize=0;
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//2. compare the old length of the text with the new one
//3. if the length is shorter, then backspace was clicked
if (lastSize > charSequence.length()) {
//4. Backspace was clicked
//5. perform action
}
//1. get the current length of of the text
lastSize = charSequence.length();
}
ฉันพบวิธีง่ายๆที่ใช้ได้กับคีย์บอร์ดนุ่ม ๆ
override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) {
text?.let {
if(count < before) {
Toast.makeText(context, "backspace pressed", Toast.LENGTH_SHORT).show()
// implement your own code
}
}
}
คุณสามารถตั้งค่าตัวรับฟังคีย์สำหรับกิจกรรมและในวิธีการโทรกลับคุณสามารถตรวจจับได้ว่าผู้ใช้กดปุ่มใด โค้ดด้านล่างนี้ใช้สำหรับการอ้างอิงของคุณ หวังว่าจะช่วยได้
//after user hits keys, this method would be called.
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (editText.isFocused()) {
switch (keyCode) {
case KeyEvent.KEYCODE_DEL: //delete key
Log.i("INFO", "delete key hit"); //you should see this log in ddms after you hit delete key
break;
}
}
return super.onKeyUp(keyCode, event);
}