android keylistener losing key taps - android

I am using a keylistener to get key taps. The problem is that once you tap the delete key, the next key tap is not registering. The key tap after that keeps working. If I tap 2 deletes in a row, they work, just no other keys. They just disappear.
I put in a log test before the "if (keycode" section and it shows nothing after the first delete is pressed, unless it is another delete.
I am using the following code (Thanks Shawn).:
itemPrice.setKeyListener(new CalculatorKeyListener());
itemPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
class CalculatorKeyListener extends NumberKeyListener {
public int getInputType() {
return InputType.TYPE_CLASS_NUMBER;
}
#Override
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event)
{
if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
digitPressed(keyCode - KeyEvent.KEYCODE_0);
} else if (keyCode == KeyEvent.KEYCODE_DEL) {
deletePressed();
}
return true;
}
#Override
protected char[] getAcceptedChars() {
return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}
}
With this problem the keylistener provides no value to me. There must be something that I am missing.
Thanks,

Related

detect middle (rotary) button click on android waer

I am developing an app for Android Wear and are using the hardware buttons.
I can manage to catch the buttons with the onKeyDown override:
public boolean onKeyDown(int keyCode, KeyEvent event){
Log.i("CLICK", Integer.toString(keyCode));
if (event.getRepeatCount() == 0) {
if (keyCode == KeyEvent.KEYCODE_STEM_1) {
// Do stuff
return true;
} else if (keyCode == KeyEvent.KEYCODE_STEM_2) {
// Do stuff
return true;
} else if (keyCode == KeyEvent.KEYCODE_STEM_3) {
// Do stuff
return true;
}
}
return super.onKeyDown(keyCode, event);
}
I would also like to catch a click on the middle (rotary) button,
but when I click this button, the watch is going back to the default 'home'(watchface)-screen,
and no event is being logged.
I can manage to catch the rotary scrolling, but it's the click I'd like to use.
#Override
public boolean onGenericMotionEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_SCROLL && RotaryEncoder.isFromRotaryEncoder(ev)) {
// // Note that we negate the delta value here in order to get the right scroll direction.
// float delta = -RotaryEncoder.getRotaryAxisValue(ev)
// * RotaryEncoder.getScaledScrollFactor(getContext());
// scrollBy(0, Math.round(delta));
return true;
}
return super.onGenericMotionEvent(ev);
}
Is this possible, or is it impossible to override the functionallity of the middle watch button?
AFAIU It should be getting KEYCODE_HOME as key event on pressing RSB in onKeyDown().
If it is the case then it is controlled by Android framework only and apps can't do anything with it.
Here is the official description
Key code constant: Home key. This key is handled by the framework and
is never delivered to applications.
https://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_HOME

Android SoftKeyboard onKeyDown/Up not detecting 'alternative' keys

