Android - catch backspace (delete) button on custom EditText - android

I want to catch the backspace/delete button event in soft keyboard on EditText custom.
How can I do it ?
I tried these solutions but they do not work for me :
Android custom EditText and back button override
EditText OnKeyDown
Get back key event on EditText
Android EditText delete(backspace) key event
Thanks for your help !
EDIT :
I found a fix for that isssue with the function DispatchKeyEvent :
#Override public boolean dispatchKeyEvent(#NonNull KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
// ...
}
return super.dispatchKeyEvent(event);
}

I found a fix for that isssue with the function DispatchKeyEvent :
#Override public boolean dispatchKeyEvent(#NonNull KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
// ...
}
return super.dispatchKeyEvent(event);
}

Catching Key Events from soft input methods in Android is unreliable. Here is an excerpt from the JavaDoc for the KeyEvent class:
As soft input methods can use multiple and inventive ways of inputting
text, there is no guarantee that any key press on a soft keyboard will
generate a key event: this is left to the IME's discretion, and in
fact sending such events is discouraged. You should never rely on
receiving KeyEvents for any key on a soft input method. In particular,
the default software keyboard will never send any key event to any
application targetting Jelly Bean or later, and will only send events
for some presses of the delete and return keys to applications
targetting Ice Cream Sandwich or earlier.
One workaround could involve using TextWatcher. Whenever a delete occurs in an EditText, the character count drops.
myEditText.addTextChangedListener(this);
//...
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (count == 0) {
//text was deleted.
}
}
Edit: This is untested, so may not be completely reliable. In addition, it's worth pointing out that count may also read 0 if a long section of text is selected and then replaced. I created a library once that was designed to add Undo/Redo functionality to EditText, but can also identify the difference between text being replaced and deleted, so this may be of use to you if you require more accuracy.

Please, take a look at a solution I provided in another similar topic: Android - cannot capture backspace/delete press in soft. keyboard. You need to build your custom EditText class and override onCreateInputConnection method in it. It will give you access to deleteSurroundingText event which is firing when you click backspace. I've tested it in some devices and hope it will work in others also. Try it and give a feedback.

Here you go..
editText.addTextChangedListener(new TextWatcher() {
private int before;
private int after;
private int prevLength;
private boolean isBackPressed;
ArrayList<Integer> arrayList;
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
prevLength = charSequence.length();
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int end, int count) {
}
#Override
public void afterTextChanged(Editable editable) {
isBackPressed = prevLength > editable.length();
if(isBackPressed){
Toast.makeText(getApplicationContext(),"Back",Toast.LENGTH_LONG).show();
}
}
});

Related

Android: soft keyboard Backspace on EditText not working

This is what happens:
Activity A and B have an EditText and they both have IME_SEARCH. The input is done only via soft keyboard on a SAMSUNG tablet.
On Activity A I can use the EditText without problems. The thing is that on Activity B I can't erase text with backspace after I hit 'space' or whenever I use a word from the suggestions. It behaves like there wasn't text there anymore. If I type new characters, I can erase them up to the space.
Important points:
The View hierarchy that contains the EditTexts are identical
The code that configures the IME_SEARCH processing (via setOnEditorActionListener) is identical
The TextWatcher of both are also identical
In the Manifest, both activities are configures with
android:configChanges="keyboardHidden|keyboard|orientation"
android:windowSoftInputMode="stateAlwaysHidden|adjustUnspecified"
I set a breakpoint on the method beforeTextChanged of both TextWatcher. I inserted a 'space' and hit 'backspace'. On the Edittext of activity A, the method is triggered but on activity B's it is not triggered. I can't see the reason for this to happen since the properties of both Edittext are configured identically.
I also tried removing the IME option but the behavior kept the same.
Does anyone know what could be happening?
EDIT 1:
searchTxt.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 (s.length() == 0) {
btnClear.setVisibility(View.GONE);
} else{
btnClear.setVisibility(View.VISIBLE);
}
}
});
searchTxt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
buildGrid();
return true;
}
return false;
}
});
EDIT 2:
The layout hierarchy is as following.
<LinearLayout
... >
<include layout="#layout/title_bar" />
<RelativeLayout
...>
<EditText
...>
The problem was that, for some reason, the Activity B was overriding dispatchKeyEvent() and always returning true. Removing it solved the problem.
I have similar problems that you are facing and I somehow managed to stumble on the solution. Apparently, I had setOnKeyListener to 'return true'. After I changed it to 'return false', the phone keyboard works perfect with backspace functioning properly once again on edittext. Hope this helps:
.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
...
return false;
}
});

EditText OnKeyListener not working

