android: problems with programmatic invoking of soft keyboard - android

In my application I want to display a list of stuff and provide the user with the ability to filter the list by using the soft keyboard. To that end I added a button that should trigger (hide/show) the soft keyboard for filtering. I don't want to have a visible edit text control, cause it would take up unnecessary space. Rather than that, I would like to display a toast showing the filter query as the user types, much as the 'android:textFilterEnabled' attribute for ListView does. To my understanding there is no obvious way of doing this with available Android components. So I tried the following approach:
1) creating a layout containing invisible edit text and the list view:
<ListView android:id="#+id/main_list"
android:drawSelectorOnTop="false"
android:layout_height="0px"
android:layout_width="fill_parent"
android:layout_weight="5"
/>
2) adding button as a popup and invoking InputMethodManager on click to toggle the soft input (called in onCreate):
private void initButton() {
Button buttonView = (Button) getLayoutInflater().inflate(R.layout.keyboard_button, null);
buttonView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final View target = findViewById(R.id.filterbox);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// this does not work...
// imm.toggleSoftInputFromWindow(target.getWindowToken(), InputMethodManager.SHOW_FORCED, 0);
// ... so need to track this in an instance variable - which sucks
if (imeShowing) {
imm.hideSoftInputFromWindow(target.getWindowToken(), 0);
imeShowing = false;
} else {
// check that the filterbox got focus
Preconditions.checkState(target.requestFocusFromTouch());
Preconditions.checkState(target.hasWindowFocus());
Preconditions.checkState(target.hasFocus());
imm.showSoftInput(target, 0);
imeShowing = true;
}
}
});
buttonPopup = new PopupWindow(buttonView);
// ... code to display the button as a small popup
}
As mentioned in the code sample, the 'obvious' approach (calling toggleSoftInput) does not work, so I had to revert to this ugly if-else. This is however, a secondary problem. The primary problem is that when I run this in the emulator, the soft keyboard is displayed correctly, but as soon as I start typing in it, the systems starts an intent to the google search activity! And the typed characters appear in the Google search box displayed as a result. What is even more weird, this only happens the first time I type after deploying and running the app. I.e. if I go back to my app from the Google search box, everything works as expected (no redirects to the search box). Before showing the display I make sure that the invisible edittext gets focus, so it should be the target of the soft keyboard, right??
Does anyone have any idea what is happening here?

Sorry this is me (the author of this question), I can't access my old account due to SO new 'awesome' OpenID login:/
So I figured out that what I really need to do is just turn on the 'android:textFilterEnabled' attribute of the list, and focus on it on the button click. ListView supports input from soft keyboard (although I figured it out by looking at the actual code of AbsListView rather than getting hints in any documentation:). Also, I managed to get PopupWindow working for the button (instead of Dialog that I tried previously) so the focus problem is gone. The working code for this (in case anyone has similar problem) below:
View popupView = getLayoutInflater().inflate(R.layout.keyboard_button, null);
Button buttonView = (Button) popupView.findViewById(R.id.keyboardButton);
buttonView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
final View list = findViewById(R.id.the_list);
list.requestFocus();
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
});
buttonPopup = new PopupWindow(this);
The list will handle input from soft keyboard just as it does from hard one. The trick is just to trigger the keyboard and focus on the list. Also you may control how the filtering is applied to the list by setting a custom QueryFilterProvider on its associated adapter.

Related

How do I clear the focus on an editext? Other StackOverflow posts haven't helped much

