Android EditText удалить (backspace) ключевое событие

Как я могу обнаружить ключевое событие delete (backspace) для editText? Я пробовал использовать TextWatcher, но когда editText пуст, когда я нажимаю клавишу удаления, ничего не происходит. Я хочу обнаружить нажатие клавиши удаления для editText, даже если в нем нет текста.


person Buda Gavril    schedule 03.02.2011    source источник


Ответы (18)


ПРИМЕЧАНИЕ. 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;       
    }
});
person Labeeb Panampullan    schedule 03.02.2011
comment
Я просто попробовал, но onKeyListeners, по-видимому, не регистрирует обратные пробелы. - person stefs; 30.06.2011
comment
Это не будет работать с мягкой клавиатурой. Это будет работать только для аппаратного ввода. - person Varundroid; 06.04.2014
comment
На моем Nexus4 (под управлением стандартного KitKat) это действительно работает с программной клавиатурой. - person Matthias; 02.05.2014
comment
Фактически, он также работает с мягкой клавиатурой на моем Samsung Galaxy Xcover (под управлением v2.3.6 / Gingerbread) - person Matthias; 02.05.2014
comment
что делать для программных клавиатур onKeyListener- @Estel - person SubbaReddy PolamReddy; 02.07.2014
comment
Привет, на моем HTC m7 он работает с системной клавиатурой и SwiftKey, но не работает с новой клавиатурой Google. Я также обнаружил эту проблему на клавиатуре Samsung S3 и Swype. Какие-нибудь рабочие решения для этого? - person Eliasz Kubala; 14.11.2014
comment
ТАК, если он не работает для программных клавиш, то почему этот ответ принят в / под платформой Android .. - person DJphy; 10.06.2015
comment
Подтверждено, что это НЕ работает для мягкой клавиатуры в Android 5.1 на Nexus 5. - person vwmattr; 19.06.2015
comment
используйте event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_DEL, если вы не хотите, чтобы событие запускалось дважды при нажатии клавиши Backspace - person Fonix; 15.08.2016
comment
Подтверждена работа с Samsung Galaxy S6 Edge под управлением 6.0.1 и Nexus 5 под управлением 6.0.1 - person MichaelStoddart; 25.10.2016
comment
Согласно developer.android.com/reference/android/view/, не используйте этот метод для обнаружения смены программной клавиши клавиатуры. - person Cheok Yan Cheng; 22.03.2018
comment
Использование TextWatcher () запрещено stackoverflow.com/a/65574180/8663316 - person Faizan Haidar Khan; 05.01.2021

Прошло некоторое время с тех пор, как вы спросили, но у меня была такая же проблема. Как уже упоминала Эстель, проблема с ключевыми слушателями в том, что они работают только с аппаратными клавиатурами. Чтобы сделать это с помощью IME (программной клавиатуры), решение немного сложнее.