I know this/similar question has been asked before but the solution given is not working for me so I'm asking again.
I tried the solution given in that answer but still my OnKeyListener is never being invoked on some devices, especially the ones with stock OS. I need to detect pressing of del key of soft keyboard when when there is no character in editText. Here is my code;
EditText et = (EditText) findViewById(R.id.et);
et.setOnKeyListener(new EditText.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d("OnKeyListener", keyCode + " character(code) to send");
return false;
}
});
Finally solved myself by implementing this feature through TextWatcher. The major hurdle was that, I needed to detect backspace press even when there is no character in EditText or at least the end user perceives that there is no character there. The fist thing couldn't be achieved however I did the later one. Following is the detailed solution.
First of all, I always retained a space ' ' character in my editText.
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if(cs.toString().length() == 0)
editText.setText(" ");
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }
#Override
public void afterTextChanged(Editable arg0) { }
});
Then I customized EditText to notify me for every cursor position change. This purpose is achieved by overriding onSelectionChanged method of EditText. My customized EditText looks like this.
public class SelectionEnabledEditText extends EditText {
public SelectionEnabledEditText(Context context) {
super(context);
}
public SelectionEnabledEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectionEnabledEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd);
if(onSelectionChangeListener != null)
onSelectionChangeListener.onSelectionChanged(selStart, selEnd);
}
public static interface OnSelectionChangeListener{
public void onSelectionChanged(int selStart, int selEnd);
}
private OnSelectionChangeListener onSelectionChangeListener;
public void setOnSelectionChangeListener(OnSelectionChangeListener onSelectionChangeListener) {
this.onSelectionChangeListener = onSelectionChangeListener;
}
}
Finally, in my activity, I'm listening for cursor position changed event and resetting my cursor position in editText if it's there at the necessary space charatcer start i.e. at 0th index, like this;
editText.setOnSelectionChangeListener(new SelectionEnabledEditText.OnSelectionChangeListener() {
#Override
public void onSelectionChanged(int selStart, int selEnd) {
if (selEnd == 0) {
if (editText.getText().toString().length() == 0)
editText.setText(" ");
editText.setSelection(1);
}
}
});
Hope this would be helpful in similar situations. Suggestions are welcomed for improvements/optimizations.
The documentation states that the key events will only be propagated for the hardware key strokes, not software.
http://developer.android.com/reference/android/view/View.OnKeyListener.html
The device manufacturers are actually being discouraged to propagate soft keyboard events through key listeners, although it is completely up to the manufacturer to honour that or to actually treat the soft and hard keyboards with equal terms.
Starting from Android 4.2.2, Android system itself will not support key stoke events for the soft keyboards at all, so even the manufacturers will not be able to choose their way.
So the only foolproof option here is to implement your own IME (soft keyboard), and handle the keystrokes yourself.
TextWatcher can be used mostly to replace the key listeners, however editText.setText(...); will also trigger the TextWatcher events, so if one is interested in typed keys only then probably TextWatcher is not a solution either.
Please be cautious when using TextWatcher with AutocomleteTextView or EditText. Do not modify text in the AutocompleteTextView / EditText's content from within TextWatcher events, cause otherwise you'll most probably end up in an infinite event/listening loop.
Based on the documentation of the OnKeyListener it seems that the callback is invoked only for hardware keyboards.
Interface definition for a callback to be invoked when a hardware key event is dispatched to this view. The callback will be invoked before the key event is given to the view. This is only useful for hardware keyboards; a software input method has no obligation to trigger this listener.
There's an attribute for EditText: android:imeOptions
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/main_editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionGo"
/>
I noticed that for values: actionGo, actionNone, normal, actionSearch onKeyListener got called.
P.S. It even worked without specifying that attribute.!
Try something like this :
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
//Log key
Log.d("OnKeyListener", keyCode + " character(code) to send");
}
return false;
}

Space Key event behaviour on Numeric Input field?

