PopupWindow - Dismiss when clicked outside - android

I have a PopupWindow on my activity, the thing is my PopupWindow still shows even when I'm interacting with my activity (say scrolling on my list). I can scroll through my list and the PopupWindow is still there.
What I want to achieve is when I'm touching/scrolling/clicking/etc on the screen which is not the PopupWindow, I want to dismiss the PopupWindow. Just like how a menu works. If you clicked outside of the menu, the menu will be dismissed.
I've tried setOutsideTouchable(true) but it won't dismiss the window. Thanks.

Please try to set setBackgroundDrawable on PopupWindow that should close the window if you touch outside of it.

I found that none of the answers supplied worked for me, except WareNinja's comment on the accepted answer, and Marcin S.'s will probably also work. Here's the part that works for me:
myPopupWindow.setBackgroundDrawable(new BitmapDrawable());
myPopupWindow.setOutsideTouchable(true);
Alternatively:
myPopupWindow.setFocusable(true);
Not sure what the differences are, but the ListPopupWindow source code actually uses the latter when it's modality is set to true with setModal, so at least the Android developers consider this a viable approach, and it's only one line.

I met the same issues, and fixed it as below codes. It works fine for me.
// Closes the popup window when touch outside.
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setFocusable(true);
// Removes default background.
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
BTW, Don't use BitmapDrawable deprecated constructor, use this new ColorDrawable(android.R.color.transparent) to replace default background.
Have fun#.#

I know it's late but I notice that people still have an issue with the popup window. I have decided to write a fully working example where you can dismiss the popup window by touching or clicking outside of it or just touching the window itself. To do so create a new PopupWindow class and copy this code:
PopupWindow.class
public class PopupWindow extends android.widget.PopupWindow
{
Context ctx;
Button btnDismiss;
TextView lblText;
View popupView;
public PopupWindow(Context context)
{
super(context);
ctx = context;
popupView = LayoutInflater.from(context).inflate(R.layout.popup, null);
setContentView(popupView);
btnDismiss = (Button)popupView.findViewById(R.id.btn_dismiss);
lblText = (TextView)popupView.findViewById(R.id.text);
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
// Closes the popup window when touch outside of it - when looses focus
setOutsideTouchable(true);
setFocusable(true);
// Removes default black background
setBackgroundDrawable(new BitmapDrawable());
btnDismiss.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
dismiss();
}});
// Closes the popup window when touch it
/* this.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
dismiss();
}
return true;
}
}); */
} // End constructor
// Attaches the view to its parent anchor-view at position x and y
public void show(View anchor, int x, int y)
{
showAtLocation(anchor, Gravity.CENTER, x, y);
}
}
Now create the layout for the popup window:
popup.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:text="PopupWindow Example"
android:textColor="#000000"
android:textSize="17sp"
android:textStyle="italic" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<Button
android:id="#+id/btn_dismiss"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dismiss"
android:visibility="gone" />
<TextView
android:id="#+id/lbl_dismiss"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Touch outside of this box to dismiss"
android:textColor="#ffffff"
android:textStyle="bold" />
</FrameLayout>
In your main activity create an instance of the PopupWindow class:
final PopupWindow popupWindow = new PopupWindow(this);
popupWindow.show(findViewById(R.id.YOUR_MAIN_LAYOUT), 0, -250);
where YOUR_MAIN_LAYOUT is the layout of the current activity in which popupWindow will pop up

Thanks for #LunaKong's answer and #HourGlass's confirmation. I don't want to make a duplicated comment, but only want to make it clear and concise.
// Closes the popup window when touch outside. This method was written informatively in Google's docs.
mPopupWindow.setOutsideTouchable(true);
// Set focus true to prevent a touch event to go to a below view (main layout), which works like a dialog with 'cancel' property => Try it! And you will know what I mean.
mPopupWindow.setFocusable(true);
// Removes default background.
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Mttdat.

For a ListPopupWindow set the window to be a modal when shown.
mListPopupWindow.setModal(true);
That way, clicking outside of the ListPopupWindow will dismiss it.

