onKey and exceptions - android

I'm building an Android application and I'm facing 2 problems. I'm currently using the onKey method to parse a textbox to fetch the user typed data. This is working fine but if the user choose to let the textbox blank and send the data this will cause my application to crash. I would like to add a try and catch to handle/ignore that exception and send nothing if there is a blank even if the enter key is pressed.
My second problem occur when I press the enter key. This cause to send the data 2 times and it's kinda annoying. I think it's because there is no debounce in my code and the program register a key press and a key release. I don't really know how to filter this and I may need some inputs.
Here is my code :
//Listen to the "Enter" button state changes by user selection of keypad
txtSetKp.setOnKeyListener(new OnKeyListener(){ //This method waits for the "enter" key to be hit
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
switch(arg1)
{
case KeyEvent.KEYCODE_ENTER:
float newSetKp = Float.parseFloat(txtSetKp.getText().toString());
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //If "enter" pressed, hide keyboard
if(btSocket != null && btSocket.isConnected()){
mConnectedThread.send("P" + newSetKp);
Log.e(TAG, "P"+newSetKp);
}
imm.hideSoftInputFromWindow(txtSetPoint.getWindowToken(), 0);
return true;
default:
return false;
}
}
});
//Listen to the "Enter" button state changes by user selection of keypad
txtSetKi.setOnKeyListener(new OnKeyListener(){ //This method waits for the "enter" key to be hit
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
switch(arg1)
{
case KeyEvent.KEYCODE_ENTER:
float newSetKi = Float.parseFloat(txtSetKi.getText().toString());
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //If "enter" pressed, hide keyboard
mConnectedThread.send("I" + newSetKi);
imm.hideSoftInputFromWindow(txtSetPoint.getWindowToken(), 0);
return true;
default:
return false;
}
}
});
Thanks for all your help!

for first problem first check whether the text is empty.
if(txtSetKi.getText().length() != 0)
// perform task
for the second problem use
if(keyEvent == KeyEvent.ACTION_DOWN)
// perform task
or
if(keyEvent == KeyEvent.ACTION_UP)
// perform task

Try this
txtSetKp.setImeOptions(EditorInfo.IME_ACTION_DONE);
txtSetKp.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
String text = txtSetKp.getText().toString();
if(isNullOrEmpty(text))
System.out.println("Empty");
else
System.out.println("Correct");
return false;
}
});
}
public boolean isNullOrEmpty(String value) {
return value == null || value.length() == 0;
}

Related

OnKey event dispatched twice when I type some text into a textbox. How to prevent?

during my debug sessions I found a strange thing occurring. I have an EditText control for which I defined the current activity as OnKeyListener to perform validation while user types.
Code
txtPhoneNumber.setOnEditorActionListener(this);
txtPhoneNumber.setOnKeyListener(this);
txtPhoneNumber.setOnFocusChangeListener(this);
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
String phoneNumber = ((TextView) v).getText().toString();
if (phoneNumber != null && !"".equals(phoneNumber))
setValidPhoneNumber(checkValidPhoneNumber(phoneNumber));
setForwardButtonEnabled(this.validPhoneNumber && this.readyToGo);
if (actionId == EditorInfo.IME_ACTION_DONE) {
InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
return false;
}
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String phoneNumber = ((TextView) v).getText().toString();
if (phoneNumber != null && !"".equals(phoneNumber))
setValidPhoneNumber(checkValidPhoneNumber(phoneNumber));
setForwardButtonEnabled(this.validPhoneNumber && this.readyToGo);
return false;
}
OK I can admit that this is quite redundant to perform validation again when the user is pressing the Enter key, more than just closing the soft keyboard. However I found that the OnKey event is dispatched twice.
For example I'm writing 3551234567 and I already typed 355. When I press 1, one event is fired having v.getText() = 355 and next another event has v.getText() = 3551.
I would like to know if this is normal and if this can be avoided by either distinguishing if this is a "preOnKeyEvent" or "postOnKeyEvent". I only need the string after the event, not before.
Thank you
You are probably getting both the key down/key up events.
Try filtering your method by checking the action of the KeyEvent for an ACTION_UP action.
Read this for more information
You get the event for key down and key up. Its better to listen for text change event instead of key event
txtPhoneNumber.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, ....){
//validation
}
});

Is it possible to assign a key press code to the press on an Android button?

