20

I cannot figure how to implement onKeyPreIme(int keyCode, KeyEvent event) in a Fragment.

@Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { // do your stuff return false; } return super.dispatchKeyEvent(event); } 

I tried a lot but nothing works. Also, I could not find anything on Google or Stack Overflow. I would like to perform an action when the back key is pressed and the softkeyboard is up. Setting an onKeyListener on my EditTexts did not work, since KeyEvent.KEYCODE_BACK is not called when the soft keyboard is up. I appreciate any help and source code.

1
  • Thanks for your code, it was helpful to understand that returning super.dispatchKeyEvent(event); the activity's back button will work! Commented Oct 28, 2014 at 14:01

4 Answers 4

23

I was able to implement onKeyPreIme by sub-classing my EditText views that were related to the keyboard input. The goal is to make a custom lock screen that the user must enter a pass code or leave the application. When the user taps the "keyboard down" button the keyboard does not disappear.

Make sure to create a separate .java file for the subclassed EditText. Additionally, be sure to use the constructor in the code below (must pass AttrubuteSet).

I realize that my implementation of onKeyPreIme may not match yours, however it does demonstrate how to intercept the keyboard events before the InputMethodManager does it's thing.

I hope this helps.

Screenshot UserLockActivity enter image description here

EditText Subclass

public class LockEditText extends EditText { /* Must use this constructor in order for the layout files to instantiate the class properly */ public LockEditText(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override public boolean onKeyPreIme (int keyCode, KeyEvent event) { // Return true if I handle the event: // In my case i want the keyboard to not be dismissible so i simply return true // Other people might want to handle the event differently System.out.println("onKeyPreIme " +event); return true; } } 

UserLockActivity.java

public class UserLockActivity extends Activity { private LockEditText editText1; private LockEditText editText2; private LockEditText editText3; private LockEditText editText4; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_lock); editText1 = (LockEditText) findViewById(R.id.lock_text_1); editText2 = (LockEditText) findViewById(R.id.lock_text_2); editText3 = (LockEditText) findViewById(R.id.lock_text_3); editText4 = (LockEditText) findViewById(R.id.lock_text_4); setupTextChangedListener(editText1); setupTextChangedListener(editText2); setupTextChangedListener(editText3); setupTextChangedListener(editText4); // A method to bring out the keyboard when the view appears setFocusOnEditText(editText1); } public void setFocusOnEditText(LockEditText editText) { editText.clearFocus(); editText.requestFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0); } public void setupTextChangedListener(LockEditText editText) { editText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable arg0) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence arg0, int arg1,int arg2, int arg3) { // TODO Auto-generated method stub } }); } } 

activity_user_lock.xml Layout file

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".UserLockActivity" > <TextView android:id="@+id/main_lock_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentTop="true" android:paddingTop="60dp" android:paddingBottom="20dp" android:text="@string/enter_passcode" android:textAppearance="?android:attr/textAppearanceLarge" /> <LinearLayout android:id="@+id/lock_input_layout" android:layout_width="match_parent" android:layout_height="60dp" android:layout_below="@+id/main_lock_text" android:orientation="horizontal" > <com.yourpackage.yourappname.LockEditText android:id="@+id/lock_text_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_weight="1" android:ems="10" android:inputType="numberPassword" android:textSize="30sp" android:gravity="center_horizontal" android:textStyle="bold" > </com.yourpackage.yourappname.LockEditText> <com.yourpackage.yourappname.LockEditText android:id="@+id/lock_text_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_weight="1" android:ems="10" android:inputType="numberPassword" android:textSize="30sp" android:gravity="center_horizontal" android:textStyle="bold" > </com.yourpackage.yourappname.LockEditText> <com.yourpackage.yourappname.LockEditText android:id="@+id/lock_text_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_weight="1" android:ems="10" android:inputType="numberPassword" android:textSize="30sp" android:gravity="center_horizontal" android:textStyle="bold"> </com.yourpackage.yourappname.LockEditText> <com.yourpackage.yourappname.LockEditText android:id="@+id/lock_text_4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_weight="1" android:ems="10" android:inputType="numberPassword" android:textSize="30sp" android:gravity="center_horizontal" android:textStyle="bold" > </com.yourpackage.yourappname.LockEditText> </LinearLayout> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/lock_input_layout" android:layout_centerHorizontal="true" android:text="text" /> </RelativeLayout> 
Sign up to request clarification or add additional context in comments.

7 Comments

It does not really match what I intended it for, but your idea is creative so I will accept your answer
@i2097i I have one question. Is there any method in android to remove focus from EditText programmatically?
I want to do this in fragment using the inflater for this "LockEditText". but I am getting a exception in this case. Can you please explain how to use this LockEditText as a subclass of Edittext and add it with a inflater for Fragment
This solution worked well, but it is for an activity. To add to a Fragment, you have to get the activity when instantiating the InputMethodManager. So for this line: InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); Add a getActivity. before the getSystemService. So it will look like this: InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
23

This is my solution and it works really well for me, but everyones needs are different.

First i subclassed EditText and hooked up a listener (Google should make this the default)

public class ListenerEditText extends EditText { private KeyImeChange keyImeChangeListener; public ListenerEditText(Context context, AttributeSet attrs) { super(context, attrs); } public void setKeyImeChangeListener(KeyImeChange listener){ keyImeChangeListener = listener; } public interface KeyImeChange { public void onKeyIme(int keyCode, KeyEvent event); } @Override public boolean onKeyPreIme (int keyCode, KeyEvent event){ if(keyImeChangeListener != null){ keyImeChangeListener.onKeyIme(keyCode, event); } return false; } } 

Then you can attach a listener from anywhere like so:

myListenerEditText.setKeyImeChangeListener(new KeyImeChange() { @Override public void onKeyIme(int keyCode, KeyEvent event) { // All keypresses with the keyboard open will come through here! // You could also bubble up the true/false if you wanted // to disable propagation. } }); 

4 Comments

This looks like the best answer, since it actually enables overriding of onKeyPreIme. I hate to ask, but I'm having problems getting it to work. I extended AutoCompleteTextView and added a return statement in onKeyIme(...) within my activity (your second code block). Other than that, I've copied your code exactly, and set breakpoints on the "return" statement and each of the methods in the new class. setKeyImeChangeListener is called, and initializes keyImeChangeListener, however, the onKeyIme() never gets called when a key is pressed. Any ideas where to start troubleshooting?
Ok, I think I get it. These keyboard events are for physical keyboards, not the soft keyboard. Can anyone confirm? Thanks.
By the way, I'm still a student of all things Android, so thanks for this bit of code. I was able to use it to override the onFilterComplete method. Seems kinda silly that Android doesn't provide a listener for these events.
I'm not seeing my onKeyIme method called either. Does this work for soft keyboards?
1

I was not able to figure out how to implement the onKeyPreIME, but I was able to perform an action after the keyboard disappeared with the following code:

You man need to change comparison heightDiff > 200. This comparison worked for me because I had a scrollview.

fragmentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if(getView() != null){ int heightDiff = getView().getRootView().getHeight() - getView().getHeight(); if (heightDiff < 200) { rlupdate.setVisibility(RelativeLayout.VISIBLE); } else { rlupdate.setVisibility(RelativeLayout.GONE); } } } }); 

Comments

1

this is a more full code of answer by Deminetix.

i have used the answer by Deminetix to filter handheld barcode reader on android and have the result.

to make it usable on a screen only with buttons i have added a EditText with android:textColor="#FF000000" android:background="#00FFFFFF" android:enabled="false" disabled EditText still gets keyboard events.

optionally i could hide the software keyboard using the following but after disabling the EditText it was not required.

//InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); //imm.showSoftInput(textPatientId, InputMethodManager.HIDE_IMPLICIT_ONLY); 

MainActivity.java:

package com.doodkin.keyboardtest; import com.doodkin.keyboardtest.ListenerEditText.KeyImeChange; import android.os.Bundle; import android.app.Activity; import android.text.Editable; import android.text.TextWatcher; import android.text.method.KeyListener; import android.util.Log; import android.view.InputDevice; import android.view.KeyEvent; import android.view.Menu; import android.view.View; import android.view.View.OnKeyListener; import android.widget.EditText; public class MainActivity extends Activity { private static final String TAG = "keyboard test"; //private EditText editText1; ListenerEditText editText1=null; public String barcodebuffer=""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText1 = (ListenerEditText) findViewById(R.id.editText1); editText1.setKeyImeChangeListener(new KeyImeChange() { @Override public boolean onKeyIme(int keyCode, KeyEvent event) { String deviceName=event.getDevice().getName(); int keyboardType=event.getDevice().getKeyboardType(); int indexof=deviceName.indexOf("USB"); if(indexof!=-1 && keyboardType==InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC) { if(event.getKeyCode()==KeyEvent.KEYCODE_ENTER) { if(barcodebuffer!="") { Log.d(TAG, "filterBarcodeKeys Chars Flush: " + barcodebuffer ); barcodebuffer=""; } } else { barcodebuffer+=Character.toString((char)event.getUnicodeChar()); //Log.d(TAG, "filterBarcodeKeys Char: " + Character.toString((char)event.getUnicodeChar()) ); } return true; } return false; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } 

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <com.doodkin.keyboardtest.ListenerEditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_below="@+id/textView1" android:ems="10" > <requestFocus /> </com.doodkin.keyboardtest.ListenerEditText> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/editText1" android:layout_below="@+id/editText1" android:layout_marginTop="69dp" android:text="Button" /> </RelativeLayout> 

ListenerEditText.java:

package com.doodkin.keyboardtest; import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.widget.EditText; /* * example: myListenerEditText.setKeyImeChangeListener(new KeyImeChange() { @Override public boolean onKeyIme(int keyCode, KeyEvent event) { // All keypresses with the keyboard open will come through here! // You could also bubble up the true/false if you wanted // to disable propagation. } }); */ public class ListenerEditText extends EditText { private KeyImeChange keyImeChangeListener; public ListenerEditText(Context context, AttributeSet attrs) { super(context, attrs); } public void setKeyImeChangeListener(KeyImeChange listener){ keyImeChangeListener = listener; } public interface KeyImeChange { public boolean onKeyIme(int keyCode, KeyEvent event); } @Override public boolean onKeyPreIme (int keyCode, KeyEvent event){ if(keyImeChangeListener != null){ return keyImeChangeListener.onKeyIme(keyCode, event); } return false; } } 

2 Comments

I cant find the setKeyImeChangeListener method.
it is of - public class ListenerEditText extends EditText. it is my class I have developed you can see it above. frankly, it was a long time ago not sure how can I help you. I don't remember this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.