Notice that for canceling with popupWindow.setOutsideTouchable(true),
you need to make width and height wrap_content like below code:
PopupWindow popupWindow = new PopupWindow(
G.layoutInflater.inflate(R.layout.lay_dialog_support, null, false),
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT, true);
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.showAtLocation(view, Gravity.RIGHT, 0, 0);

You can use isOutsideTouchable OR isFocusable to dissmiss popup window when touch outside
popupWindow.isOutsideTouchable = true // dismiss popupwindow when touch outside
popupWindow.isFocusable = true // dismiss popupwindow when touch outside AND when press back button
Note
Currently, after test I see setBackgroundDrawable don't help us dismiss popupwindow
If you look at the code for dismiss in PopupWindow (PopupWindow->PopupDecorView->dispatchKeyEvent and PopupWindow->PopupDecorView->onTouchEvent). You will see that when press back button, they dismiss on ACTION_UP and when touch outside they dismiss on ACTION_UP or ACTION_OUTSIDE

mPopWindow.setFocusable(true);

popupWindow.setTouchable(true);
popupWindow.setFocusable(true);
popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
It will dismiss the PopupWindow when click/touch on screen.Make sure you have set focusable true before showAtLocation.

#LunaKong suggestion work's like a charm.
But setting up mPopupWindow.setFocusable(false). removes unnecessary touch required to make popup window disappear.
For example:
Let's consider there is a pop up window visible on screen, and you are about to click a button.
So in this case, (if mpopwindow.setFocusable(true))
on the first click of a button popupwindow will dismiss.
But you have to click again to make the button works.
if**(mpopwindwo.setFocusable(false)**
single click of button dismiss the popup window as well as trigger the button click.
Hope it helps.

In some cases making the popup focusable is not desirable (e.g. you may not want it to steal focus from another view).
An alternative approach is using a touch interceptor:
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
popupWindow.dismiss();
}
return false;
}
});

Set the window background transparent:
PopupWindow.getBackground().setAlpha(0);
After it set your background in layout. Works fine.

If this Popup Window is another activity,and you decreased its size to the original screen
and you want to enable or disable the outside area.you can simply enable or disable the outside area by this code:
enable:
YourActivity.this.setFinishOnTouchOutside(true);
disable:
YourActivity.this.setFinishOnTouchOutside(false);

Use View popupView to dismiss the popupWindow
`popupView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
popupWindow.dismiss();
}
});
`
If you use this you can also setOnClickListener to any button inside the popupWindow

Related

how to dismiss a popupwindow when click button?

what i want to do
i want to write a button that when i click it will show a popupwindow,and when i click the outside or click the button again the popupwindow will dismiss.
what i do
i use the code like this
mPopupWindow=new PopupWindow();
mPopupWindow.setTouchable(true);
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
brush.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPopupWindow.setContentView(brushView);
mPopupWindow.showAsDropDown(v);
}
});
what the problem
when i click the button again it will show Attempted to finish an input event but the input event receiver has already been disposed.
it think it because it tirgger the outside and clicklistener
Please try with below answer:
mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
mPopupWindow.setOutsideTouchable(true);
To make the popup dissapear when clicked on the outside use:
myPopupWindow.setOutsideTouchable(true);
To open and close the popup on clicking the button, put this code in your OnClickListener:
if(myPopupWindow.isShowing()) {
myPopupWindow.dismiss();
} else {
mPopupWindow.setContentView(brushView);
mPopupWindow.showAsDropDown(v);
}
Just use
myPopupWindow.setOutsideTouchable(true);
just find a trick
use
mPopupWindow=new PopupWindow(new View(mcontext),WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,true);
i don't know why but it works

Is it possible to create a clickable Toast-like notification?

