I am using Unity in my Android project. There are input fields in my app. As soon as I click on the field the keyboard pops up. I want the keyboard to only show up when there is a double-tap on the field. But I am not able to get it to work and I have tried several ways.
Requirement 1: Single tap shouldn't open keyboard
Requirement 2: Double tap should open keyboard
I tried OnPointerClick method of IPointerClickHandler but this doesn't seem to work. I used this code in one of the scripts attached to input field with IPointerClickHandler.
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.clickCount == 2)
{
Debug.Log("UNITY - Double click");
}
else if (eventData.clickCount == 1)
{
Debug.Log("UNITY - Single click");
}
}
Then there is also the question of how to hide the keyboard or prevent it from opening on single tap. This also I am not able to solve. I started with clicking the Hide Soft Keyboard in control setting of InputField in Unity editor. But surprisingly this starts opening a keyboard which has mobile input.
Can someone help? I have been stuck on this for some time I can't seem to be getting anywhere.
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
I have a EditText component, and, of course, if you click on it, the Android keypad is shown, allowing the user to input text. As far as I know, all Android software keyboards have (at least) a letter mode (ABC) and a symbols mode (?123). Their default view is the letter mode.
Now when the keypad is shown when the EditText component is clicked, I want the symbols mode to be shown by default. The user will still be able to switch to the letter mode.
Is there a way to achieve that? If yes, how?
I'm posting this because I don't think any of the answers actually address the question. The screenshot in the question does not correspond to a particular InputType's default state. So, switching InputTypes will not give you the layout from the screenshot.
(based on my research...)
Support for symbol input is not governed by any contract. One can very well leave symbols out when creating their own InputMethod. OR, they can add pagination support to provide access to 100s of symbols. Can this be bound by a contract? May be. But, it isn't at present.
Input method framework does not allow direct communication between the client and the IME. All communication happens either through the InputMethodManager or through InputConnection — a one-way channel. Switching to symbols using ?123 is, however, an internal event — not a defined state/action. Client applications cannot switch to it. There's no public (or hidden) API to make this happen.
InputType indicates something entirely different to an IME. Not sure why everyone is recommending its use. You may of course find that a particular InputType provides most of the required keys. But that isn't the same as show[ing] Android keyboard with symbols mode by default.
Possible workaround:
We'll create a custom EditText. We don't have to. It'll just keep everything in one place, and save us from copy-paste nightmare.
public class CusEditText extends EditText {
private final int mDefinedActionId;
public CusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// Corresponds to 'android:imeActionId' value
mDefinedActionId = getResources().getInteger(R.integer.definedActionId);
setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Log.i("CusEditText", "onEditorAction, actionId = " + actionId);
// Only bother if (...)
if (actionId == mDefinedActionId) {
// Check if current InputType is NUMBER
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
// Toggle
setImeActionLabel("NUM", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_TEXT);
} else {
// Current InputType is TEXT // Toggle
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
// We've handled this
return true;
}
// Let someone else worry about this
return false;
}
});
}
}
Next, we need to define definedActionId. Open or create res/values/integers.xml and add:
<integer name="definedActionId">-100</integer>
-100 is an arbitrary value. I checked EditorInfo and the actionIds (IME_ACTION_XXXX) were >= 0. -100 seems like a good candidate.
In xml, your layout will look like:
<com.your.packagename.CusEditText
android:layout_width="blah"
android:layout_height="blah"
android:inputType="number"
android:imeActionId="#integer/definedActionId"
android:imeActionLabel="ABC"/>
<!-- Probably use #string resource in place of ABC -->
There's not much to explain. IME will launch in NUMBER mode. Instead of a checkmark icon, it'll display ABC. On click, we intercept the actionId and toggle between NUMBER and TEXT input. We're using setInputType(...) because it not only updates the InputType, it also restarts the IME with changes. setRawInputType(...) only updates the InputType.
Issues:
As you can tell, this isn't really a solution. If the user closes the keyboard(using the back button) in TEXT mode, the keyboard will remain in the TEXT mode when they open it again. To go to the NUMBER mode, user will have to click NUM. Also, in TEXT mode, user will see NUM as the action, along with ?123 option. This doesn't break anything, but does take away from the UX.
We can't do anything about ?123 showing in TEXT mode for reasons listed above. But, we can try to make sure that the keyboard always opens in the NUMBER mode. I'll provide a rough sketch of how we'll do that. Its not straight-forward since we (developers) are not privy to events such as keyboard closing or opening. Updated CusEditText:
public class CusEditText extends EditText {
private final int mDefinedActionId;
private long mLastEditorActionTime = 0L;
public CusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// Corresponds to 'android:imeActionId' value
mDefinedActionId = getResources().getInteger(R.integer.definedActionId);
setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Log.i("CusEditText", "onEditorAction, actionId = " + actionId);
// Only bother if (...)
if (actionId == mDefinedActionId) {
// setInputType(...) will restart the IME
// and call finishComposingText()
// see below
mLastEditorActionTime = SystemClock.elapsedRealtime();
// Check if current InputType is NUMBER
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
// Toggle
setImeActionLabel("NUM", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_TEXT);
} else {
// Current InputType is TEXT // Toggle
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
// We've handled this
return true;
}
// Let someone else worry about this
return false;
}
});
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
return new CusInputConnectionWrapper(inputConnection, false);
}
private class CusInputConnectionWrapper extends InputConnectionWrapper {
private CusInputConnectionWrapper(InputConnection target, boolean mutable) {
super(target, mutable);
}
#Override
public boolean finishComposingText() {
Log.i("CICW", "finishComposingText");
// Ignore finishComposingText for 1 second (1000L)
if (SystemClock.elapsedRealtime() - mLastEditorActionTime > 1000L) {
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) == 0) {
// InputConnection is no longer valid.
// Switch back to NUMBER iff required
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
return super.finishComposingText();
}
}
}
Again, code is self-explanatory. We create a InputConnectionWrapper and listen for the finishComposingText() callback. If we're manually switching between TEXT and NUMBER, we use a flag since finishComposingText() will automatically be called. Else, we check if input type is set to TEXT and change it to NUMBER. I am not sure if finishComposingText() is the right method for interpreting keyboard closing/opening. Testing on API 21, vanilla android, this seems to work. More tests will be required.
I really hope someone can come up with a better, more robust solution than this - or modify my workaround so that it doesn't look like one.
Summary
Task at hand is to provide functionality of switching between NUMBER & TEXT input modes around existing Input Method Engines (IMEs). The first approach was to use imeActionLabel & imeActionId in the switching mechanism. This approach worked well with Google's keyboard (this is the imeActionLabel), but failed with Samsung's - imeActionLabel failed to show up in portrait (without extract). Possible workaround is to include the toggle button in the app's own UI.
Even with Google's keyboard, the letters (text) fail to show up when the mode switches back to NUMBER after inputting letters. This problem was fixed (at least on tested devices) by using flag flagNoExtractUi which prevents the IME from entering fullscreen mode in landscape orientation.
Final solution (pending implementation & testing)
The IME starts in the NUMBER input mode (95% use-cases involve number input)
A button is added to app's UI (next to the EditText) for switching between NUMBER & TEXT mode
User can switch from NUMBER to TEXT without any restrictions. Switching back from TEXT to NUMBER requires that no alphabets have been added.
InputType is preserved between keyboard closing & reopening. Example: If the user switches to TEXT mode and closes the keyboard, it will open in the TEXT mode. The InputType is not reset.
For more information about the approaches tried, refer to this discussion thread.
Screenshots
Default (NUMBER):
Switched to TEXT:
Recorded video link
I agree it is an InputType. If you want to show only numbers to your user then you would add the following to you xml document for your edit text:
android:inputType="number"
However if you set it as number then the user has to enter a number. But you can add additional types as well like numbers and email addresses such as:
android:inputType="number|textEmailAddress"
Check out http://developer.android.com/reference/android/text/InputType.html for more options. You can also check out what eclipse or android studio shows you under "inputType"
I believe you are looking to set the InputType of your edit text.
http://developer.android.com/reference/android/text/InputType.html
I'm not sure which you would use though you may have to play around a bit.
The only way to do this is by setting the inputType of your EditText.
If you want to set this property in the onCreate() (or inside a custom View's constructor) you can use the method setRawInputType():
mEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
Otherwise, if you need to set this property after the onCreate() (or after a custom View's constructor), you can use the method setInputType():
mEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
Obviously you can also specify the property at XML level:
android:inputType="number|numberDecimal"
You can play around with different flags to find the best composed filter.
Programmatically it is possible with little bit of tweak to the usual flow. First you have to set editText as:
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
Then you have to listen for keyevent. On pressing of pound set the InputType again to InputType.TYPE_CLASS_TEXT. This should work as it works for me.
editText.setOnKeyListener(new View.OnKeyListener()
{
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
Log.d("KeyBoard", "Keyboard Test Key Hit");
switch (keyCode) {
KeyEvent.KEYCODE_POUND:
if(editText.setInputType(InputType.TYPE_CLASS_TEXT);
{
editText.setInputType(InputType.TYPE_CLASS_TEXT);
return true;
}
Same thing I've answered i: EditText with number keypad by default, but allowing alphabetic characters
I am having issues with a PhoneGap application that I'm working in. My app has lots of forms, since the objective of the app is mostly to provide a nice user interface to a database. However, whenever the user tries to edit an input field that is close to the bottom, the Android keyboard will pop up and cover the field, so that the user cannot see what he/she is writing.
Do you know if there is a workaround for this? Has anyone come across this issue on their apps?
What you can do in this case (what I did when I had this problem...): add on-focus event on fields, and scroll up document. So you will see input field on the top of page :)
I agree with Paulius, for Android I found this to be the cleanest solution.
I know this is an old question but I will share my solution for other people if any body is still facing this issue.
// fix keyboard hiding focused input texts
// using native keyboard plugin and move.min.js
// https://github.com/vitohe/ionic-plugins-keyboard/tree/f94842fec1bacf72107083d2e44735e417e8439d
// http://visionmedia.github.io/move.js/
// not tested on iOS so implementation is for Android only
if ($cordovaDevice.getPlatform() === "Android") {
// device is running Android
// attach showkeyboard event listener
// which is triggered when the native keyboard is opened
window.addEventListener('native.showkeyboard', keyboardShowHandler);
// native.showkeyboard callback
// e contains keyboard height
function keyboardShowHandler(e) {
// get viewport height
var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
// get the maximum allowed height without the need to scroll the page up/down
var scrollLimit = viewportHeight - (document.activeElement.offsetHeight + document.activeElement.offsetTop);
// if the keyboard height is bigger than the maximum allowed height
if (e.keyboardHeight > scrollLimit) {
// calculate the Y distance
var scrollYDistance = document.activeElement.offsetHeight + (e.keyboardHeight - scrollLimit);
// animate using move.min.js (CSS3 animations)
move(document.body).to(0, -scrollYDistance).duration('.2s').ease('in-out').end();
}
}
window.addEventListener('native.hidekeyboard', keyboardHideHandler);
// native.hidekeyboard callback
function keyboardHideHandler() {
// remove focus from activeElement
// which is naturally an input since the nativekeyboard is hiding
document.activeElement.blur();
// animate using move.min.js (CSS3 animations)
move(document.body).to(0, 0).duration('.2s').ease('in-out').end();
}
}
The end result is unbelievably smooth.
Trying to make an Android InputMethod that is transparent - i.e. the underlying content shows through to the keyboard that I am developing.
I've been able to make the View that I pass to the system transparent - I think - but there seems to be something underneath my view that is solid white - and obfuscating the underlying content.
It is definitely possible, these guys do it:
https://play.google.com/store/apps/details?id=com.aitype.android.tablet.p&feature=search_result#?t=W251bGwsMSwxLDEsImNvbS5haXR5cGUuYW5kcm9pZC50YWJsZXQucCJd
I figured it out! Not sure if this is how the guys in your play store link did it, but this is what worked for me. Also, I realize this post is over a year old, but I'm still answering it just in case someone else out there discovers this when trying to create a transparent keyboard.
The "something" under your view is actually nothing - it's empty space. Your keyboard pushed the entire view up and out of the way to make room for its height, leaving empty white space behind. Your transparent keyboard let this white space show through.
Here's the solution: instead of returning your view in onCreateInputView, return it in onCreateCandidatesView. That's the view that normally lives above the keyboard and lists the autocorrect suggestions. But you're going to use this to house your actual keyboard.
The reason you want to have your keyboard be a candidates view is because the input view most often pushes the underlying view up. Individual apps can decide how they want to behave when a keyboard is shown via android:windowSoftInputMode and the input view respects their preference, but the candidates view always uses adjustPan.
From the docs: "Note that because the candidate view tends to be shown and hidden a lot, it does not impact the application UI in the same way as the soft input view: it will never cause application windows to resize, only cause them to be panned if needed for the user to see the current focus." http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html
So, return your transparent view from onCreateCandidatesView, return null from onCreateInputView and make sure to call setCandidatesViewShown(true) so your candidates view shows up (I call it in onWindowShown).
Normally InputMethodServices uses background color which is same with current binding application's background color. If you want to make this transparent, I think you should make it as popup-window structure, not an inputmethod window I think.
It may such easy to make the full screen keyboard layout extra area transparent via java reflection only if you're quite familiar with InputMethodService.
the extra area has an id name fullscreenArea, you can fetch the area's id, then findViewById() then set its background.
the keyboard look as this before I done my practice :
a giant blank cover the below page.
so after is :
you can see the below page which contained an EditText and others displayed.
here is my code :
public static void makeKeyboardTransparent(InputMethodService service) {
try {
View decorView = service.getWindow().getWindow().getDecorView();
final int viewId = fetchInternalRId("fullscreenArea");
View fullscreenArea = decorView.findViewById(viewId);
if (fullscreenArea != null) {
modifyView(fullscreenArea);
return;
}
} catch (Exception e) {
}
try {
Class<?> superClass = service.getClass().getSuperclass();
Field fullscreenAreaField = superClass.getDeclaredField("mFullscreenArea");
fullscreenAreaField.setAccessible(true);
View fullscreenArea = (View) fullscreenAreaField.get(service);
if (fullscreenArea != null) {
modifyView(fullscreenArea);
}
} catch (Exception e) {
}
}
private static void modifyView(View fullscreenArea) {
fullscreenArea.setBackgroundColor(Color.TRANSPARENT);
}
private static int fetchInternalRId(String name) throws Exception {
Class<?> rIdClass = Class.forName("com.android.internal.R$id");
return rIdClass.getDeclaredField(name).getInt(rIdClass);
}
I provided two approach to make the blank area transparent, both of them worked fine in my test, all you need is pass your InputMethodService into makeKeyboardTransparent() and see what it can do.