I've looked at other StackOverflow posts, but many of them don't work, or the comments say that they don't work. I'm wondering how I can clear the focus on an edittext. I was hoping that when I close the keyboard, it would also lose focus, but this didn't happen.
Because of this, whenever someone exits the app and goes back in (with the app running in the background) the regular keyboard shows up, even though it's not supposed to. I have a whole system in place for managing the keyboard.
Code for showing/closing keyboard
private void closeEmojiKeyboard()
{
ivEmoji.setVisibility(View.VISIBLE);
ivKeyboard.setVisibility(View.GONE);
showKeyboard(etMessage);
llEmojiKeyboard.setVisibility(View.GONE);
}
private void showKeyboard(EditText view)
{
view.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
Code for hiding keyboard when someone opens the emoji keyboard
ivEmoji.setVisibility(View.GONE);
ivKeyboard.setVisibility(View.VISIBLE);
hideKeyboard(etMessage);
llEmojiKeyboard.setVisibility(View.VISIBLE);
And the code that hides the emoji keyboard when clicking the editext
llEmojiKeyboard.setVisibility(View.GONE);
showKeyboard(etMessage);
ivEmoji.setVisibility(View.VISIBLE);
ivKeyboard.setVisibility(View.GONE);
rvMessages.scrollToPosition(messagesList.size()-1);
Can anybody share some code with me that could help clear focus on my edittext? Thanks.
you can
ex 1.
editText.clearFocus()
ex 2.
EditText et = (EditText)view.findViewById(R.id.my_name);
et.setInputType(EditorInfo.TYPE_NULL); // setCursorVisible(false);

How to add a static keyboard in Android?

I want to add a keyboard to an activity in my app. I don't want the default Android keyboard, that pops up once the user clicks a text field and hides when the user clicks somewhere else. I want to make the keyboard static (it is accessible at any time and doesn't disappear) and identical on any device.
Essentially I would like the keyboard to function similarly as in this crossword puzzle app (Image) that I found.
The first solution that came to my head was to make the keyboard entirely by myself. Basically to add and hardcode every single button manually.
Is there a way to do this easier? Is there an available template?
(I am a total beginner in Android, so I might have missed even the most obvious solution)
Thanks.
EDIT: What I would like to achieve is not only that the keyboard stays open all the time, but also that I can easily control the size and position of the keyboard. I want it to cover a specific area of the screen.
You're going to need to make your own keyboard layout, but unless it needs to be a fully-featured keyboard, it won't be too difficult. Put it in its own layout XML, with corresponding IDs for each key.
You can then use <include> in the layouts where it needs to be included. In Java (or Kotlin), you can then make a "helper" class, which takes the root View of the current Activity/Fragment, finds the keys and sets up a listener framework for when a key is pressed.
As for keeping the device's keyboard hidden, check out the answers here.
Put these methods inside your activity . For opening the keyboard
public void openKeyboard() {
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}
For closing the keyboard :
public void closeKeyboard(Activity activity) {
if (activity != null) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null && activity.getCurrentFocus() != null) {
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
}
}

Soft Input Opens over a custom keyboard on Text Selection -- how to prevent

Many questions refer to a keyboard service rearing it's head at the wrong time, or how to substitute a view specific keyboard. I have no problem doing this. This problem is different in that the keyboard service pops up on top of a custom keyboard that was working fine until a long press to make a selection. At that point the default keyboard appears. I want to stop this.
As further clarification, it is not the long press that opens the system keyboard. It is action of making a selection. For example: A long press at the end of input does not select anything, but does pop up the "cut copy select all share..." dialog. When you click on "Select All" then the system keyboard opens.
I think the misleading suggestion of a link to a solution to this problem should be removed.
I use the following to install a special keyboard under an EditText:
MA_expression.setOnClickListener { view ->
mKeyboardView.visibility = View.VISIBLE
mKeyboardView.isEnabled = true
if (view != null) {
val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
This works as expected:
Now the goal is to use "45" as the argument to a function, so the range of text that is to become the argument is selected (simple here, but it could just as well be embedded in a more complicated expression):
Now the problem is evident -- the standard keyboard service has popped up. It can be dismissed with the done button, the selection remains, my keyboard remains, the FUNa keyboard is selected and the function to apply is picked.
The result is correct, it is only the intervening system keyboard that must be told it is not wanted.
How is that done?
dismiss the android key board on the focus listener
view.setOnFocusChangeListener
view.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
});

How does Facebook app handle layout changes when keyboard appears?

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);
}
});

Disable soft-keyboard from EditText but still allow copy/paste?

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

Categories

Resources