Is it possible to detect whether a keyboard is visible on the screen or not?
Thanks
I think this thread should answer your question. To summarize, you can give your activity's root view an id, such as "#+id/activityRoot", and then hook a GlobalLayoutListener into the ViewTreeObserver for that view. In the listener is where you check the visibility of the keyboard, like so:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // Check if keyboard is not hidden
// ... do something here
}
}
});
This is a combination of #Reuben_Scratton and #Yogesh's answers in the above thread.
UPDATE:
Note that the documentation for keyboardHidden says it will ALWAYS return Configuration.KEYBOARDHIDDEN_YES if there is a hard keyboard available on the device(i.e. like a Motorola Droid 1 & 2)
try this or this workaround since its not possible within "simple" sdk method invocation
You might try something along the lines of this:
InputMethodManager imm =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
boolean showingKeyboard = imm.isActive();
Hope this helps!
EDIT:
The other option is simply to force the keyboard open or closed, depending on what you want the user to see :) This would lead to more predictable use behavior and likely improve the user experience.
Related
I need something to verify the existence of the keyboard in the window of an android app ... The problem is I can not test the focus / blur the input, and need that check for keyboard ... I see the official documentation Appcelerator and this functionality is only for iOS ... does anyone have a solution?
KeyboardVisible property for iOS:
http://docs.appcelerator.com/platform/latest/#!/api/Titanium.App-property-keyboardVisible
As you can see in the official docs there is no native way to detect if the keyboard is visible; if you need to show the keyboard when the user open the window, add a listener to 'open' and 'resume' (this one is from the activity, not the window, and is triggered also when your app go from the background to the foreground) for a function that focus your field, if you need to know when the keyboard is open to change the layout, android already try to fit it for you (in this case, place everything inside of a scrollview).
On iOS you can listen to the keyboardframechanged event. For Android, you might be able to use one of these modules.
There is no any direct way to do this. but some trick may be work. try this.
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
... do something here
}
}
});
Facebook app is just amazingly handling UI changes at login screen. Check it out.
No keyboard
With keyboard (notice how need help? and English Change views disappear)
Yes, I do know about the adjustPan and adjustResize settings, but how does Facebook set exactly which views will be visible when keyboard is present?
Seems like they are showing/hiding specific text (such as need help or English in example above), when Soft keyboard becomes visible.
Now, in Android, there is No direct way to detect if soft keyboard is visible or not.
Why?
Below is the Answer from Android framework Engineer.
The IME being shown has little meaning, since exactly how the IME
behaves is up to it -- it may be a transparent overlay and not impact
the application, a small strip, or all other kinds of things.
Due to this, the main way you interact with the IME is by setting your
softInputMode to be resizeable so when the IME says it wants to
occlude part of the screen your app's UI will get resized to take that
into account if needed.
But, there are different ways/methods/workarounds by using which Apps (like Facebook) could potentially detect if Soft keyboard is visible or not and based on the outcome, app could show/hide texts/widgets in it's UI.
Method 1:
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
//soft keyboard is shown, so hide "need help" text, for example
} else {
//Software Keyboard was not shown;
}
Method 2:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 3) {
//Make changes for Keyboard not visible
} else {
//Make changes for keyboard visible
}
}
});
Now both Above mentioned methods does not necessarily works 100% in every situations (as one can expect from non-supported operation way out of SDK)
Facebook may be using any of the above method or who knows, they may have implemented it in different way!
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// view/hide whatever you want depending on the hasFocus value
// hasFocus == true -> keyboard shown
}
});
edittext.post(new Runnable() {
public void run() {
edittext.requestFocusFromTouch();
InputMethodManager lManager = (InputMethodManager) activity
.getSystemService(Context.INPUT_METHOD_SERVICE);
lManager.showSoftInput(edittext, 0);
}
});
Hi I'm making custom dialer so I create my own input pad.
The problem is how do I disable the EditText but still allow cut/copy/paste? The stock dialer can do this.
I have tried android:focusable="false" but it disables cut/copy (can still paste though).
I also tried to disable the inputType programatically which disables all three commands:
myEditText.setInputType(InputType.TYPE_NULL); //Can't cut/copy/paste
Disabling it from manifest also doesn't work:
android:configChanges="orientation|keyboardHidden" //Keyboard still popped up
Any solution? Thanks
After hours and hours of research, I finally found a solution that works for all API versions. Hope this saves someone's time.
If you are developing for API >= 11, the solution is simple, either:
1) Add the two properties below in the xml file of EditText
android:inputType="none"
android:textIsSelectable="true"
or
2) Programatically do the below
myEditText.setInputType(InputType.TYPE_NULL);
myEditText.setTextIsSelectable(true);
And you're done.
If you want to cater for API < 11 as well, I found that there is no way to disable to keyboard from popping out if you wanted to select the text for copy paste purpose. Setting focusable to false will disable the keyboard but it doesn't help because it disables your ability to select text too. Any other solutions I found in stackoverflow all either doesn't work or disables text selection at the same time too.
One ugly way to solve this is as such..
First, add this property in the xml file of EditText
android:editable="false"
Yes this is deprecated, but necessary for making the EditText not editable in API version < 11.
Next, we will need to hide the keyboard as soon as it shows up, so that we can continue selecting text without the keyboard blocking the way.
Use this code below to detect keyboard showing up (solution obtained from https://stackoverflow.com/a/9108219/1241783), and hide it immediately.
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
{
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
//Hide the keyboard instantly!
if (getCurrentFocus() != null)
{
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
}
});
}
It works for my case. Though you can see the keyboard showing up in a split second (which is the ugly part) but I can't think of any other way to get this to work at the time of writing. If you have a better solution, please leave a comment!
Let me know too if this saves someone's time :)
To disable the soft keyboard showing, keeping the copy/paste and cursor functionality, just add this line in your activity:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
Since the current top answer uses a deprecated method and didn't have the paste method for me, here's another way that doesn't use old methods. But, it does try to use a hidden method via reflection with a fallback. =)
I've subclassed EditText into a new widget called KeyboardlessEditText that still retains all the cool editing features without the keyboard showing. Just drop the file in and go.
The full code is a little long for this post, but as long as GitHub doesn't go down, then this will work: https://github.com/danialgoodwin/android-widget-keyboardless-edittext/blob/master/KeyboardlessEditText2.java
To disable system keyboard automatic pop up for EditText or TextView do the following:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
editTextView.setShowSoftInputOnFocus(false);
} else {
editTextView.setTextIsSelectable(true);
//N.B. Accepting the case when non editable text will be selectable
}
I had the same problem but later I also wanted allow typing after double tap.. after hours and hours of searching I found working solution (at least for me). Use this in your onCreate method:
editText.setCursorVisible(false);
editText.setTextIsSelectable(true);
editText.setShowSoftInputOnFocus(false);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); // This just hide keyboard when activity starts
These lines should definitely do the trick.. and if you want to revert that use this:
editText.setCursorVisible(true);
editText.setShowSoftInputOnFocus(true);
To show keyboard again use:
private void showSoftKeyboard(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
view.requestFocus();
inputMethodManager.showSoftInput(view, 0);
}
To allow copy/paste next time just use these three lines:
editText.setCursorVisible(false);
editText.setTextIsSelectable(true);
editText.setShowSoftInputOnFocus(false);
For further keyboard hide use:
private void hideSoftKeyboard() {
if(getCurrentFocus() != null) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
This code is working on API >= 21
try this
EditText et = ... // your EditText
et.setKeyListener(null) //makes the EditText non-editable so, it acts like a TextView.
No need to subclass. The main difference between this and making your EditText non-focusable, is that the EditText still has its own cursor - you can select text, etc. All it does is suppress the IME from popping up its own soft keyboard.
Had a similar need due to my custom inline "fake" input which was still visible as the os soft keypad was appearing after focus moved to an edit text.
Solution was to make the edit text hide soft input until the previous custom input widget had finished its edit lifecycle.
Used #Bruce's answer for inspiration, also saw a few related posts which I'll attach at end.
Solution I found worked was:
fun setInputType(inputType: Int) {
getEditText().setRawInputType(inputType)
if (inputType == InputType.TYPE_NULL) {
getEditText().setTextIsSelectable(true)
getEditText().isCursorVisible = true
}
}
had to use setRawInputType() instead as multiline text input was not respected when setting from InputType.TYPE_NULL back to InputType.TYPE_TEXT_FLAG_MULTI_LINE.
Seems there are users reporting issues relating to calling setInputType(InputType.TYPE_NULL). see:
https://issuetracker.google.com/issues/36907992
other useful related posts:
How to make EditText not editable through XML in Android?
EditText non editable
Is there any way to show software keyboard with USB keyboard connected (in my case RFID reader)?
I tried to force show it using InputManager (with these or similar parameters), but with no luck
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
Important notice - I know that there is a button in status/system bar to show it, but this button is not visible to user (Kiosk app).
You need to override the InputMethodService method onEvaluateInputViewShown() to evaluate to true even when there is a hard keyboard. See onEvaluateInputShown() and the Soft Input View section of InputMethodService. Try creating your own custom InputMethodService class to override this method.
EDIT: The source for onEvaluateInputShown() should help. The solution should be as simple as creating your own class that extends InputMethodService and overriding this one method, which is only a couple of lines long. Make sure to add your custom service to your manifest as well.
From Source:
"Override this to control when the soft input area should be shown to the user. The default implementation only shows the input view when there is no hard keyboard or the keyboard is hidden. If you change what this returns, you will need to call updateInputViewShown() yourself whenever the returned value may have changed to have it re-evalauted and applied."
public boolean onEvaluateInputViewShown() {
Configuration config = getResources().getConfiguration();
return config.keyboard == Configuration.KEYBOARD_NOKEYS
|| config.hardKeyboardHidden == Configuration.KEYBOARDHIDDEN_YES;
}
Here are the possible configurations you can check for. Configuration.KEYBOARD_NOKEYS corresponds to no hardware keyboard. This method returns true (soft keyboard should be shown) if there is no hardware keyboard or if the hardware keyboard is hidden. Removing both of these checks and simply returning true should make the software keyboard visible even if a hardware keyboard is attached.
Try (not tested):
public boolean onEvaluateInputViewShown() {
return true;
}
Since this return value will not change, you won't need to call updateInputViewShown() yourself. If you modify this method differently, be sure to remember this detail.
The soft keyboard can have unpredictable behaviour on different platforms. First in your code, ensure you have an editable input control. Eg, if you have an EditText, you could use:
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE))
.showSoftInput(myEditText, InputMethodManager.SHOW_FORCED);
However, you can just show and hide it whenever you want using:
//show keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
You could also add any of these events inside OnCreate or some other method of the controls.
If however for some reason any of the above fails, your best option might be to use an alternative keyboard, e.g. Compass Keyboard,
OR
You could even build yours:
See an example of a keyboard implementing the inputmethodservice.KeyboardView
You might also want to take a look at the GingerBread Keyboard source.
If your app has the WRITE_SECURE_SETTINGS permission (available to system apps or Android Things apps) it can set the show_ime_with_hard_keyboard system setting which will enable soft keyboard even if a hard keyboard is plugged:
Settings.Secure.putInt(getContentResolver(), "show_ime_with_hard_keyboard", 1);
This worked in my app, interestingly, also an kiosk app.
This is a bit stripped, I did some checks beforehand, whether IMM is null and such.
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInputFromWindow(someInputView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
according to this https://stackoverflow.com/a/24287780/2233069, I made working solution for Kiosk mode.
boolean hardwareKeyboardPlugged=false;
....
mEditText.setOnFocusChangeListener(this);//in onCreate()
....
#Override
public void onResume() {
//protect from barcode scanner overriding keys
hardwareKeyboardPlugged=(getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO);
super.onResume();
}
....
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
if (hardwareKeyboardPlugged){
//protect from barcode scanner overriding keys
hardwareKeyboardPlugged=false;
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).showInputMethodPicker();
Toast.makeText(this, "USB device detected. Turn OFF hardware keyboard to enable soft keyboard!", Toast.LENGTH_LONG).show();
}
}
after fixing another problem in my Android Application, i came to another thing.
It would be important that i can do something, like hide some visual elements, if the SoftKeyboard so a Input like Swipe or the normal Android Keyboard is shown.
I've tried the onConfigurationChange="KeyboardShow" (pseudocode) but had no change to get a event when for example skype got shown.
So now my question is, is there any solution or function or listener, with which i can handle such a action?
I hope someone can help me.
Sincerly,
Mike Penz
There might be better approaches, but a possibility is to add: android:configChanges="keyboardHidden" to the manifest. That will fire with any keyboard changes, so the you will need to query the Configuration object
static Configuration prevConf = Configuration();
static int ignoreMasks = Configuration.HARDKEYBOARDHIDDEN_NO|Configuration.HARDKEYBOARDHIDDEN_YES;
onCreate() {
prevConf = setToDefaults();
}
// all your code here
#Override
public void onConfigurationChanged (Configuration newConfig) {
int deltas = newConfig.diff (prevConf); // what changed?
prevConf = newConfig;
if (delta & ignoreMasks)
return; // you're not interested in hard keyboards.
// your code here
}
I suck at bitwise operators, so you might need to work around that.
This is the API documentation:
http://developer.android.com/reference/android/R.attr.html#configChanges
http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged%28android.content.res.Configuration%29
http://developer.android.com/reference/android/content/res/Configuration.html