Android EditText删除(退格)键事件

Bud*_*ril 113 events android key android-edittext

如何检测editText的删除(退格)键事件?我尝试过使用TextWatcher,但是当editText为空时,当我按下删除键时,没有任何反应.即使没有文本,我想检测删除键按下一个editText.

Lab*_*lan 149

注意:onKeyListener不适用于软键盘.

你可以设置OnKeyListenereditText这样你就可以检测到任何按键
编辑:我们正在检查一个常见的错误KeyEvent.KEYCODE_BACKbackspace,但实际上它是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;       
    }
});
Run Code Online (Sandbox Code Playgroud)

  • onKeyListener不适用于软键盘 (102认同)
  • 使用`event.getAction()== KeyEvent.ACTION_DOWN && event.getKeyCode()== KeyEvent.KEYCODE_DEL`如果你不希望每按一次退格事件两次触发事件 (23认同)
  • 所以,如果它不适用于软键,那么为什么这个答案在android平台下被接受? (8认同)
  • 我刚尝试过,但onKeyListeners显然没有注册退格. (7认同)
  • 在我的Nexus4(运行库存KitKat)上,这**适用于软件键盘. (5认同)
  • 它不适用于软键盘.这仅适用于硬件输入. (2认同)
  • 根据https://developer.android.com/reference/android/view/View.OnKeyListener.html,不要使用此方法来检测软键盘按键变化。 (2认同)

Idr*_*ris 82

你提问已经有一段时间了,但我遇到了同样的问题.正如Estel已经提到的那样,关键监听器的问题在于它们只能与硬件键盘配合使用.要使用IME(软键盘)执行此操作,解决方案会更复杂一些.

我们实际上要重写的一个方法是sendKeyEventEditTextInputConnection类.在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);
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

调用的行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>
Run Code Online (Sandbox Code Playgroud)

  • 我最近在Jelly Bean上遇到了同样的问题.我发现这个解决方案大部分都有效,除了我必须覆盖deleteSurroundingText(...)而不是sendKeyEvent(...)(根本没有被调用).希望这有助于其他人! (27认同)
  • 当edittext为空时,当edittext为空且没有文本时,如何获取删除键的事件的任何想法都不起作用?4.2 (24认同)
  • @idris此解决方案不适用于Nexus 7 Andorid 4.4.2 (3认同)

Jef*_*eff 66

这只是Idris答案的补充,也是对overrideSurroundingText的覆盖.我在这里找到了更多信息:Android:BackView in 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);
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢一个男人,没有使用deleteSurroundText.Android非常随意,应该将其重命名为androm. (6认同)
  • 在以前的Android版本中,这个解决方案对我来说非常好用,但不幸的是deleteSurroundingText仅在删除4.4(KitKat)上的空格时调用.我已经在Nexus4和7上进行了测试. (5认同)
  • 谢谢!在尝试无数其他解决方案之后,`deleteSurroundingText`位正是我所需要的. (3认同)
  • 它适用于我,但我不能删除标点符号或空格了! (2认同)

Leo*_*der 26

这是我的简单解决方案,适用于所有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 ...

    } 
}
Run Code Online (Sandbox Code Playgroud)

更新17.04.18.
正如评论中所指出的,如果EditText为空,此解决方案不会跟踪退格按(与大多数其他解决方案相同).
但是,对于大多数用例来说,这已经足够了.
PS如果我今天必须创造类似的东西,我会这样做:

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());
    }  
}
Run Code Online (Sandbox Code Playgroud)

然后只需将其用作常规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 
        }
    });
Run Code Online (Sandbox Code Playgroud)

  • TextWatcher不会在空的EditText上触发 (7认同)
  • 只要您不使用选择(自动完成)就可以工作 (2认同)

小智 13

我发送了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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

将textwatcher添加到EditText后:

yourEditText.addTextChangedListener(textWatcher);
Run Code Online (Sandbox Code Playgroud)

我希望它也适用于其他Android设备(三星,LG等).

  • 这完全不起作用.count == 0只有在edittext为空时! (5认同)

EAM*_*Max 7

我的简单解决方案完美运行。您应该添加一个标志。我的代码片段:

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
            }
        }
Run Code Online (Sandbox Code Playgroud)