답변:
참고 : 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
백 스페이스를 누를 때마다 두 번 이벤트를 실행하고 싶지 않은 경우 사용
질문 한 지 오래되었지만 같은 문제가 발생했습니다. Estel이 이미 언급했듯이 키 리스너의 문제는 하드웨어 키보드에서만 작동한다는 것입니다. IME (소프트 키보드) 로이 작업을 수행하려면 위한 솔루션은 좀 더 정교합니다.
우리가 실제로 재정의하고자하는 하나의 방법은 sendKeyEvent
에서 EditText
의 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
은 내 특별한 백 스페이스 작업이 발생하는 곳입니다. 이 경우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 : 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 .
주석에서 지적했듯이이 솔루션은 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
}
});
나는 해결책을 찾기 위해 이틀을 보냈고 작동하는 것을 알아 냈습니다 :) (소프트 키에서)
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) {
}
}
EditText에 textwatcher를 추가 한 후 :
yourEditText.addTextChangedListener(textWatcher);
다른 안드로이드 기기 (삼성, 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
}
}
TextWatcher로 EditText 생성 예
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
확장 기능은 안드로이드 KTX 라이브러리에 액세스 할 수
EditText
있습니까? 미리 감사드립니다
Stackoverflow에 비슷한 질문이 있습니다. 메서드 가 포함 된 개체에 EditText
액세스하려면 재정의해야합니다 . 삭제 (백 스페이스) 이벤트를 감지하는 데 도움이됩니다. 제가 Android에서 제공 한 솔루션을 살펴보세요 . 소프트에서 백 스페이스 / 삭제 프레스를 캡처 할 수 없습니다. 건반InputConnection
deleteSurroundingText
나는 또한 setOnKeyListener를 사용하고 있기 때문에 Dialog ..에서 같은 문제에 직면했다. 그러나 나는 기본 반환 true를 설정했다. 아래 코드와 같이 변경하면 잘 작동합니다 ..
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
. 백 스페이스가 눌러 졌는지 감지하고 싶었습니다.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
}
}
버전 4.2, 4.4, 6.0에서 @Jeff의 솔루션을 테스트했습니다. 4.2 및 6.0에서는 잘 작동합니다. 그러나 4.4에서는 작동하지 않습니다.
이 문제를 쉽게 해결할 수있는 방법을 찾았습니다. 요점은 처음에 EditText의 내용에 보이지 않는 문자를 삽입하고 사용자가이 문자 앞에 커서를 이동하지 못하도록하는 것입니다. 내 방법은 ImageSpan이 너비가 0 인 공백 문자를 삽입하는 것입니다. 다음은 내 코드입니다.
@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);
}
}
}
그리고 SelectionChangeListener가있는 사용자 정의 EditText가 필요합니다.
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));
}
}
});
이제 끝났습니다 ~ 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();
}
활동에 키 리스너를 설정할 수 있으며 콜백 메서드에서 사용자가 어떤 키를 누르는지 감지 할 수 있습니다. 아래 코드는 참조 용입니다. 도움이 되었기를 바랍니다.
//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);
}