I created two EditText with "android:inputType="number" property.
here I am using hardware Keyboard, so when I perform Space Key event on textField, focus control directly shift from editText view to some other random view of screen. In normal text field type it took it as an another character, that's fine.
Any one have idea how can use Space key event to retain focus on same field.
Using editText.setInputType(InputType.TYPE_CLASS_NUMBER) may probably solve your problem.
Change/Add your EditText Property with android:imeOptions="actionNext" like as follows
<EditText
android:id="#+id/edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="text" />
Or with android:imeOptions="actionNone" for default behavior of EditText
<EditText
android:id="#+id/edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNone"
android:inputType="text" />
So it looks like your problem doesn't have to do with the 'input' type of your EditText, but rather the key press events coming from the keyboard....
So 'hopefully' this should fix your problem for you (by 'skipping over' the 'next' event from the 'space' button being pressed.)
// do for both EditText(s)
editText1.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
log.d("main","KeyPress:"+ actionID);
if (event != null ) { log.d("main","KeyPress:" + event.getKeyCode() ); }
if ( actionId == EditorInfo.IME_ACTION_NEXT) {
// do 'nothing' or 'add a space' if you want that
return true;
}
return false;
}
});
This is likely what is happening (hard to tell without your XML)
So I found something that should help you figure out the pattern + possibly lead to solving it... from https://stackoverflow.com/a/17990096
if there is a android:nextFocus.... setting in your XML (or equivalent in code) and/or the physical keyboard 'space' is also signalling IME_ACTION_NEXT (or another IME action similar to it)
If the EditorInfo.IME_ACTION_NEXT isn't the IME action that is causing your problems, then you can try this... to determine WHAT is.
from: https://stackoverflow.com/a/4171427
if you have PHYSICAL keyboard you can use to detect keyDown events and handle them appropriately,
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
log.d("main","KeyPress:" + keyCode);
if (event != null ) { log.d("main","KeyPress:" + event.getKeyCode() ); }
// if you want to 'handle' the keyPess here, best to use switch like below
// switch (keyCode) {
// case KeyEvent.KEYCODE_A:
// {
// //your Action code
// return true;
// }
/// }
return super.onKeyDown(keyCode, event);
}
BUT... if you have software keyboard You need to use addTextChangedListener/TextWatcher Because the physical key press is 'eaten' by the EditText (from what I saw in another post, but seems to be correct from my testing.)
mMyEditText.addTextChangedListener(new TextWatcher()
{
public void afterTextChanged(Editable s)
{
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
/*This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.*/
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
);
You can override what the EditText does when a 'space' is entered.
This seems pretty easy when in 'software keyboard', but physical keyboard seems to be a bit more difficult.
https://developer.android.com/reference/android/widget/TextView.OnEditorActionListener.html
Similar to this question (but 'space' instead of 'enter') Android - Handle "Enter" in an EditText
This could help you determine the 'pattern' of the focus being changed. if it is random or not (most likely -not- random, but possibly 'interesting' to look into)
http://developer.android.com/reference/android/view/View.OnFocusChangeListener.html
// try this to see
View.OnFocusChangeListener changeListener = new View.OnFocusChangeListener()
{
#Override
public void onFocusChange(View v, boolean hasFocus) {
log.d("YourClassName", "FocusChanged" + hasFocus)
}
};
EditText1.setOnFocusChangeListener(changeListener);
EditText2.setOnFocusChangeListener(changeListener);
Button.setOnFocusChangeListener(changeListener);
// ... etc... (add to views to see if there is pattern)

Detect backspace in TextWatcher [duplicate]

This question already has answers here:
Android EditText delete(backspace) key event
(17 answers)
Closed 8 years ago.
I am using TextWatcher and I am unable to detect Backspace key in TextWatcher.afterTextChange event. I also want to clear textView on some condition in textWatcher event.
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
// I want to detect backspace key here
}
To detect a backspace in TextWatcher, you can check the variable count that is passed into the onTextChange function (count will be 0 if a backspace was entered), like this:
#Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {
if (react) {
if (count == 0) {
//a backspace was entered
}
//clear edittext
if(/*condition*/) {
react = false;
setText("");
react = true;
}
}
}
The react boolean is needed for the setText() function otherwise it becomes recursive. Hope this helps!
A KeyListener can fulfil both of your conditions.
mEditText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DEL){
//on backspace
}
return false
}
});
Similarly inside the onKey(), you can put multiple check statements to check for the condition, when you would want to clear the textView.
EDIT : As #RankoR was kind enough to point out, please bear in mind that onKeyListener() works only for the hardware keyboards and not the soft keyboards.

android input method problems

A few questions about android:
Is it possible to replace the keys in default keyboards ? For example, is it possible to replace the dot in the numeric keyboard with a comma ?
I wrote a very simple IME, but I cannot set it to an EditText. What I want is to set one of my EditText to use the IME I wrote by default, not the default LatinIME. Is that possible ? How inputMethod attribute works ? I set the fully qualified class name of IME but it raises class not found exception.
Thanks.
Is it possible to replace the keys in default keyboards ?
You don't. Users are in control over their device, including what keyboard gets used.
But You can try to make some input methods
Read this tutorial: Creating an Input Method
clone this repo: LatinIME
And if replacing one character is your requirement, you can override text change listener of edittext, and check each entered character and if user entered dot then replace that with comma as
editText.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
//Check if s contains dot and replace it with comma
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){}
});
But this method executes each key hit in EditText.
try override this method.return another keyCode and see the reslt
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == someKeyCode) {
//...... button is pressed
}
return super.onKeyDown(keyCode, event);
}
Pretty sure replacing keys in the default keyboard is not possible, you would need to write your own keyboard replacement, much like all the keyboard Apps do.

Categories

Resources