I have a need to show a minimally-intrusive non-blocking notification which is not tied to the activity it was shown in (like a Toast) and which is clickable. Anyone have any idea whether or not this is possible? Unfortunately, it appears that Toast notifications (custom or otherwise) are not clickable (i.e. setting an OnClickListener on its views has no effect). All the alternatives that I'm aware of (i.e. AlertDialog, PopupWindow and Crouton) seem to show a notification which is tied to the activity it was shown in (i.e. they won't continue showing when the activity finishes). Any suggestions?
You can use PopupWindow, add an onClickListener and add a handler to auto cancel it after n times (just like the behavior of a toast). Something like this:
public static void showToast(Activity a, String title, String message) {
// inflate your xml layout
LayoutInflater inflater = a.getLayoutInflater();
View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) a.findViewById(R.id.toast_layout_root));
// set the custom display
((TextView) layout.findViewById(R.id.title)).setText(title);
((TextView) layout.findViewById(R.id.message)).setText(message);
// initialize your popupWindow and use your custom layout as the view
final PopupWindow pw = new PopupWindow(layout,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT, true);
// set windowType to TYPE_TOAST (requires API 23 above)
// this will make popupWindow still appear even the activity was closed
pw.setWindowLayoutType(WindowManager.LayoutParams.TYPE_TOAST);
pw.showAtLocation(layout, Gravity.CENTER | Gravity.TOP, 0, 500);
// handle popupWindow click event
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do anything when popupWindow was clicked
pw.dismiss(); // dismiss the window
}
});
// dismiss the popup window after 3sec
new Handler().postDelayed(new Runnable() {
public void run() {
pw.dismiss();
}
}, 3000);
}
xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toast_layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
android:orientation="vertical"
android:elevation="10dp"
android:padding="20dp">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#FFF"
android:textStyle="bold"/>
<TextView
android:id="#+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#FFF"/>
</LinearLayout>
You are right, a Toast object has no way to be interacted with, but there are many libraries out there that will give you the same look and feel as a toast, but with some interactivity. The one I use is https://github.com/JohnPersano/SuperToasts
I think what you need is in fact a PopupWindowwhich can be seen here "http://developer.android.com/reference/android/widget/PopupWindow.html".
Toasts have a very specific task, which is to inform the user, without any input from them. So instead of trying to extend the purpose of the Toast, use the PopupWindow which can be interacted with by the user.
A 'Dialog' type of activity will probably be your best bet.
In manifest:
<activity android:name=".ToastLikeActivity"
android:theme="#android:style/Theme.Dialog"
android:label="#string/label"
></activity>
And timeout the activity within the onCreate():
class ToastLikeActivity extends Activity {
#Override
public void onCreate(Bundle state)
// auto-kill activity after X seconds <-------------------------
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
ToastLikeActivity.this.finish(); // kill after X seconds
}
}
}, VisibleTimeSecs*1000);
}
To display the dialog start it as with any other activity:
Intent i = new Intent(this, ToastLikeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
And it will show up and automatically go away after X seconds.
Such a popup will not be tied to the caller activity. In fact - it will not even require a caller activity. You
can activate it (bad idea, but possible) even from a service.
You can implement basically any kind of sensitive (i.e. accepting user's clicks) interface you want to
the ToastLikeActivity. Especially: you can make its exteriors transparent, giving it a dialog-likke looks.

Can't edit an edittext in a popup window without dismissing and recalling it first

I am using a popup window to display some information and have an edit button that allows that information to be changed. I am loading all textviews, buttons and edittext fields and hiding/showing them as needed. The edittext fields are not letting me edit them. I have tried the below suggestion about setting focusable to true, but that isn't working. Any other suggestions?
Tried this: EditText On A Popup Window
EDIT: Below is part of my code. I've just included the parts for initializing the edittext and showing the popup contents since everything else is working, just not the edittext. I am using a tablelayout, and when the user clicks a row, the popup window displays. Keep in mind I'm still pretty new to Java and Android!
EDIT #2: The softkeyboard was not showing when the edittext was selected, but now it will show if I dismiss the popup once and then call it again. I then tried forcing the softkeyboard to display, and it showed behind the popup (another problem). I was able to select the number 1 since it was barely showing behind the popup window, but it didn't seem to work either. The fix was the same here: dismiss the popup window and recall it. So my remaining problem is being able to type into the edittext without having to dismiss the popup once and recall it. As such, I am changing the title of this question.
row1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final EditText pwETBrand = (EditText) vPopUp.findViewById(R.id.et_editbrand);
if (!infoClick) {
infoClick = true;
// Popup elements initialized earlier
pwInfo.showAtLocation(llInfo, Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
pwInfo.update(0, 0, llMain.getWidth()-50, llMain.getHeight()-100);
pwInfo.setFocusable(true);
....
// Hide some elements initially until "EDIT" button is pressed
pwETBrand.setVisibility(View.INVISIBLE);
....
// When EDIT button is pressed, hide default elements, and show edit elements
pwEdit.setOnClickListener(new OnClickListener() {
public void onClick(View v2) {
pwETBrand.setVisivility(View.VISIBLE);
// Other element settings go here
pwInfo.setFocusable(true);
}
)};
....
}
}
I have implemented a solution, though it may not be the best solution. I have set a boolean field at the class initialization that checks if the popupwindow has ever been called. If it has not yet been called, then it will immediately dismiss the popupwindow and re-open it since my problem is in the popupwindow initialization.
pwInfo.showAtLocation(llInfo, Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
pwInfo.update(0, 0, llMain.getWidth()-50, llMain.getHeight()-100);
pwInfo.setFocusable(true);
if (pwFirst) {
pwFirst = false;
pwInfo.dismiss();
pwInfo.showAtLocation(llInfo, Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
pwInfo.update(0, 0, llMain.getWidth()-50, llMain.getHeight()-100);
pwInfo.setFocusable(true);
}
Not the best solution, but it works.
Try this,
final PopupWindow popupWindow = new PopupWindow(popupView,LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,true);
works for me.
Use Below Link's Code for that, it may help you.
Popup With Edittext
Whenever you create a PopupWindow you must put true in focusable like that :
PopupWindow(View contentView, int width, int height, boolean focusable)
final PopupWindow popupWindow = new PopupWindow(popupView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,true);
good luck

Issue dismissing popup window

I have a popup menu implemented , which shows up on click of a button. This is my onclick method.
public void showOverflow(View view) {
boolean click = true;
Button action = (Button) findViewById(R.id.btbAction);
LayoutInflater inflater = (LayoutInflater) main.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popupView = inflater.inflate(R.layout.overflow_layout, null);
final PopupWindow pw = new PopupWindow(popupView,
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
pw.setOutsideTouchable(true);
if (click) {
pw.showAsDropDown(action, 0, 0);
click = false;
} else {
pw.dismiss();
click = true;
}
}
The popup window shows up when the button is clicked. Now, the problem is that the window is not dismissed when i touch outside the popup window.
I tried setting this property to the popup window
pw.setOutsideTouchable(true);
Things remain the same. Please help me fix this
You should change the setOutsideTouchable call's parameter to true:
pw.setOutsideTouchable(false);
Controls whether the pop-up will be informed of touch events outside
of its window. This only makes sense for pop-ups that are touchable
but not focusable, which means touches outside of the window will be
delivered to the window behind. The default is false.
If the popup is showing, calling this method will take effect only the
next time the popup is shown or through a manual call to one of the
update() methods.
Parameters: touchable true if the popup should receive outside touch
events, false otherwise
On the other hand, what is the click local variable supposed to do? It is set to true, so it will always force the pw to pop up, whenever the showOverflow method is called, and for no reason it is set to false later, because it's life cycle ends as you leave that method.
Your code should look something like this:
private LayoutInflater inflater;
private Button action;
private PopupWindow pw;
private View popupView;
/*
* (non-Javadoc)
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
popupView = inflater.inflate(R.layout.overflow_layout, null, false);
action = (Button) findViewById(R.id.action);
action.setOnClickListener(this);
}
public void showOverflow()
{
pw = new PopupWindow(getApplicationContext());
pw.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
pw.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
pw.setOutsideTouchable(true);
pw.setContentView(popupView);
pw.showAsDropDown(action, 0, 0);
}
The getApplicationContext() shoud be used in case you are inside an Activity class. Otherwise you should get the Context as a parameter.
change pw.setOutsideTouchable(true); to pw.setOutsideTouchable(false);
I know this is an old question but this is what I have done to fix it
The problem is:
You are creating a new instance of popupwindow everytime you call showOverFlow() thats why after you close the popupwindow another popup window will show
What will you do is initialize popupview in OnCreate
Then call popupwindow.showAsDropDown(view) in showOverFlow() method
And lastly you can check whether is it showing below code
Put this code in your button onclick
if(popupwindow.isShowing()){
popup.dismiss() }
else{
ShowOverflow()}

Android: EditText in Dialog doesn't pull up soft keyboard

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

Categories

Resources