In my application I have a custom view which requires some text input. As the view in itself doesn't contain any actual views (it's a Surface with custom drawing being done), I have a FrameLayout which contains the custom view and underneath it an EditText -view. When the user does a specific action, the custom view is hidden and the EditText takes over for user input. This works fine, but android:imeOptions seem to be ignored for this view. I'm currently doing this:
InputMethodManager inputMethodManager = (InputMethodManager)parent.getSystemService(Context.INPUT_METHOD_SERVICE);
EditText t = (EditText)parent.findViewById(R.id.DummyEditor);
t.setImeOptions(EditorInfo.IME_ACTION_DONE);
inputMethodManager.showSoftInput(t, 0, new ResultReceiver(mHandler) {
#Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
// We're done
System.out.println("Editing done : " +
((EditText)parent.findViewById(R.id.DummyEditor)).getText());
}
}
);
It seems that the setImeOptions(EditorInfo.IME_ACTION_DONE) has no effect. I've also tried adding the option to the layout XML with android:imeOptions="actionDone". No help.
Any ideas?
this post looks like will answer your question:
How do I handle ImeOptions' done button click?
Related
I have an activity that is basically a long form of entry fields.
On each row, I want to show a TextView to serve as hint text just below each EditText and I want the TextView to remain visible at all times when the user is entering data. Unfortunately, the soft keyboard obscures the hint text and always positions itself immediately below the EditText. Is there any technique that will allow the TextView below the EditText to also be visible when the soft keyboard appears and the contents are adjusted (via windowSoftInputMode=adjustResize|adjustPan), without having the user scroll ?
Vishavjeet got me on the right track in suggesting I scrolldown to reveal the view that may be overlapped by the keyboard. Below is a function similar to what I used to solve the problem. It can be called when the EditText above the TextView receives focus:
// View targetView; // View that may be hidden by keyboard
// ScrollView scrollContainerView; // Scrollview containing hiddenView
//
void assureViewVisible (View targetView, ScrollView, scrollContainerView) {
Window rootWindow = activity.getWindow();
Rect rMyView = new Rect();
View rootview = rootWindow.getDecorView();
rootview.getWindowVisibleDisplayFrame(rMyView); // Area not taken up by keyboard
int subTextPos[] = new int[2];
targetView.getLocationInWindow(subTextPos); // Get position of targetView
int subTextHt = targetView.getHeight(); // Get bottom of target view
if ((subTextPos[1]+subTextHt) > rMyView.bottom) { // Is targetView at all obscured?
int scrollBy = (subTextPos[1]+subTextHt) - rMyView.bottom + 10; // add a small bottom margin
mMeasurementViewScrollView.smoothScrollBy(0, scrollBy); // Scroll to subtext
}
}
EDIT:
By understanding the problem more deeply, I think that you should add scroll programatically when user clicks on the Edittext. Here is the code to do that:
private final void focusOnView()
{
new Handler().post(new Runnable()
{
#Override
public void run()
{
your_scrollview.scrollTo(0, your_EditBox.getBottom());
}});
}
From my personal experience I think there is not such way to do that. The thing you can do is place the hint textview toRightOf the editext. Or Use modern Approach by using a Hint Placeholder on Edittext:
In XML, it's simply android:hint="someText"
Programatically you can use edittext.setHint(int);
pass R.string.somestring in above method.
I have extended EditTextPreference, but the Dialog Message won't display. This happens if I add the dialogMessage programatically or in the the preferences.xml.
Here is my onBindDialogView:
AutoCompleteTextView editText = mEditText;
editText.setText(getText());
ViewParent oldParent = editText.getParent();
if (oldParent != view) {
if (oldParent != null) {
((ViewGroup) oldParent).removeView(editText);
}
onAddEditTextToDialogView(view, editText);
}
Is the dialog message really absent? It's probably there but its text color might make it less (or not) visible. (Or try to dismiss software keyboard). Try experimenting with dialog messages having a number of "\n" characters and see if that affects dialog layout. If so, it means the dialog message is actually there but camouflaged too well.
EditTextPreference brings a text view (in the preference_dialog_edittext.xml) that replaces the existing one (in the alert_dialog.xml) for the dialog message, but unfortunately with different text style, which might cause a visibility problem under certain themes. Even their sizes are different.
One solution might be to obtain the text color and size from the original text view to be replaced and apply them to the new one, but I would suggest retaining the original text view instead, because it's more likely to be visually consistent if there are any future UI changes. Try adding the following overrides
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
builder.setMessage(getDialogMessage()); // bring back the original text view
}
protected void onAddEditTextToDialogView(View dialogView, EditText editText) {
int id = getContext().getResources().getIdentifier("edittext_container", "id", "android");
ViewGroup container = (ViewGroup) dialogView.findViewById(id);
container.removeAllViews(); // remove the new text view
super.onAddEditTextToDialogView(dialogView, editText);
}
If you think the dialog message and the edittext view is too far apart, they can be brought together a little closer by adding another override:
protected void showDialog(Bundle state) {
super.showDialog(state);
int id = getContext().getResources().getIdentifier("message", "id", "android");
TextView message = (TextView) getDialog().findViewById(id);
message.setPadding(message.getPaddingLeft(), message.getPaddingTop(), message.getPaddingRight(), 0);
}
and add the following line in the onAddEditTextToDialogView method after calling removeAllViews:
container.setPadding(container.getPaddingLeft(), 0, container.getPaddingRight(), container.getPaddingBottom());
My question is on invoking the soft-keyboard in Android.
I am trying out the FingerPaint (API Demos), which is essentially a touch-drawing app. Attempting to give it a touch text-input interface, I added EditText inside the CustomView class, like the following:
private void inputText() {
EditText newText = new EditText(getContext());
//getContext needed as we're in a class extending View, not activity
newText.setText("Text Text Text");
//'addView' is deliberately left out for invisibility
//'requestFocus' also left out
// Show soft keyboard for the user to enter the value.
InputMethodManager imm = (InputMethodManager) ConfigKey.context.getSystemService("input_method");
imm.showSoftInput(newText, InputMethodManager.SHOW_IMPLICIT);
String newTextString = newText.getText().toString();
System.out.println(newTextString);
}
The EditText was added alright (as seen from the Logcat, "Text Text Text") but there was just no keyboard to be seen for inputing.
Any way to fix it?
Any thoughts would be appreciated!
Im working on an input method for android and one of the tasks is to implement a custom popup keyboard for hard keyboard key presses. Usually input methods let the editor handle that but the thing is I need to add more symbols than android supports.
So I implemented the popup keyboard and even have it displaying well when a hard key (character key) is long pressed.
The steps I've followed are:
Create popup window.
Inflate a linear layout which contains a keyboardview and a close button and save it to a view object
bind the keyboardview and close buttons to the relevant objects
Create a keyboard for the popup characters and set it as the keyboard for the keyboard view. The keyboard has a column limit of 5.
set the linear layout as the content view for the popup window
Display the popup window
THE ISSUE: If there are multiple rows in the popup keyboard I am only able to select key in the last row for the column. Even if I click on the key in the first row of that column, the key in the last row gets selected.
If anyone could explain why this is happening and how do I fix it, Id appreciate it.
THE CODE:
PopupWindow mPopupKeyboard = new PopupWindow(this.getBaseContext());
mPopupKeyboard.setBackgroundDrawable(null);
if(mPopupKeyboard != null)
{
this.dismissPopupKeyboard();
View mMiniKeyboardContainer = null;
KeyboardView mMiniKeyboard = null;
View closeButton = null;
mMiniKeyboardContainer = getLayoutInflater().inflate(R.layout.keyboard_popup_keyboard, null);
mMiniKeyboard = (KeyboardView) mMiniKeyboardContainer.findViewById(R.id.popup_keyboardView);
closeButton = mMiniKeyboardContainer.findViewById(R.id.closeButton);
if (closeButton != null)
{
closeButton.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
mPopupKeyboard.dismiss();
});
}
mMiniKeyboard.setOnKeyboardActionListener(this);
String resourcestring = "abcdefghi";
mMiniKeyboard.setKeyboard(new Keyboard(this.getBaseContext(), R.xml.kbd_popup_template, alternates, 3, 0));
mMiniKeyboard.setPopupParent(mCandidateView);
mPopupKeyboard.setContentView(mMiniKeyboardContainer);
mPopupKeyboard.setWidth(LayoutParams.WRAP_CONTENT);
mPopupKeyboard.setHeight(LayoutParams.WRAP_CONTENT);
mPopupKeyboard.showAtLocation(mCandidateView, Gravity.TOP, 0, 0);
}
I had a similar problem with popup keyboards. I found that it was a problem only with Android 2.3. My only workaround was to avoid popup keyboards with more than one row.
The reason this occurs is because KeyboardView sends off the MotionEvent. MotionEvent.getRawX() and getRawY() only return coordinates within the bounds of KeyboardView. If the MotionEvent happens above KeyboardView, it returns the closest absolute coordinates in KeyboardView.
One solution is to create an invisible View above KeyboardView. It will have to detect the MotionEvent and then pass the MotionEvent back to KeyboardView and then your multirow popup keyboard will work
For the starting code look at CandidateViews above the KeyboardView. For example look at this project:
https://github.com/blackcj/AndroidCustomKeyboard
In the
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
(https://github.com/blackcj/AndroidCustomKeyboard/blob/master/app/src/main/java/com/blackcj/customkeyboard/CandidateView.java)
method add 200 to desiredHeight in this statement:
setMeasuredDimension(measuredWidth, resolveSize(desiredHeight, heightMeasureSpec));
Notice how this will cause the motionEvent.getRawY() to work for an extra 200p in height
I like my UIs to be intuitive; each screen should naturally and unobtrusively guide the user on to the next step in the app. Barring that, I strive to make things as confusing and confounding as possible.
Just kidding :-)
I've got three TableRows, each containing a read-only and non-focusable EditText control and then a button to its right. Each button starts the same activity but with a different argument. The user makes a selection there and the sub-activity finishes, populating the appropriate EditText with the user's selection.
It's the classic cascading values mechanism; each selection narrows the available options for the next selection, etc. Thus I'm disabling both controls on each of the next rows until the EditText on the current row contains a value.
I need to do one of two things, in this order of preference:
When a button is clicked, immediately remove focus without setting focus to a different button
Set focus to the first button when the activity starts
The problem manifests after the sub-activity returns; the button that was clicked retains focus.
Re: #1 above - There doesn't appear to be a removeFocus() method, or something similar
Re: #2 above - I can use requestFocus() to set focus to the button on the next row, and that works after the sub-activity returns, but for some reason it doesn't work in the parent activity's onCreate().
I need UI consistency in either direction--either no buttons have focus after the sub-activity finishes or each button receives focus depending on its place in the logic flow, including the very first (and only) active button prior to any selection.
Using clearFocus() didn't seem to be working for me either as you found (saw in comments to another answer), but what worked for me in the end was adding:
<LinearLayout
android:id="#+id/my_layout"
android:focusable="true"
android:focusableInTouchMode="true" ...>
to my very top level Layout View (a linear layout). To remove focus from all Buttons/EditTexts etc, you can then just do
LinearLayout myLayout = (LinearLayout) activity.findViewById(R.id.my_layout);
myLayout.requestFocus();
Requesting focus did nothing unless I set the view to be focusable.
Old question, but I came across it when I had a similar issue and thought I'd share what I ended up doing.
The view that gained focus was different each time so I used the very generic:
View current = getCurrentFocus();
if (current != null) current.clearFocus();
You can use View.clearFocus().
Use View.requestFocus() called from onResume().
android:descendantFocusability="beforeDescendants"
using the following in the activity with some layout options below seemed to work as desired.
getWindow().getDecorView().findViewById(android.R.id.content).clearFocus();
in connection with the following parameters on the root view.
<?xml
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants" />
https://developer.android.com/reference/android/view/ViewGroup#attr_android:descendantFocusability
Answer thanks to:
https://forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text
About windowSoftInputMode
There's yet another point of contention to be aware of. By default,
Android will automatically assign initial focus to the first EditText
or focusable control in your Activity. It naturally follows that the
InputMethod (typically the soft keyboard) will respond to the focus
event by showing itself. The windowSoftInputMode attribute in
AndroidManifest.xml, when set to stateAlwaysHidden, instructs the
keyboard to ignore this automatically-assigned initial focus.
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
great reference
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/ll_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
LinearLayout llRootView = findViewBindId(R.id.ll_root_view);
llRootView.clearFocus();
I use this when already finished update profile info and remove all focus from EditText in my layout
====> Update: In parent layout content my EditText add line:
android:focusableInTouchMode="true"
What about just adding android:windowSoftInputMode="stateHidden" on your activity in the manifest.
Taken from a smart man commenting on this: https://stackoverflow.com/a/2059394/956975
I tried to disable and enable focusability for view and it worked for me (focus was reset):
focusedView.setFocusable(false);
focusedView.setFocusableInTouchMode(false);
focusedView.setFocusable(true);
focusedView.setFocusableInTouchMode(true);
First of all, it will 100% work........
Create onResume() method.
Inside this onResume() find the view which is focusing again and again by findViewById().
Inside this onResume() set requestFocus() to this view.
Inside this onResume() set clearFocus to this view.
Go in xml of same layout and find that top view which you want to be focused and set focusable true and focusableInTuch true.
Inside this onResume() find the above top view by findViewById
Inside this onResume() set requestFocus() to this view at the last.
And now enjoy......
android:focusableInTouchMode="true"
android:focusable="true"
android:clickable="true"
Add them to your ViewGroup that includes your EditTextView.
It works properly to my Constraint Layout. Hope this help
You could try turning off the main Activity's ability to save its state (thus making it forget what control had text and what had focus). You will need to have some other way of remembering what your EditText's have and repopulating them onResume(). Launch your sub-Activities with startActivityForResult() and create an onActivityResult() handler in your main Activity that will update the EditText's correctly. This way you can set the proper button you want focused onResume() at the same time you repopulate the EditText's by using a myButton.post(new Runnable(){ run() { myButton.requestFocus(); } });
The View.post() method is useful for setting focus initially because that runnable will be executed after the window is created and things settle down, allowing the focus mechanism to function properly by that time. Trying to set focus during onCreate/Start/Resume() usually has issues, I've found.
Please note this is pseudo-code and non-tested, but it's a possible direction you could try.
You do not need to clear focus, just add this code where you want to focus
time_statusTV.setFocusable(true);
time_statusTV.requestFocus();
InputMethodManager imm = (InputMethodManager)this.getSystemService(Service.INPUT_METHOD_SERVICE);
imm.showSoftInput( time_statusTV, 0);
Try the following (calling clearAllEditTextFocuses();)
private final boolean clearAllEditTextFocuses() {
View v = getCurrentFocus();
if(v instanceof EditText) {
final FocusedEditTextItems list = new FocusedEditTextItems();
list.addAndClearFocus((EditText) v);
//Focus von allen EditTexten entfernen
boolean repeat = true;
do {
v = getCurrentFocus();
if(v instanceof EditText) {
if(list.containsView(v))
repeat = false;
else list.addAndClearFocus((EditText) v);
} else repeat = false;
} while(repeat);
final boolean result = !(v instanceof EditText);
//Focus wieder setzen
list.reset();
return result;
} else return false;
}
private final static class FocusedEditTextItem {
private final boolean focusable;
private final boolean focusableInTouchMode;
#NonNull
private final EditText editText;
private FocusedEditTextItem(final #NonNull EditText v) {
editText = v;
focusable = v.isFocusable();
focusableInTouchMode = v.isFocusableInTouchMode();
}
private final void clearFocus() {
if(focusable)
editText.setFocusable(false);
if(focusableInTouchMode)
editText.setFocusableInTouchMode(false);
editText.clearFocus();
}
private final void reset() {
if(focusable)
editText.setFocusable(true);
if(focusableInTouchMode)
editText.setFocusableInTouchMode(true);
}
}
private final static class FocusedEditTextItems extends ArrayList<FocusedEditTextItem> {
private final void addAndClearFocus(final #NonNull EditText v) {
final FocusedEditTextItem item = new FocusedEditTextItem(v);
add(item);
item.clearFocus();
}
private final boolean containsView(final #NonNull View v) {
boolean result = false;
for(FocusedEditTextItem item: this) {
if(item.editText == v) {
result = true;
break;
}
}
return result;
}
private final void reset() {
for(FocusedEditTextItem item: this)
item.reset();
}
}