Единственный метод, который мы действительно хотим переопределить, - это sendKeyEvent в InputConnection классе EditText. Этот метод вызывается, когда ключевые события происходят в 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>
person Idris    schedule 07.07.2012
comment
Недавно я столкнулся с той же проблемой на Jelly Bean. Я обнаружил, что это решение в основном работает, за исключением того, что мне пришлось переопределить deleteSurroundingText (...) вместо sendKeyEvent (...) (который вообще не вызывался). Надеюсь, это поможет кому-то другому! - person Brandon; 26.09.2012
comment
Этот ответ в сочетании с комментарием @Brandon выше помог мне. Теперь мне интересно, как это будет работать на устройствах до JellyBean. - person Christopher Perry; 13.01.2013
comment
Он работает с принятым ответом на устройствах 2.2 и 2.3 для меня. - person Christoph; 11.04.2013
comment
похоже, что он дважды запускает ключевое событие для backspace в 2.3 ...: / - person Jeff; 15.05.2013
comment
Есть две отдельные ошибки, влияющие на клавиатуру LatinIME, которые могут препятствовать генерации событий KEYCODE_DEL. Если вы прочитаете мой ответ ниже, он объяснит, что происходит с каждой из этих проблем и как их обойти. Решение включает в себя код: stackoverflow.com/questions/18581636/ - person Carl; 17.01.2014
comment
Мне это решение подходит, спасибо! Но есть одна ситуация, в которой это не работает - когда пользователь выделил текст (т.е. getSelectionStart! = GetSelectionEnd). В этой ситуации метод sendKeyEvent даже не вызывается. Я попробовал решение ниже, используя deleteSurroundingText, но этот метод не вызывается, если есть выбор. Это в 4.2. Любые идеи? - person Sarah; 11.02.2014
comment
Это не работает, когда текст редактирования пуст, есть идеи о том, как получить событие для клавиши удаления, когда текст редактирования пуст и не имеет текста? 4.2 - person Rickster; 05.04.2014
comment
Есть ли способ привязать это только к определенному EditText? - person Alex; 16.03.2015
comment
@jibruno Я знаю, что это может быть немного поздно, но может случиться так, что вы получаете событие один раз для нажатия клавиши и один раз для нажатия клавиши (проверьте event.getAction () для KeyEvent.ACTION_DOWN и ACTION_UP). - person MCLLC; 05.02.2016
comment
Есть ли способ получить событие удаления ключа на клавиатуре ввода рукописного ввода gboard. (клавиатура с одним микрофоном, значком шестеренки и клавишей удаления). Этот метод отлично работает с gboard и клавиатурой для рукописного ввода. - person arjunkn; 22.05.2018

Это просто дополнение к ответу Идриса, добавляющее также переопределение для 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);
        }

    }

}
person Jeff    schedule 14.05.2013
comment
Спасибо! Бит deleteSurroundingText был именно тем, что мне было нужно после того, как я испробовал множество других решений. - person Adam Rosenfield; 17.09.2013
comment
Это решение очень хорошо работало для меня в предыдущих версиях Android, но, к сожалению, deleteSurroundingText вызывается только при удалении пробелов в 4.4 (KitKat). Я тестировал как на Nexus4, так и на 7. - person Dean; 03.12.2013
comment
кажется, что deleteSurroundingText требуется, когда EditText является многострочным. Странный - person Alex Sorokoletov; 02.08.2014
comment
Спасибо большое, не получилось без deleteSurroundText. Android настолько случайен, что они должны переименовать его в androm. - person Torsten Ojaperv; 10.04.2015
comment
Для меня просто добавление KeyListener в ZanyEditText во включающем фрагменте теперь регистрирует ключевые события. По крайней мере, на Android M Preview. Здесь также стоит отметить, что если кто-то пробует этот метод и также использует Библиотеку поддержки дизайна, вам необходимо расширить AppCompatEditText. Причина этого в том, что Библиотека поддержки дизайна автоматически заменяет все экземпляры EditText в ваших макетах новой версией (все делается в фоновом режиме без вашего ведома - чтобы помочь с темой и стилем), но она не может заменить пользовательские классы, такие как это. - person Chris; 27.07.2015
comment
@jibruno, эй, я реализовал это, но в моем случае у меня есть три Edittext, теперь как я могу узнать, на каком Edittext я нажал DEL_KEY? - person user5716019; 28.03.2016
comment
Буду честен с вами @ user5716019 Я не трогал код Android уже 3 года. Вам, вероятно, следует задать новый вопрос, чтобы привлечь к нему внимание. - person Jeff; 28.03.2016
comment
@jbruno Привет, я реализовал предложенное вами решение. Но, очевидно, я получаю сбой нулевого указателя из этой новой реализации. Журнал выглядит следующим образом: java.lang.NullPointerException: попытка вызвать метод интерфейса 'boolean android.view.inputmethod.InputConnection.finishComposingText ()' для ссылки на нулевой объект в android.view.inputmethod.InputConnectionWrapper.finishComposingTextrapper. ) - person Pruthviraj; 21.04.2016
comment
У меня это работает, но я больше не могу удалять знаки препинания и пробелы! - person jaytj95; 22.04.2016
comment
Он хорошо работает для Backspace, но когда текст многострочный, он копирует текст из предыдущей строки при нажатии Backspace. Есть идеи, как это решить? - person Nainal; 26.08.2017
comment
Боже, это мне так сильно помогло. У меня было уродливое решение (с невидимым символом в начале) для обнаружения пробелов в начале текста, но это приводило к проблемам с автоматическим завершением и т. Д. Это решение намного чище - оно не работает с API 19, хотя , но поскольку у Google Keep такая же проблема с этой версией, я полагаю, что она настолько хороша, насколько и здесь. - person Ridcully; 15.09.2017
comment
line '// Снимите комментарий, если хотите отменить возврат: // return false;' требуется, чтобы раскомментировать. По умолчанию событие вызывается дважды, если это не возвращает false. - person Pankaj Kumar; 17.04.2018
comment
FYI для тех, кто все еще использует это. После последнего обновления Gboard (25 июня 2018 г.) это решение будет вызывать странное поведение при попытке удалить текст. Esp, если в тексте несколько точек. - person Kachi; 04.07.2018
comment
Приведенный выше код не работает для последней версии Gboard. Чтобы код работал в старом и новом Gboard, используйте if (beforeLength == 1 && afterLength == 0 && ZanyEditText.this.getText().length() == 0) { - person Cheok Yan Cheng; 17.09.2018

Вот мое простое решение, которое работает для всех 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 пуст (как и большинство других решений).
Однако этого достаточно для большинства случаев использования.
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());
    }  
}

