New to programming, now to android. So I hope I dont annoy you to much.
How would I go about setting an onkeylistener at the top level of the app that captured the keyevent no matter what.
Basically what i have is a linear layout with dynamically added edittexts.
I want to capture the Enter key event and have it get the current edittext, perform some tests then create a new edittext and add it to the layout.
I know I can (and have) implement an onkeylistener to individual child views, but not being a programmer, the logic seems weird to create an edittext that listens for input to create another edittext that listens for input to create another.... (you see where this goes)
Can anyone point me in the right direction?
I have lots more info about what Im trying to do, I just dont know what is pertinent and what is not, so let me know if you need more.
Thanks for your time in advance,
Chris
Take a look at http://developer.android.com/reference/android/app/Activity.html#dispatchKeyEvent%28android.view.KeyEvent%29
What you want is to intercept all the events before they are processed by any View in the window. Return true if the event was handled or false if you want the childs to process the event further.
Like Ben said your activity can implement OnKeyListener then for each EditText you create, set the OnKeyListener to be the activity.
editText1.setOnKeyListener(this);
And then in your implementation of onKey you can handle the key press event.
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(v == editText1) {
// do something
} else if( v == editText2 ) {
// do something
}
return true; // return true if you handled the keypress
}
Your activity can implement OnKeyListener.
Related
I'm starting with one programatically created AutoCompleteTextView view on my layout. After user typed valid data into the field, I'm creating a new AutoCompleteTextView object right under the first one by the same way, with the same parameters. I'm storing all of the field references in an ArrayList to keep up with the last one, this way I'm making sure that there will be new fields only under the one at the bottom (basically the last element in the reference list) - so it goes on at every field.
I would like to add this feature: when a new field is created, I change the last field's IME options to EditorInfo.IME_ACTION_NEXT and nextFocusForward attribute to the freshly created field - also programmatically. What I want to achieve: right when user presses Enter on the keyboard, last field's focus jumps to the new field. I'm using this code to set new IME options:
ArrayList<AutoCompleteTextView> fields = new ArrayList<>();
//Creating freshlyCreatedField, IT'S STILL NOT IN THE fields LIST!
AutoCompleteTextView currentlySelectedField = fields.get(fields.size() - 1); // last element
currentlySelectedField.setImeOptions(EditorInfo.IME_ACTION_NEXT);
currentlySelectedField.setNextFocusForwardId(freshlyCreatedField.getId());
currentlySelectedField.setSingleLine(true); //ACTV needs it to get IME to work
//Adding freshlyCreatedField to the fields list,
//so next time it will be the currentlySelectedField
But after running this code nothing happens to the currently selected AutoCompleteTextView object. Clearing and requesting focus did not work, and making it work by the reversed way (creating +1 "invisible" (technically GONE) field everytime) would be much more painful.
One more thing: after selecting any other field and re-selecting the one with configuration changes the Enter button works as it should first time! If I could do the same programmatically, it would solve my problem... so, any ideas how to do it? (Of course, I welcome better solutions also... ;) )
After some days, I've started to play with this problem again. Yes, it is a solution, but no, it's not so pretty as I would it to be like...
Anyhow, I created this code:
ArrayList<AutoCompleteTextView> fields = new ArrayList<>();
//Creating freshlyCreatedField, IT'S STILL NOT IN THE fields LIST!
//Last element
AutoCompleteTextView currentlySelectedField = fields.get(fields.size() - 1);
currentlySelectedField.setOnEditorActionListener(
new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_NEXT
|| actionId == EditorInfo.IME_ACTION_DONE
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
freshlyCreatedField.requestFocus();
handled = true;
}
return handled;
}
});
//Adding freshlyCreatedField to the fields list,
//so next time it will be the currentlySelectedField
I put an EditorActionListener to the field actually under edit where the keyboard listens for one of the IME_ACTION_NEXT (if it's already set) and IME_ACTION_DONE action IDs (it's the default), or for the Enter key (for the case if someone would like to use physical keyboard). Then it jumps to the field below.
It works great, there aren't terrible problems with this approach. However I'm a little bit sad, because all of these possibilities stay invisible. The Done action button switches to Next only by clicking to somewhere else as I wrote it down in my question. So I think my "solution" can work, but it's not the best answer, so feel free to write your thoughts down if you have another idea... :)
Quick, probably simple, question. I have a view whose background is animating, and during that time, I want to disable the user from interacting with the view. My view is a FrameLayout, and I'm capturing touch events with onTouchEvent(). Solutions I've tried:
1) First setOnTouchListener(null), then setOnTouchListener(this). Problem is, my view only calls onTouchEvent(MotionEvent), and not onTouch(View, MotionEvent), so I can't pump through the Events there.
2) First setEnabled(false), then setEnabled(true). The source code says: A disabled view that is clickable still consumes the touch events, it just doesn't respond to them. Problem is, MotionEvents still get pumped through in onTouchEvent().
3) requestDisallowInterceptTouchEvent(false), then (true). This only handles touch events from the parent.
The solution I have working is using a boolean variable isAnimating, and checking the value of that in onTouchEvent(). I'd rather not do this, because it looks ugly to me and I'd rather use the API for it than reinvent the wheel, sooo... anyone got any ideas? Thanks.
Try:
setFocusable() and setFocusableInTouchMode()
Try:
#Override
public boolean onTouchEvent(MotionEvent event) {
//Check if event is on your view
if(event.getY()>view.getTop()&&event.getY()<view.getBottom()&&event.getX()>view.getLeft()&&event.getX()<view.getRight()){
//event occured inside your view
}
//here return super or as your logic prefer
return super.onTouchEvent(event);
}
I would like to ask if someone could give me a simple explanation of the KeyEvent.ACTION_MULTIPLE in Android and an example when it is triggered.
Here -> http://developer.android.com/reference/android/view/KeyEvent.html#ACTION_MULTIPLE it says that:
When interacting with an IME, the framework may deliver key events with the special action ACTION_MULTIPLE that either specifies that single repeated key code or a sequence of characters to insert.
What does it mean reapeted key code? That a key is pressed and held down? Sorry but it is not really clear to me cause I am not English and I am new in the Android developing.
Thanks for the attention!
EDIT:
So the event is triggered only when an arrow key of the keyboard is pressed and held down? As the user whose answer was accepted says here -> What triggers (or generates) KeyEvent.ACTION_MULTIPLE?, is it correct?
Your question made me curious :)..so I tried this code,and I was able to repeat this with a few keys.eg.
Backpress:when you press this key continuously,the IME starts deleting one word a ta time instead of one letter.similarly,it is possible determine multiple presses of keys which support such action.
This again depends on the IME.This would also be useful majorly from an IME app's Point.You cannot often replicate it is because long press usually triggers a different character.
Another point would be that KeyCodes are also inputted from the presence of a hardware keyboard.So this can come up and depends how you handle it.
While the http://developer.android.com/reference/android/view/View.OnKeyListener.html says that this action is triggerred only hardware keyboards,it worked with my software keyboard too.ALTHOUGH they are not expected to do so.I guess you can say that this would into picture when you use a hardware keyboard
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText et = (EditText) findViewById(R.id.checkText);
KeyListener listener = et.getKeyListener();
Log.d("tag", listener.toString());
et.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d("tag", event.getAction()+"event");
return true;
}
});
}
}
I would like to implement an EditText that operates similarly to the android alarm app. In this app, there are two EditText fields that serve as the HH and mm. Typing in these fields overwrites the number that was previously there. When you have typed the second number into the HH field, focus automatically switches to the mm field.
I have tried to put this logic in manually using a TextWatcher in the afterTextChanged() method, but unfortunately modifying the text whilst in this method causes a recursive loop.
What's the correct way to implement this?
See below for alarm app example:
add listener to your hh text view like this
hh.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (hh.getText().toString().length() == 2){
mm.requestFocus();
}
return false;
}
});
hope this will work for you.
It turns out editing the text from the onTextChanged method doesn't actually cause a recursive loop, as long as you temporarily disable the logic with a boolean switch. Painstakingly wrote in all the logic into the TextWatcher to mimic the alarm-style EditText fields.
I have a view in my app which contains a ListView. Sometimes a row in the list is highlighted when the activity starts or resumes and if I hit the Enter key (on the physical keyboard of my device) then it does a click on the row.
I tried to override the OnKeyListener of the main view or of the list or to set it to null but it didn't change anything.
How can I achieve this ?
EDIT : sorry if it wasn't clear.
I want the ListView to react on clicks but only if I touch the screen, not when I push the enter key. And I don't want the list to react to the physical arrow keys. Basically a row should be focused or clicked in any other way than touching the screen.
Try to set focus to another view from your screen.
It's not 100% clear, but I suppose that you want your ListView to not react to clicks on rows. You're better off with returning false for .areAllItemsEnabled() on your adapter, and false for every row for .isEnabled(). This way you can switch off unneeded interactions on rows in your list.
It's not 100% right but since my view only had a ListView the following code did what I wanted :
menuListView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
return true;
}
return false;
}
});