I have a view which handles input for me, I pop up a keyboard and set the view focusable. Now I can get certain key presses...
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
} else if (keyCode == KeyEvent.KEYCODE_ENTER) {
} else {
}
}
and so on... the character pressed I get by using
event.getDisplayLabel()
That works as long as I only want the normal letters A-Z.
In other languages, more letters can be reached by long pressing a normal letter on the soft keyboard... however, these alternative letters cannot be detected by onKeyDown/Up. I can only detect the normal letters, the labels of the soft keyboard.
Now my app has to process foreign input and letters, I have changed the keyboard to turkish and I can find letters like í ì ú ù on the keyboard, but if I press them, I don't get any response. Not with event.getDisplayLabel nor event.getUnicodeChar();
How do I detect these letters?
When the keyboard is open, onKeyDown() and onKeyUp() methods don't work properly because Android considers on-screen keyboard as a separate activity.
The easiest way to achieve what you want is to override onKeyPreIme() method on your view. For example, if you're trying to capture onKeyDown from an EditText, create a new Class which extends EditText, and override the onKeyPreIme() method:
public class LoseFocusEditText extends EditText {
private Context mContext;
protected final String TAG = getClass().getName();
public LoseFocusEditText(Context context) {
super(context);
mContext = context;
}
public LoseFocusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public LoseFocusEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//hide keyboard
InputMethodManager mgr = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
//lose focus
this.clearFocus();
return true;
}
return false;
}
}
This was tested on kitkat / htc one.
Edit:
I'm not sure what is causing the onKeyDown not to be called at all. Perhaps it's an issue with your view? There may be a better answer than my solution because of this. Either way, this might work:
Instead of using the onKeyDown from the view, override dispatchKeyEvent at the activity level. This will handle your key event before it gets to the window manager, so make sure to call super on any key events you do not explicitly handle.
Example using the ACTION_DOWN (as every event has both ACTION_UP and ACTION_DOWN) since your example used onKeyDown:
#Override
public boolean dispatchKeyEvent(KeyEvent event){
if(event.getAction() == KeyEvent.ACTION_UP) {
return super.dispatchKeyEvent(event);
}
if (keyCode == KeyEvent.KEYCODE_DEL) {
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
} else if (keyCode == KeyEvent.KEYCODE_ENTER) {
} else {
return super.dispatchKeyEvent(event);
}
}
NOW (sorry about that)
You can try:
char key = (char)event.getUnicodeChar();
Instead of
char key = event.getDisplayLabel();
getDisplayLabel() will only give you the key that is displayed on the keyboard, which as you point out, is not necessarily the character the user has selected.
Got it :)
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction()==KeyEvent.ACTION_DOWN) return true;
if(keyCode==KeyEvent.KEYCODE_ALT_LEFT || keyCode==KeyEvent.KEYCODE_ALT_RIGHT || keyCode==KeyEvent.KEYCODE_SHIFT_LEFT || keyCode==KeyEvent.KEYCODE_SHIFT_RIGHT) return true;
if (keyCode == KeyEvent.KEYCODE_DEL) {
doBackspace();
return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
if(this.avl!=null) this.avl.onInputCancelled(this);
return false;
} else if (keyCode == KeyEvent.KEYCODE_ENTER) {
inputstarted=false;
if(this.avl!=null) this.avl.onInputFinished(this,this.text,celldata);
return true;
}
String key = "";
if (event.getAction()==KeyEvent.ACTION_UP) key = String.valueOf((char)event.getUnicodeChar()).toUpperCase();
else if (event.getAction()==KeyEvent.ACTION_MULTIPLE) key = String.valueOf(event.getCharacters()).toUpperCase();
return process(key);
}
The important part is blocking the ALT_LEFT/SHIFT_LEFT/etc keycodes and differentiate between ACTION_UP/ACTION_MULTIPLE and either use event.getUnicodeChar() or event.getCharacters().
It works now, I can get all of the chars and even KEYCODE_DEL works on the mobile. But on the tablet I still get no callback for the delete key. Seems like a bad bug, as today in the morning it worked fine even on tablet.

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.

Android: onKeyDown does not trigger until after mouse click

I have an onKeyDown Event which is supposed to display an image once triggered, but I have noticed that despite pressing the corresponding key several times, the image does not appear until I click anywhere on the canvas with my mouse. Any suggestions on the actual problem and how to proceed? Pretty new to the concept so not quite sure what may be missing.
*Edited and pasted class in its entirety.
Thanks
public class BuccaneerView extends TileView {
public static final int PLAYER = 1;
public static final int GREEN_STAR = 2;
Coordinate P_Location;
public BuccaneerView(Context context, AttributeSet attrs) {
super(context, attrs);
initBucc();
}
private void initBucc() {
this.setFocusable(true);
Resources r = this.getContext().getResources();
resetTiles(4);
loadTile(PLAYER, r.getDrawable(R.drawable.aerialplayer));
loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));
/**/
P_Location = new Coordinate(5,5);
setTile(PLAYER, P_Location.x, P_Location.y);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {
if (keyCode == KeyEvent.KEYCODE_SPACE)
{
setTile(GREEN_STAR, 1, 0);
}
return super.onKeyDown(keyCode, msg);
}
public void update()
{
}
}
You seem to be treating onKeyDown as one of your on methods.
return super.onKeyDown(keyCode, msg);
Is a bad thing to do, its as if you have called this function and want to return what key has been pressed. Change it to simply be return false which will mean you are handling what they keyboard is doing.
EDIT
Is there any reason you use onKeyDown and not onKey? Here is some extra code which I use, it uses an array of booleans (pressedKeys, which is 128 in length) and you can later use it to check the array to see if a key is pressed
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (event.getAction() == android.view.KeyEvent.ACTION_DOWN)
{
if(keyCode > 0 && keyCode < 127)
pressedKeys[keyCode] = true;
}
if (event.getAction() == android.view.KeyEvent.ACTION_UP)
{
if(keyCode > 0 && keyCode < 127)
pressedKeys[keyCode] = false;
}
keyEventsBuffer.add(keyEvent);
}
return false;
}
So with this you can then say
If(pressedKeys[KeyYouWantToCheck])
{
//Do some stuff if that key is down
}
At a guess, the key event is not being delivered to whatever you have set the key listener on. This can happen if there is another view in between which is a listener and which stops the propagation of the key event (i.e. returning true from this method). There are some views which do this by default (e.g. EditText for most keys). It would be helpful if you could edit your question and include more code, or describe how your activity is setup.
By 'clicking on the canvas' you are probably changing the focus and making the key event being delivered to a different view. This could explain why you suddenly see the key listener working after clicking.

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