Затем просто используйте его как обычный 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 
        }
    });
person Leo Droidcoder    schedule 06.06.2016
comment
TextWatcher не запускается при пустом EditText - person Dan Neacșu; 14.11.2016
comment
у этого алгоритма есть недостаток, так как если вы нажимаете пробел после ввода, тогда предыдущая длина больше, чем s.length - person Marcin S.; 13.03.2017
comment
Работает, пока вы не используете выделение (автозаполнение) - person Javatar; 17.10.2017
comment
Это сработает, если вы выберете вариант автозаполнения. - person PhillyTheThrilly; 19.10.2019

Отправил 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) {
    }
}

После добавления текстового наблюдателя в ваш EditText:

yourEditText.addTextChangedListener(textWatcher);

Надеюсь, он работает и на других устройствах Android (samsung, LG и т. Д.).

person J.P    schedule 24.05.2016
comment
Аппарат HTC desire (хотя и распространен HTC :-P) - person Junaid; 06.09.2016
comment
если введено пробел, то также count == 0 - person Bincy Baby; 21.08.2017
comment
Это совершенно не работает. count == 0 будет только тогда, когда edittext пуст! - person Leo Droidcoder; 17.04.2018
comment
@MarcAlexander Я не уверен в этом ответе, однако вы можете проверить мое решение в ответе выше - person Leo Droidcoder; 15.02.2019

Мое простое решение, которое отлично работает. Вы должны добавить флаг. Мой фрагмент кода:

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
            }
        }
person Max Zonov    schedule 07.05.2018
comment
textChangeListner никогда не вызывал emptTextview. - person Janardhan R; 21.04.2020

Пример создания 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) {



        }
    }
person Alex Bigalo    schedule 02.07.2015

Я нашел действительно простое решение, которое работает с мягкой клавиатурой.

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
        }
    }
}
person Hawklike    schedule 21.08.2019

для тех, кто использует Kotlin

addOnTextChanged недостаточно гибок для обработки некоторых случаев (например, определение того, нажимает ли пользователь кнопку удаления, когда текст редактирования был пуст)

setOnkeyListener Работала даже мягкая клавиатура или жесткая клавиатура! но только на некоторых устройствах. В моем случае он работает на Samsung s8, но не работает на Xiaomi mi8 se.

если вы используете kotlin, вы можете использовать функцию кросслайна doOnTextChanged, она такая же, как addOnTextChanged, но срабатывает обратный вызов, даже если текст редактирования был пуст.

ПРИМЕЧАНИЕ. DoOnTextChanged является частью библиотеки Android KTX.