I have been working on passing an edit text value to a string so I can upload the input to my database, but after a lot of time working I have figured out how to do this by pressing enter on the keyboard. I also have a button for uploading the string and I want to have only the button involved, so the upload button will be enter also.
Here is my button:
submit.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
postData();
}
});
Here is the key press enter command:
enter.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
name = enter.getText().toString();
return true;
}
return false;
}
});
Here is where I am using the converted string called name:
nameValuePairs.add(new BasicNameValuePair("username", name));
So I want to get rid of the need for the user to press enter before pressing the submit button, so pressing upload will take care of the enter key press code. I tried creating a method to simulate this being pressed but it didn't work, and researching didn't show me a possible way to assign a key press to a button on click.
Any suggestions would be appreciated.
Thanks.
you can try this to perform press button
enter.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
name = enter.getText().toString();
submit.performclick();
return true;
}
return false;
}
});

Hiding the keyboard when user hit the return key on keyboard

First, I don't know what's the key code for the Return key or Backspace the one that has a line on the Android keyboard.
Secondly I have multiple edittext fields on the screen and I want each one to resign the keyboard when the user hit that Return key.
imm= (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
public void onClick(View v) {
int flag;
flag=v.getId();
// keycode for return
if(v.getId()==XX) {
imm.hideSoftInputFromWindow(YYY.getWindowToken(), 0);
}
XX is the keycode for that Return key and YYY is what I should fill in. I would like YYY generic that's applying to all the edittext fields in the program
I'm not sure why you are trying to handle this in an onClick method. The right way, I think, is to call setOnKeyListener() for each EditText view and in your OnKeyListener, you can do this:
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode = KeyEvent.KEYCODE_ENTER) {
// non-null only for enter key
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
return true;
}
return false;
}
A single instance of OnKeyListener can be used for all EditText views (any view at all, actually) where you want this behavior.

Handle edittexts onKeyListener?

I am creating login screen with 2 editTexts: etUsername and etPassword.
On the etUsername, user should input the username and press Enter to go to the edit text etPassword, then he inputs the password, press Enter to login. Here is my current code:
etUsername.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_ENTER)) {
etPassword.requestFocus();
return true;
} else
return false;
}
});
etPassword.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_ENTER)) {
loginToServer();
return true;
} else
return false;
}
});
But when I input the username, and then press Enter – the program tries to log in to the server.
In the debug mode, I saw that when I pressed Enter once (on the etUsername) then first: etUsername.onKey() is called and then etPassword.onKey() is also called !
How can I modify the code so that the ENTER event is only processed once for the current field?
Before you check which key is pressed, try adding a check for which key event occurs. I would guess that it first triggers on the key-down event, then you move focus to the second text field, and here it also triggers on the key-up event.
See here for an example on how to check both the event type and key: Use "ENTER" key on softkeyboard instead of clicking button
I'm not 100% sure of this, but it is worth a try :-)

Android - Handle "Enter" in an EditText

