I am very new to developping Android application and I am facing a
difficulty.
What I want to do is to use a specific keyboard when I click on an
EditText. So far, I have found the Keyboard and KeyboardView
classes but I haven't succeeded to do what I want yet.
Here is the description of where I am :
I have described my keyboard in a XML file,
I create a "KeyboardView" object,
I initialize it with clavier=new KeyboardView(activité,
(AttributeSet)findViewById(R.xml.clavier_numerique));
but I don't know how to replace the standard keyboard with this
customized keyboard.
Am I doing something wrong? What else should I do?
Thanks in advance for the time you will spend trying to help me.
You should use something like this:
//retrieve the keyboard view from xml
kbdV= (KeyboardView) findViewById(R.id.kbd);
//set the keyboard layout to the layout you defined in res/xml/keyboard_layout.xml
kbdV.setKeyboard(new Keyboard(this,R.xml.keyboard_layout)); //defines the keyboard layout
//add a keyboard action listener
kbdV.setOnKeyboardActionListener(new KeyboardView.OnKeyboardActionListener(){
public void onKey(int primaryCode, int[] keyCodes) {
handlePress(primaryCode, keyCodes); // callback to handle keypresses
}
public void onPress(int primaryCode) {}
public void onRelease(int primaryCode) {}
public void onText(CharSequence text) {}
public void swipeDown() {}
public void swipeLeft() {}
public void swipeRight() {}
public void swipeUp() {}
});
with a layout xml file similar to this :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- your widgets here -->
<KeyboardView android:id="#+id/kbd" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
</LinearLayout>
At first you should decide what you want from keyboard:
if you just want to change to numbers you can do that by the first answer from Macarse
if you want a complete customized keyboard you should use Keyboard and KeyboardView classes by a second project
You need to specify an inputType in the xml:
<EditText android:inputType="textUri"/>
or from the code doing:
EditText input;
input.setInputType(InputType.TYPE_CLASS_NUMBER);
You can read the available inputTypes here.
When you initialize it with clavier=new KeyboardView(activity,
(AttributeSet)findViewById(R.xml.clavier_numerique),EditText edit);
You can transfer the EditText object in. And hide the standard keyboard,show the customized KeyboardView like this.
public void showKeyboard() {
if (edit != null) {
InputMethodManager imm = (InputMethodManager)mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
}
keyboardView.setVisibility(View.VISIBLE);
keyboardView.setEnabled(true);
}
Related
I have an EditText, since I use a custom keyboard in my App, I have disabled the standard android keyboard.
Unfortunately now seems that I cannot use the copy paste, selection etc when I click on the EditText in Jelly Bean, in Gingerbread my edit text has the desired behavior.
I need simply to disable the android keyboard to use my custom keyboard but the others copy-paste actions, selection etc, must be active
How could I fix this?
My EditText is this:
<EditText
android:id="#+id/input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:autoText="false"
android:background="#color/light_sky"
android:cursorVisible="true"
android:editable="true"
android:gravity="left"
android:imeOptions="flagNoEnterAction|flagNoExtractUi"
android:scrollbars="none"
android:singleLine="true"
android:textSize="32dip" />
You proably have set a null input in your EditText.
If other situations you can prevent the keyboard showing simply using in the manifest
android:configChanges="orientation|keyboardHidden"
In this way the Android keyboard will not auto-open but is shown only if you click directly the EditText
Building on this topic https://stackoverflow.com/a/10636686/2558337 i suppose that you should #Override onClickListener
inputField.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
});
You could even try this that works
declare a InputMethodManager variable private InputMethodManager imm;
And in your onActivityCreated() method add these lines
// to hide the keypad
imm = (InputMethodManager) getActivity().getBaseContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(inputSearch.getWindowToken(), 0);
And to unhide use the following code
editText = (EditText) getView().findViewById(R.id.editText);
editText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
imm.showSoftInput(inputSearch, 0);
}
});
I want to immediately highlight give focus to a particular edit box when the activity loads and bring up the softkeyboard. how can I do this? Also should there be anything in onStart()?
You can call : requestFocus() on the View after you do findViewByID()
You can do that in onStart - I see now reason for it not to work.
Check here too :
http://developer.android.com/reference/android/view/View.html
In your layout put </requestFocus> tag inside EditText.
In onStart() call
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Ideally this should work.
<EditText
android:id="#+id/Abc"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<requestFocus />
</EditText>
But there have been some known issues of the keyboard not popping up. See this.
You can also do this using Runnable:
public class MyActivity extends Activity {
private Handler mHandler= new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get text
mHandler.post(new Runnable() {
public void run() {
text.requestFocus();
}
});
}
}
Using the getSystemService(...), one can obtain, in this case, the Context.INPUT_METHOD_SERVICE, have a look at this code sample below for illustration:
InputMethodManager imm = (InputMethodManager)context.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edittext, 0, null);
so I tried android:selectAllOnFocus and of course I'm using android:hint.
The app loads, requestFocus triggers and the full text is selected.
The problem is that when I click in the EditText the selection is lost.
I've already read:
Select all text inside EditText when it gets focus
For some reason, it worked (on Jelly Bean) only if I posted it with a Handler:
new Handler().post(new Runnable() {
#Override
public void run() {
paidView.selectAll();
}
});
Set the selection in an View.OnClickListener like so:
editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText.setSelection(0, editText.getText().length() - 1);
}
}
Set the selection in an View.OnClickListener like so: (with the 0 and text length opposite to the previously approved response) - this will ensure that when the user starts typing the content will be overridden.
editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText.setSelection(editText.getText().length() - 1, 0);
}
}
I realize this is an old post, but I had this same problem. For me, the reasoning was that I like to move the keyboard out of the way (dismiss it) to get my bearings (or hit buttons to add or remove rows of data) and when i touched back on the EditText I was previously editing, it was annoying to have the keyboard pop back up and the text un-select, forcing me to either work to get the cursor to where I wanted to start deleting, or touch another EditText and then touch back on the original to re-select everything. I just want to have the keyboard pop back up and have the text selected and ready to overwrite whenever I go to that EditText.
There are easy solutions to this:
1) Long tap does this for you on most occasions.
2) If you're already using setSelectAllOnFocus(true), you can just throw a simple clearFocus() and requestFocus() in your onClick listener:
etMyEditText.setSelectAllOnFocus(true);
etMyEditText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.clearFocus();
view.requestFocus();
}
});
This way the EditText has everything selected when you tap on it, regardless of soft keyboard status.
Additional bonus:
Add android:windowSoftInputMode="adjustPan" inside your <activity .../> tag in your AndroidManifest.xml file to force the selected EditText to stay in sight when the soft keyboard pops up.
try This
editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText.selectAll();
//or this.selectAll();
}
To select all the text.
Do the code below after you did findViewById and you are good to go:
edtProductPrice.setSelectAllOnFocus(true);
edtProductPrice.requestFocus();
edtProductPrice.selectAll();
So I've got what seems to be a common problem, which is that the EditText in my dialog box doesn't show up when it gets focus. I've seen several workarounds, such as in this thread, this one and this one (and many more), but I have never seen a satisfactory explanation for why this is happening in the first place.
I would much prefer to have android use its own default behavior for EditTexts than to build my own, but it seems like everyone (in those threads) has accepted that the default behavior for EditTexts in Dialogs is to just give a cursor and no keyboard. Why would that be?
For the record, none of these workarounds seem to be working for me - the closest I've been able to come is forcing a keyboard to appear underneath the dialog box (using InputMethodManager.toggleSoftKeyboard(*)). My particular configuration is API15, the EditText shows up in a footer on a ListView within an AlertDialog. The EditText android:focusable="true" is set, and onFocusChangeListener is receiving focus events.
Edit:
As requested, here is the specific code snippet that I'm working with. I won't bother with the whole layout, but in this specific application, the EditText appears in response to pressing a button on the dialog (similar to an action view). It is contained in a RelativeLayout which by default has visibility "gone":
<RelativeLayout
android:id="#+id/relLay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:visibility="gone"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp">
<ImageButton
android:id="#+id/cancelBut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#color/transparent"
android:src="#drawable/cancelButton"
android:layout_margin="5dp"/>
<ImageButton
android:id="#+id/okBut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/cancelBut"
android:background="#color/transparent"
android:src="#drawable/okButton"
android:layout_margin="5dp" />
<EditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:focusable="true"
android:layout_toLeftOf="#id/okBut"/>
</RelativeLayout>
The code which builds this sets the visibility of the relativeLayout to "Visible" (and hides the other UI elements). This should be enough to pull up the keyboard when the EditText gets focused, based on my experience with EditText. However, for some reason this is not the case. I can set the following onFocusChangeListener:
edit_text.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// For whatever reason we need to request a soft keyboard.
InputMethodManager imm = (InputMethodManager)dlg.getWindow().getContext().getSystemService(_Context.INPUT_METHOD_SERVICE);
if(hasFocus)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
Log.v("DialogProblem", "Focus requested, " + (hasFocus?"has focus.":"doesn't have focus."));
}
}
});
Using this configuration, when I first enter the EditText, the onFocusChangedListener triggers, and generates a log that invariably looks like this:
Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.
The keyboard shows up and then disappears, probably because I toggle it twice, but even when I make sure it stays up, it's behind the dialog window (in a greyed out area), and there's no way to get to it without closing the dialog.
That said, I'd like to emphasize that even though I may be able to get this work-around to work, I'm primarily interested in finding a simple reason why the EditText isn't triggering in the first place, and why this seems to be so commonplace!
OK, so after reading a lot, I have figured out why this is a problem, and I do not need to use any workarounds.
The problem seems to be (at least in my case), that since the place where you enter text is hidden initially (or nested or something), AlertDialog is automatically setting the flag WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (or some combination of that and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) so that things don't trigger a soft input to show up.
The way that I've found to fix this is to add the following line after the dialog has been created:
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
Once this is done, the EditText acts like a normal EditText, no kludges or workarounds necessary.
I have the same problem in my own app. If you are developing for API level >= 8 you can use this snippet:
dialog.setOnShowListener(new OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
}
});
I haven't found a solution for lower API levels...
BTW: This snippet doesn't always work on emulator. I don't know why.
If you read the AlertDialog documentation you'll find there:
The AlertDialog class takes care of automatically setting *WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM* for you based on whether any views in the dialog return true from View.onCheckIsTextEditor(). Generally you want this set for a Dialog without text editors, so that it will be placed on top of the current input method UI. You can modify this behavior by forcing the flag to your desired mode after calling onCreate.
I had the problem you've mentioned with EditText in ListView inside a Dialog. I fixed it by overwriting the custom view class (in my case ListView) with my own FocusableListView, with just one method overwritten:
public class FocusableListView extends ListView {
public FocusableListView(Context context) {
super(context);
}
public FocusableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FocusableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean onCheckIsTextEditor() {
// this is where the magic happens
return true;
}
}
Then I'm using it in the layout file as:
<?xml version="1.0" encoding="UTF-8"?>
<com.myexample.wiget.FocusableListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
android:layout_height="wrap_content" />
You can overwrite the RelativeLayout in your case the same way and it should work.
This is what worked for me. Create the AlertDialog.Builder, set title, positiveButton, negativeButton. After do this:
AlertDialog dialog = builder.create();
dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
dialog.show();
editText.requestFocus();
You don't need to use builder.show();.
The code above is very helpfull. But you must call the "show" method after the "create" method (I don't know why, but only this works in my dialog with EditText in ListView).
In method onCreateDialog:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case YOUR_DIALOG_ID: {
//...
AlertDialog a = new AlertDialog.Builder(this)./*
... set the properties here
*/
.create();
a.show(); //!!! this is very important to call the "show" method
a.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
return a;
}
//...
}
return null;
}
Thank you! I have an embedded TextEdit in the last row of ListView embedded in the alert dialog fragment. I used your solution of clearing the flags as a post runnable and now it works perfectly.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("My Title");
m_adapter = new MyAdapter(getContext());
builder.setAdapter(m_adapter, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
final AlertDialog dialog = builder.create();
final ListView listView = dialog.getListView();
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
listView.post(new Runnable() {
#Override
public void run() {
dialog.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
});
return dialog;
}
Here's one way to do it:
final Window dialogWindow = dialog.getWindow();
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
I would like to add on to Paul's answer and Alexander's comment.
I myself have a dialog that's created in the onCreateDialog() method, which (seems to) require returning dialog.show();, wherefore you can not add the layoutparams to the dialog where the dialog is created. To work around this, just keep your onCreateDialog() method the same, and add an onResume() method as follows:
#Override
public void onResume() {
super.onResume();
Dialog dialog = getDialog();
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
This should do the trick, it works for me, thankfully. Have been on this case for quite some while.
full code for showing the keyboard in dialog:
public void onFocusChange(View v, boolean hasFocus) {
Log.v("onFocusChange", hasFocus + " " + showkeyboard);
if (hasFocus) {
if (showkeyboard++ == 0) {
alertDialog.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
alertDialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
} else {
showkeyboard = 1;
}
}
}
This worked for me ----
editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
//dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
editText.setFocusable(true);
}
});
just add below codeLine:
// to show keyboard automatically while editText is in dialog
dialog.getWindow().setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
I'm trying to have an EditText and the possibility to display a keyboard at the bottom of the screen when the user taps the EditText. I'm aware of the InputMethodService and the SoftKeyboard example, but I can't use it in that fashion as my keyboard should only be available to this very EditText.
Furthermore, there should be a context menu, but that's not part of this question (I think).
I've read plenty of code fragments, but in many cases they contain methods that aren't available anymore (i.e., getViewInflate()) or are written in a context that I don't understand or can't translate into my code (mind that I'm a newbie regarding Android).
In most attempts I fail with this exception when I tap the EditText:
java.lang.IllegalArgumentException: width and height must be > 0
followed by a stack-trace that doesn't contain any of my classes. As you can see in the code below all sizes are set.
What you see below is the current status of the code (I removed some of the code and I hope it still makes sense). I also tried to use what's inside of handler.post() in the main thread, use the commented stuff instead of the handler.post() ...
What's not below is an attempt to use a RelativeLayout with the EditText and the KeyboardView in one layout-XML. There was a different exception, something like "invalid type 0x12" or something when creating the layout.
It just doesn't work or I just don't know how to do it. Can anyone please guide me through this? Please let me know if something is missing.
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:id="#+id/field_input"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:inputType="textMultiLine|textImeMultiLine"
android:typeface="monospace"
android:gravity="top|left"
android:maxLength="255"
/>
</LinearLayout>
keyboard.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.messenger.keyboard.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/keyboard"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
LatinKeyboardView.java:
import android.inputmethodservice.KeyboardView;
public class LatinKeyboardView extends KeyboardView {
:
}
EditorActivity.java
import android.app.Activity;
public class EditorActivity extends Activity {
private View keyboardLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
final EditText inputField;
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
keyboardLayout = (View)getLayoutInflater().inflate(R.layout.keyboard, null, false);
inputField = (EditText)findViewById(R.id.field_input);
registerForContextMenu(inputField);
inputField.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//PopupWindow pw = new PopupWindow(inflater.inflate(R.layout.input, null, false), 100, 100, true);
PopupWindow pw = new PopupWindow(keyboardLayout, 100, 100, true);
pw.showAtLocation(findViewById(R.id.field_input), Gravity.CENTER, 0, 0);
}
});
/*
if (keyboardLayout.getVisibility() == View.GONE) {
// Show Media Player
TranslateAnimation mAnimUp =
new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, -keyboardLayout.getHeight(),
Animation.RELATIVE_TO_SELF, 0);
mAnimUp.setStartOffset(500);
mAnimUp.setDuration(500);
keyboardLayout.setVisibility(View.VISIBLE);
keyboardLayout.setAnimation(mAnimUp);
}
*/
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
:
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
:
}
#Override
public boolean onOptionsItemSelected(final MenuItem item) {
:
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
:
}
}
After hours of "research and trying" stuff, I finally understood my mistake, which seems to be "sjngm"'s one. In order for a virtual keyboard to render, you must
declare the view either by inflating a layout xml file, or by declaring in row your KeyboardView (just as you would do it for an other View).
And what was forgotten here: retrieve your KeyboardView with findViewById() and call on it:
keyboardViewInstance.setKeyboard(new Keyboard(...) );
That's it. You will be able to see your keyboardView on the screen! Of course, you need to either create your own Keyboard class, or to use the existing one with an xml resource file defining your keyboard keys (res/xml/keyboard.xml).
I'm currently reinventing my approach as I think that I didn't break the InputMethodService enough to have it work without itself. In other words I threw away the sample and started from scratch to get the layout working (it's now one layout instead of two) and then added the code from the sample to handle the inputs properly.
After further research I found a really helpful question about an App-specific soft-keyboard. If you run into my situation, look there.