What I'm looking to do is hide only the popups that show what key you are currently pressing while using a soft keyboard. Is this possible? I am creating my own new keyboard which will have no need for them.
From what I think I understand, the picture below is the actual popup keyboard that you can choose to show using android:popupKeyboard and android:popupCharacters in the Keyboard.Key XML.
But the image below is not the same (also see this picture). Is there a way to turn the following off, using XML or even programmatically?
After reading a little bit of the actual android keyboard source code:
What I was referring to was the "key preview", which is "a popup that shows a magnified version of the depressed key." By default the preview is enabled, but to disable it, simply enough, is setPreviewEnabled(boolean previewEnabled). Which is a method from the KeyboardView class. API.
public void onPress(int primaryCode) {
mInputView.setPreviewEnabled(false);
}
public void onRelease(int primaryCode) {
mInputView.setPreviewEnabled(true); //Change to false if you want remove too for the Del key when it's pressed
}
Additionally, To get the view and universally disable the preview from within a custom class extending InputMethodService
private KeyboardView mInputView;
#Override
public KeyboardView onCreateInputView() {
mInputView = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null);
mInputView .setPreviewEnabled(false);
return mInputView;
}
Related
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);
}
});
Is there a way I can change the suggestions the keyboard shows for autocompletion of a word? I want to maintain a separate dictionary in the app and when the user types in the EditText he should be shown suggestions from that dictionary.
For changing the suggestions, you will have to implement your own keyboard. This is not what you want to do I believe.
The simplest option for you is to use AutoCompleteTextView for showing user the suggestions. Looks something like the following:
After reading several posts, I understood it can not be done without implementing my own keyboard. So, I ended up implementing a layout for displaying suggestions over the keyboard.(i.e. at the bottom of the activity view). When the keyboard shows up it automatically comes over the keyboard.
First, I turned off the default suggestions in the EditText using
edittext.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Then for detecting if the keyboard is displaying or not:
myActivityView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = myActivityView.getRootView().getHeight() - myActivityView.getHeight();
if (heightDiff > 180) {
// if more than 180 then its a keyboard
showSuggestions();
}else{
//keyboard gone...
// hide suggestion layout
}
}
});
I added a 100ms delay so that the keyboard hides its default suggestion layout, in case it is displaying.
private void showSuggestions(){
myActivityView.postDelayed(new Runnable() {
#Override
public void run() {
mySuggestionLayout.setVisibility(View.VISIBLE);
}
}, 100);
}
There is a tutorial on the Android Development website, which explains this. See the link here: http://developer.android.com/guide/topics/search/adding-custom-suggestions.html
In a current fullscreen opengl based project I work on, I have some GL based graphical elements, notably a text entry field. For the use to enter text when this element has the focus, I display the soft keyboard (which appears fine).
On android version before 5.0, the Google Keyboard was working fine, sending key events like for hardware keyboards. On android Lollipop, some other keyboards like Swiftkey or the free Hacker's keyboard are still working, but the Google Keyboard isn't anymore.
When pressing a key on the Google Keyboard on Lollipop, no visual feedback appears on the keyboard itself and my application receives the touch events as if the keyboard was not shown (but it is). The 'hardware' back key works fine though.
The view used in the app is a SurfaceView (and it's not a TextView). I've overridden onCheckIsTextEditor and I return a specific InputConnection from onCreateInputConnection where I've set the inputType to be TYPE_NULL.
Note that onCreateInputConnection doesn't seem to be called.
This app is compiled with android level 15 compatibility.
Any idea what would prevent the keyboard to accept touch events?
What should I do to debug the touch events flow?
I finally found a workaround to my problem, even though I don't really understand exactly why it works. This solution is partially based on what Cocos2d-x does for input on Android.
I created an android EditText (actually a class than inherits EditText in which I overrode onKeyUp and onKeyDown, this is to track focus and the back key).
Instead of having the SurfaceView the sole element of the activity, I created a layout that has the fake edit text in the background (but not fullscreen), and the SurfaceView on top:
private FrameLayout setupView(View androidView)
{
ViewGroup.LayoutParams framelayout_params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
frameLayout = new FrameLayout(this);
getFrameLayout().setLayoutParams(framelayout_params);
ViewGroup.LayoutParams edittext_layout_params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
edittext = new FakeEditText(this);
edittext.setLayoutParams(edittext_layout_params);
// make sure this edit text is not fullscreen
edittext.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
// ...add to FrameLayout
frameLayout.addView(edittext);
frameLayout.addView(androidView);
return frameLayout;
}
I also added a TextWatcher linked to the fake edit text, this is mainly to capture the text entered by the user and send it back to the GL based edit text I have on the SurfaceView (in my case, when the afterTextChanged method is called, I transform the received characters to internal keydown/keyup events that are routed to my GL control).
When the virtual keyboard needs to be shown (for example when the GL text field has focus), I set the fake edit text content from the GL text field content, and attach this TextWatcher to the fake edit text, and attach the virtual keyboard to the android fake edit text.
// Control is the base class of my GL controls
private void uiShowVirtualKeyboard(Control control)
{
if (fakeEdit.requestFocus()) {
// textWrapper is our TextWatcher
fakeEdit.removeTextChangedListener(textWrapper);
fakeEdit.setText("");
// get the text from the GL Text entry
final String text = control.getTextContent();
// and make sure it's in the android EditText at start
fakeEdit.append(text);
// listen to user changes
fakeEdit.addTextChangedListener(textWrapper);
// show the virtual keyboard
InputMethodManager imm = (InputMethodManager) fAndroidActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(fakeEdit, InputMethodManager.SHOW_FORCED);
}
}
I had exactly the same problem. Google keyboard did no show up correctly and passed touch input through it's buttons.
As it turned out Google keyboard was not happy with the default settings of EditorInfo class passed into onCreateInputConnection for a view. If you fill in at least imeOptions field and leave the rest to their default values it will work, even if you return null from the function.
In order to fix it i've added these lines to my SurfaceView subclass:
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE | InputType.TYPE_CLASS_TEXT;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN;
return super.onCreateInputConnection(outAttrs);
}
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();
}
}
I'm trying to get Android to select all the text in an EditText field when it gets the focus. I'm using this attribute in the layout (on both fields):
android:selectAllOnFocus="true"
I'm not sure if this is relevant, but to get the cursor to the first editable field (there's also a disabled field before it), I'm using the following commands:
quizStartNum.setFocusable(true);
quizStartNum.requestFocus();
But, while the cursor does move to the desired field when the layout is first displayed, the text doesn't get highlighted; instead the cursor ends up to the left of the text, the default behavior. If I move to the second field by touching it, all the text is selected as desired. Then, if I move back to the first field, again by touching it, the text is also completely selected. I would like to have the behavior right from the start. Is there a way to do this?
If android:selectAllOnFocus="true" does not work, try calling setSelectAllOnFocus(true) on that particular EditText.
If that doesn't work either, this is another workaround from a previous SO post.
EditText dummy = ...
dummy.setOnFocusChangedListener(new OnFocusChangedListener(){
public void onFocusChange(View v, boolean hasFocus){
if (hasFocus) && (isDummyText())
((EditText)v).selectAll();
}
});
I had a similar issue and android:selectAllOnFocus="true" did not work for me.
The reason was that i was programatically requesting focus to the EditText before it was displayed. So if you are doing this for a EditText in an AlertDialog make sure you show it before you request focus to the EditText.
EditText should be focussed after it displayed.
Following workout worked for me,
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Set Input Methode
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
#Override
public void onStart() {
super.onStart();
new Handler().post(new Runnable() {
#Override
public void run() {
Dialog dialog = getDialog();
if (dialog != null) {
// Set Layout
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// Set Cancelable False
setCancelable(false);
// Set Focus Here <------------------------
uiET_myTextView.requestFocus();
}
}
});
}
Try removing your focus commands. They aren't necessary, Android should focus on the first field automatically?
I also noticed that with android:selectAllOnFocus="true" seemed not to work, I used the mouse to select EditText in the emulator, but if I used my finger and touched it, as if on the phone, it worked. If you don't have a touch screen on your computer you may have to install your app on a physical device to test it.
Android Studio may not recognize the mouse in this case
I'll refer to this older post.
If you just want your EditText to show a hint (for "what goes in here"), you might want to use the Android's XML-attribute hint (link).