I am wondering if there is a way to handle the user pressing Enter while typing in an EditText, something like the onSubmit HTML event.
Also wondering if there is a way to manipulate the virtual keyboard in such a way that the "Done" button is labeled something else (for example "Go") and performs a certain action when clicked (again, like onSubmit).
I am wondering if there is a way to
handle the user pressing Enter while
typing in an EditText, something like
the onSubmit HTML event.
Yes.
Also wondering if there is a way to
manipulate the virtual keyboard in
such a way that the "Done" button is
labeled something else (for example
"Go") and performs a certain action
when clicked (again, like onSubmit).
Also yes.
You will want to look at the android:imeActionId and android:imeOptions attributes, plus the setOnEditorActionListener() method, all on TextView.
For changing the text of the "Done" button to a custom string, use:
mEditText.setImeActionLabel("Custom text", KeyEvent.KEYCODE_ENTER);
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
// Perform action on key press
Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
Here's what you do. It's also hidden in the Android Developer's sample code 'Bluetooth Chat'. Replace the bold parts that say "example" with your own variables and methods.
First, import what you need into the main Activity where you want the return button to do something special:
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.view.KeyEvent;
Now, make a variable of type TextView.OnEditorActionListener for your return key (here I use exampleListener);
TextView.OnEditorActionListener exampleListener = new TextView.OnEditorActionListener(){
Then you need to tell the listener two things about what to do when the return button is pressed. It needs to know what EditText we're talking about (here I use exampleView), and then it needs to know what to do when the Enter key is pressed (here, example_confirm()). If this is the last or only EditText in your Activity, it should do the same thing as the onClick method for your Submit (or OK, Confirm, Send, Save, etc) button.
public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_DOWN) {
example_confirm();//match this behavior to your 'Send' (or Confirm) button
}
return true;
}
Finally, set the listener (most likely in your onCreate method);
exampleView.setOnEditorActionListener(exampleListener);
This page describes exactly how to do this.
https://developer.android.com/training/keyboard-input/style.html
Set the android:imeOptions then you just check the actionId in onEditorAction. So if you set imeOptions to 'actionDone' then you would check for 'actionId == EditorInfo.IME_ACTION_DONE' in onEditorAction. Also, make sure to set the android:inputType.
If using Material Design put code in TextInputEditText.
Here's the EditText from the example linked above:
<EditText
android:id="#+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/search_hint"
android:inputType="text"
android:imeOptions="actionSend" />
You can also set this programmatically using the setImeOptions(int) function. Here's the OnEditorActionListener from the example linked above:
EditText editText = (EditText) findViewById(R.id.search);
editText.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND) {
sendMessage();
handled = true;
}
return handled;
}
});
Hardware keyboards always yield enter events, but software keyboards return different actionIDs and nulls in singleLine EditTexts. This code responds every time the user presses enter in an EditText that this listener has been set to, regardless of EditText or keyboard type.
import android.view.inputmethod.EditorInfo;
import android.view.KeyEvent;
import android.widget.TextView.OnEditorActionListener;
listener=new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (event==null) {
if (actionId==EditorInfo.IME_ACTION_DONE);
// Capture soft enters in a singleLine EditText that is the last EditText.
else if (actionId==EditorInfo.IME_ACTION_NEXT);
// Capture soft enters in other singleLine EditTexts
else return false; // Let system handle all other null KeyEvents
}
else if (actionId==EditorInfo.IME_NULL) {
// Capture most soft enters in multi-line EditTexts and all hard enters.
// They supply a zero actionId and a valid KeyEvent rather than
// a non-zero actionId and a null event like the previous cases.
if (event.getAction()==KeyEvent.ACTION_DOWN);
// We capture the event when key is first pressed.
else return true; // We consume the event when the key is released.
}
else return false;
// We let the system handle it when the listener
// is triggered by something that wasn't an enter.
// Code from this point on will execute whenever the user
// presses enter in an attached view, regardless of position,
// keyboard, or singleLine status.
if (view==multiLineEditText) multiLineEditText.setText("You pressed enter");
if (view==singleLineEditText) singleLineEditText.setText("You pressed next");
if (view==lastSingleLineEditText) lastSingleLineEditText.setText("You pressed done");
return true; // Consume the event
}
};
The default appearance of the enter key in singleLine=false gives a bent arrow enter keypad. When singleLine=true in the last EditText the key says DONE, and on the EditTexts before it it says NEXT. By default, this behavior is consistent across all vanilla, android, and google emulators. The scrollHorizontal attribute doesn't make any difference. The null test is important because the response of phones to soft enters is left to the manufacturer and even in the emulators, the vanilla Level 16 emulators respond to long soft enters in multi-line and scrollHorizontal EditTexts with an actionId of NEXT and a null for the event.
I know this is a year old, but I just discovered this works perfectly for an EditText.
EditText textin = (EditText) findViewById(R.id.editText1);
textin.setInputType(InputType.TYPE_CLASS_TEXT);
It prevents anything but text and space. I could not tab, "return" ("\n"), or anything.
In your xml, add the imeOptions attribute to the editText
<EditText
android:id="#+id/edittext_additem"
...
android:imeOptions="actionDone"
/>
Then, in your Java code, add the OnEditorActionListener to the same EditText
mAddItemEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_DONE){
//do stuff
return true;
}
return false;
}
});
Here is the explanation-
The imeOptions=actionDone will assign "actionDone" to the EnterKey. The EnterKey in the keyboard will change from "Enter" to "Done". So when Enter Key is pressed, it will trigger this action and thus you will handle it.
I had a similar purpose. I wanted to resolve pressing the "Enter" key on the keyboard (which I wanted to customize) in an AutoCompleteTextView which extends TextView. I tried different solutions from above and they seemed to work. BUT I experienced some problems when I switched the input type on my device (Nexus 4 with AOKP ROM) from SwiftKey 3 (where it worked perfectly) to the standard Android keyboard (where instead of handling my code from the listener, a new line was entered after pressing the "Enter" key. It took me a while to handle this problem, but I don't know if it will work under all circumstances no matter which input type you use.
So here's my solution:
Set the input type attribute of the TextView in the xml to "text":
android:inputType="text"
Customize the label of the "Enter" key on the keyboard:
myTextView.setImeActionLabel("Custom text", KeyEvent.KEYCODE_ENTER);
Set an OnEditorActionListener to the TextView:
myTextView.setOnEditorActionListener(new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event)
{
boolean handled = false;
if (event.getAction() == KeyEvent.KEYCODE_ENTER)
{
// Handle pressing "Enter" key here
handled = true;
}
return handled;
}
});
I hope this can help others to avoid the problems I had, because they almost drove me nuts.
Just as an addendum to Chad's response (which worked almost perfectly for me), I found that I needed to add a check on the KeyEvent action type to prevent my code executing twice (once on the key-up and once on the key-down event).
if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN)
{
// your code here
}
See http://developer.android.com/reference/android/view/KeyEvent.html for info about repeating action events (holding the enter key) etc.
You can also do it..
editText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
{
Log.i("event", "captured");
return false;
}
return false;
}
});
If you use DataBinding, see https://stackoverflow.com/a/52902266/2914140 and https://stackoverflow.com/a/67933283/2914140.
Bindings.kt:
#BindingAdapter("onEditorEnterAction")
fun EditText.onEditorEnterAction(callback: OnActionListener?) {
if (callback == null) setOnEditorActionListener(null)
else setOnEditorActionListener { v, actionId, event ->
val imeAction = when (actionId) {
EditorInfo.IME_ACTION_DONE,
EditorInfo.IME_ACTION_SEND,
EditorInfo.IME_ACTION_GO -> true
else -> false
}
val keydownEvent = event?.keyCode == KeyEvent.KEYCODE_ENTER
&& event.action == KeyEvent.ACTION_DOWN
if (imeAction or keydownEvent) {
callback.enterPressed()
return#setOnEditorActionListener true
}
return#setOnEditorActionListener false
}
}
interface OnActionListener {
fun enterPressed()
}
layout.xml:
<data>
<variable
name="viewModel"
type="YourViewModel" />
</data>
<EditText
android:imeOptions="actionDone|actionSend|actionGo"
android:singleLine="true"
android:text="#={viewModel.message}"
app:onEditorEnterAction="#{() -> viewModel.send()}" />
First, you have to set EditText listen to key press
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set the EditText listens to key press
EditText edittextproductnumber = (EditText) findViewById(R.id.editTextproductnumber);
edittextproductnumber.setOnKeyListener(this);
}
Second, define the event upon the key press, for example, event to set TextView's text:
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
// Listen to "Enter" key press
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER))
{
TextView textviewmessage = (TextView) findViewById(R.id.textViewmessage);
textviewmessage.setText("You hit 'Enter' key");
return true;
}
return false;
}
And finally, do not forget to import EditText,TextView,OnKeyListener,KeyEvent at top:
import android.view.KeyEvent;
import android.view.View.OnKeyListener;
import android.widget.EditText;
import android.widget.TextView;
password.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
submit.performClick();
return true;
}
return false;
}
});
Works very fine for me
In addition hide keyboard
working perfectly
public class MainActivity extends AppCompatActivity {
TextView t;
Button b;
EditText e;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button) findViewById(R.id.b);
e = (EditText) findViewById(R.id.e);
e.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (before == 0 && count == 1 && s.charAt(start) == '\n') {
b.performClick();
e.getText().replace(start, start + 1, ""); //remove the <enter>
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(Editable s) {}
});
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
b.setText("ok");
}
});
}
}
working perfectly
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId != 0 || event.getAction() == KeyEvent.ACTION_DOWN) {
// Action
return true;
} else {
return false;
}
}
});
Xml
<EditText
android:id="#+id/editText2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/password"
android:imeOptions="actionGo|flagNoFullscreen"
android:inputType="textPassword"
android:maxLines="1" />
This should work
input.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#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( -1 != input.getText().toString().indexOf( "\n" ) ){
input.setText("Enter was pressed!");
}
}
});
Type this code in your editor so that it can import necessary modules.
query.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
if(actionId == EditorInfo.IME_ACTION_DONE
|| keyEvent.getAction() == KeyEvent.ACTION_DOWN
|| keyEvent.getAction() == KeyEvent.KEYCODE_ENTER) {
// Put your function here ---!
return true;
}
return false;
}
});
you can use this way
editText.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// Do some things
return true;
}
return false;
});
you can see list of action there.
For example:
IME_ACTION_GO
IME_ACTION_SEARCH
IME_ACTION_SEND
This works fine on LG Android phones. It prevents ENTER and other special characters to be interpreted as normal character. Next or Done button appears automatically and ENTER works as expected.
edit.setInputType(InputType.TYPE_CLASS_TEXT);
Here's a simple static function that you can throw into your Utils or Keyboards class that will execute code when the user hits the return key on a hardware or software keyboard. It's a modified version of #earlcasper's excellent answer
/**
* Return a TextView.OnEditorActionListener that will execute code when an enter is pressed on
* the keyboard.<br>
* <code>
* myTextView.setOnEditorActionListener(Keyboards.onEnterEditorActionListener(new Runnable()->{
* Toast.makeText(context,"Enter Pressed",Toast.LENGTH_SHORT).show();
* }));
* </code>
* #param doOnEnter A Runnable for what to do when the user hits enter
* #return the TextView.OnEditorActionListener
*/
public static TextView.OnEditorActionListener onEnterEditorActionListener(final Runnable doOnEnter){
return (__, actionId, event) -> {
if (event==null) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// Capture soft enters in a singleLine EditText that is the last EditText.
doOnEnter.run();
return true;
} else if (actionId==EditorInfo.IME_ACTION_NEXT) {
// Capture soft enters in other singleLine EditTexts
doOnEnter.run();
return true;
} else {
return false; // Let system handle all other null KeyEvents
}
} else if (actionId==EditorInfo.IME_NULL) {
// Capture most soft enters in multi-line EditTexts and all hard enters.
// They supply a zero actionId and a valid KeyEvent rather than
// a non-zero actionId and a null event like the previous cases.
if (event.getAction()==KeyEvent.ACTION_DOWN) {
// We capture the event when key is first pressed.
return true;
} else {
doOnEnter.run();
return true; // We consume the event when the key is released.
}
} else {
// We let the system handle it when the listener
// is triggered by something that wasn't an enter.
return false;
}
};
}
InputType on the textfield must be text in order for what CommonsWare said to work. Just tried all of this, no inputType before the trial and nothing worked, Enter kept registering as soft enter. After inputType = text, everything including the setImeLabel worked.
Example : android:inputType="text"
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
// Perform action on key press
Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
Using Kotlin I've made a function that handles all kinds of "done"-like actions for EditText, including the keyboard, and it's possible to modify it and also handle other keys as you wish, too :
private val DEFAULT_ACTIONS_TO_HANDLE_AS_DONE_FOR_EDIT_TEXT = arrayListOf(EditorInfo.IME_ACTION_SEND, EditorInfo.IME_ACTION_GO, EditorInfo.IME_ACTION_SEARCH, EditorInfo.IME_ACTION_DONE)
private val DEFAULT_KEYS_TO_HANDLE_AS_DONE_FOR_EDIT_TEXT = arrayListOf(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_NUMPAD_ENTER)
fun EditText.setOnDoneListener(function: () -> Unit, onKeyListener: OnKeyListener? = null, onEditorActionListener: TextView.OnEditorActionListener? = null,
actionsToHandle: Collection<Int> = DEFAULT_ACTIONS_TO_HANDLE_AS_DONE_FOR_EDIT_TEXT,
keysToHandle: Collection<Int> = DEFAULT_KEYS_TO_HANDLE_AS_DONE_FOR_EDIT_TEXT) {
setOnEditorActionListener { v, actionId, event ->
if (onEditorActionListener?.onEditorAction(v, actionId, event) == true)
return#setOnEditorActionListener true
if (actionsToHandle.contains(actionId)) {
function.invoke()
return#setOnEditorActionListener true
}
return#setOnEditorActionListener false
}
setOnKeyListener { v, keyCode, event ->
if (onKeyListener?.onKey(v, keyCode, event) == true)
return#setOnKeyListener true
if (event.action == KeyEvent.ACTION_DOWN && keysToHandle.contains(keyCode)) {
function.invoke()
return#setOnKeyListener true
}
return#setOnKeyListener false
}
}
So, sample usage:
editText.setOnDoneListener({
//do something
})
As for changing the label, I think it depends on the keyboard app, and that it usually change only on landscape, as written here. Anyway, example usage for this:
editText.imeOptions = EditorInfo.IME_ACTION_DONE
editText.setImeActionLabel("ASD", editText.imeOptions)
Or, if you want in XML:
<EditText
android:id="#+id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:imeActionLabel="ZZZ" android:imeOptions="actionDone" />
And the result (shown in landscape) :
Kotlin solution to react to enter press using Lambda expression:
editText.setOnKeyListener { _, keyCode, event ->
if(keyCode == KeyEvent.KEYCODE_ENTER && event.action==KeyEvent.ACTION_DOWN){
//react to enter press here
}
true
}
not doing the additional check for the type of event will cause this listener to be called twice when pressed once (once for ACTION_DOWN, once for ACTION_UP)
A dependable way to respond to an <enter> in an EditText is with a TextWatcher, a LocalBroadcastManager, and a BroadcastReceiver. You need to add the v4 support library to use the LocalBroadcastManager. I use the tutorial at vogella.com: 7.3 "Local broadcast events with LocalBroadcastManager" because of its complete concise code Example. In onTextChanged before is the index of the end of the change before the change>;minus start. When in the TextWatcher the UI thread is busy updating editText's editable, so we send an Intent to wake up the BroadcastReceiver when the UI thread is done updating editText.
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.Editable;
//in onCreate:
editText.addTextChangedListener(new TextWatcher() {
public void onTextChanged
(CharSequence s, int start, int before, int count) {
//check if exactly one char was added and it was an <enter>
if (before==0 && count==1 && s.charAt(start)=='\n') {
Intent intent=new Intent("enter")
Integer startInteger=new Integer(start);
intent.putExtra("Start", startInteger.toString()); // Add data
mySendBroadcast(intent);
//in the BroadcastReceiver's onReceive:
int start=Integer.parseInt(intent.getStringExtra("Start"));
editText.getText().replace(start, start+1,""); //remove the <enter>
//respond to the <enter> here
This question hasn't been answered yet with Butterknife
LAYOUT XML
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/some_input_hint">
<android.support.design.widget.TextInputEditText
android:id="#+id/textinput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionSend"
android:inputType="text|textCapSentences|textAutoComplete|textAutoCorrect"/>
</android.support.design.widget.TextInputLayout>
JAVA APP
#OnEditorAction(R.id.textinput)
boolean onEditorAction(int actionId, KeyEvent key){
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND || (key.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
//do whatever you want
handled = true;
}
return handled;
}
Replace "txtid" with your EditText ID.
EditText txtinput;
txtinput=findViewById(R.id.txtid)
txtinput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
//Code for the action you want to proceed with.
InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
return false;
}
});
Add these depencendy, and it should work:
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
This will give you a callable function when the user presses the return key.
fun EditText.setLineBreakListener(onLineBreak: () -> Unit) {
val lineBreak = "\n"
doOnTextChanged { text, _, _, _ ->
val currentText = text.toString()
// Check if text contains a line break
if (currentText.contains(lineBreak)) {
// Uncommenting the lines below will remove the line break from the string
// and set the cursor back to the end of the line
// val cleanedString = currentText.replace(lineBreak, "")
// setText(cleanedString)
// setSelection(cleanedString.length)
onLineBreak()
}
}
}
Usage
editText.setLineBreakListener {
doSomething()
}
I created a helper class for this by extending the new MaterialAlertDialogBuilder
Usage
new InputPopupBuilder(context)
.setInput(R.string.send,
R.string.enter_your_message,
text -> sendFeedback(text, activity))
.setTitle(R.string.contact_us)
.show();
Code
public class InputPopupBuilder extends MaterialAlertDialogBuilder {
private final Context context;
private final AppCompatEditText input;
public InputPopupBuilder(Context context) {
super(context);
this.context = context;
input = new AppCompatEditText(context);
input.setInputType(InputType.TYPE_CLASS_TEXT);
setView(input);
}
public InputPopupBuilder setInput(int actionLabel, int hint, Callback callback) {
input.setHint(hint);
input.setImeActionLabel(context.getString(actionLabel), KeyEvent.KEYCODE_ENTER);
input.setOnEditorActionListener((TextView.OnEditorActionListener) (v, actionId, event) -> {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_DOWN) {
Editable text = input.getText();
if (text != null) {
callback.onClick(text.toString());
return true;
}
}
return false;
});
setPositiveButton(actionLabel, (dialog, which) -> {
Editable text = input.getText();
if (text != null) {
callback.onClick(text.toString());
}
});
return this;
}
public InputPopupBuilder setText(String text){
input.setText(text);
return this;
}
public InputPopupBuilder setInputType(int inputType){
input.setInputType(inputType);
return this;
}
public interface Callback {
void onClick(String text);
}
}
Requires
implementation 'com.google.android.material:material:1.3.0-alpha04'

Categories

Resources