person Mạnh Hoàng Huynh    schedule 23.07.2019
comment
Вероятно, вы можете указать, что функция расширения doOnTextChanged доступна в библиотеке Android KTX - person stone; 17.12.2019
comment
Но кажется, что обратный вызов НЕ запускается, даже текст редактирования был пуст. Не могли бы вы предоставить фрагмент с перехватом удаления (возврата) для пустого EditText? заранее спасибо - person stone; 17.12.2019
comment
ах, я тестирую это, когда разрабатываю проект. В моем случае на xiaomi mi8se, когда edittext пуст и вы нажимаете delete, обратный вызов не запускается. Я найду отрывок для этого предложения. - person Mạnh Hoàng Huynh; 17.12.2019

В Stackoverflow есть аналогичный вопрос. Вам необходимо переопределить EditText, чтобы получить доступ к объекту InputConnection, который содержит метод deleteSurroundingText. Это поможет вам обнаружить событие удаления (возврата). Пожалуйста, взгляните на решение, которое я предоставил там Android - не может захватывать backspace / delete press в программном обеспечении. клавиатура

person Ayaz Alifov    schedule 18.01.2016

Кажется, это работает для меня:

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();
    }
}
person rocker99    schedule 01.04.2017

Я также столкнулся с такой же проблемой в Dialog .. потому что я использую setOnKeyListener .. Но я установил значение return по умолчанию 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 

        }
    });
person Ranjith Kumar    schedule 15.07.2017

На основе @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;
    }

}
person Qamar    schedule 02.08.2017
comment
Он вызывается дважды для каждого ключевого события удаления. - person Pankaj Kumar; 17.04.2018

Моя проблема заключалась в том, что у меня был собственный 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
}
}
person Dmitry Smolyaninov    schedule 02.10.2017

Я тестировал решение @ Jeff на версиях 4.2, 4.4, 6.0. На 4.2 и 6.0 работает хорошо. Но на 4.4 не работает.

Я нашел простой способ обойти эту проблему. Ключевым моментом является вставка невидимого символа в содержимое EditText в начале и не позволять пользователю перемещать курсор перед этим символом. Мой способ - вставить символ пробела с ImageSpan нулевой ширины. Вот мой код.

                @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 не имеет фактического содержимого, и пользователь ничего не узнает о нашем трюке.

person passerbywhu    schedule 07.11.2017

Этот вопрос может быть старым, но ответ очень прост с использованием 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();
}
person BluRe.CN    schedule 05.12.2017
comment
Как и в предыдущих решениях, это может быть вызвано автозаполнением / предложениями. - person Stonz2; 17.01.2020

Запоздало, но это может помочь новым посетителям, вместо этого используйте TextWatcher(), это очень поможет, а также он будет работать как с программной, так и с жесткой клавиатурой.

 editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (charSequence.length() > 0) {
                    //Here it means back button is pressed and edit text is now empty
                } else {
                   //Here edit text has some text
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });
person Faizan Haidar Khan    schedule 05.01.2021

Вы можете установить ключевой прослушиватель для действия, а в методе обратного вызова вы можете определить, какой ключ нажимает пользователь. Код ниже предназначен для справки. Надеюсь, поможет.

//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);
    }
person Huang    schedule 03.02.2011
comment
Проверил это решение - KEYCODE_DEL будет активирован только в том случае, если текст редактирования не справится с этим сам по себе. Например, когда в editText нет текста или есть текст, но курсор находится в самом начале. Забавно, что в моем случае мне нужно именно такое поведение - person Anton Kizema; 24.06.2015
comment
В моей деятельности нет EditText, и я просто программно заставляю отображать клавиатуру. Мне нужно поймать каждую программную клавишу клавиатуры, и это кажется единственным рабочим решением. Другой переопределяет метод dispatchKeyEvent. К сожалению, начиная с JellyBean, IME не отправляет KeyEvent для клавиши DELETE. developer.android.com/reference/android/view/KeyEvent.html - person Bemipefe; 12.09.2015