I have a popup window displaying when I click an item in my list activity. The problem is that the back key doesn't close it. I tried catching the back key in my list activity but it doesn't register it...then I tried registering a onkeylistener to the view I'm passing to my popup window. Like this:
pop.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
boolean res=false;
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
Log.e("keydown","back");
if (pw.isShowing()) {
Log.e("keydown","pw showing");
pw.dismiss();
res = true;
}
} else {
res = false;
}
return res;
}
});
which is passed to a popup like this:
pw = new PopupWindow(
pop,
240,
70,
true);
But that listener doesn't fire neither. Can you help me? I'm out of ideas :)
This is because the popup window does not respond to onTouch or onKey events unless it has a background that != null. Check out some code I wrote to help with this. In the basic case you can to call PopupWindow#setBackgroundDrawable(new BitmapDrawable()) to force it to act the way you expect. You won't need your own onKey listener. You might also need to call PopupWindow#setOutsideTouchable(true) if you want it to go away when the user clicks outside of the window boundaries.
Extended esoteric answer:
The reason the background cannot be null is because of what happens in PopupWindow#preparePopup. If it detects background != null it creates an instance of PopupViewContainer and calls setBackgroundDrawable on that and puts your content view in it. PopupViewContainer is basically a FrameLayout that listens for touch events and the KeyEvent.KEYCODE_BACK event to dismiss the window. If background == null, it doesn't do any of that and just uses your content view. You can, as an alternative to depending on PopupWindow to handle that, extend your root ViewGroup to behave the way you want.
Do as per following it works fine:
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(btnSelectWeight);
For new projects it's better to use
popupWindow.setBackgroundDrawable(new ColorDrawable());
instead of
popupWindow.setBackgroundDrawable(new BitmapDrawable());
as BitmapDrawable is deprecated. Also, it's better than ShapeDrawable in this case. I noticed that when PopupWindow is a rectangle with rounded corners, ShapeDrawable fills corners with black.
A really simple solution is to write pw.setFocusable(true), but probably you don't want to do this because then the MapActivity won't handle touch events.
A better solution is to override the back key, e.g like this:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Override back button
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (pw.isShowing()) {
pw.dismiss();
return false;
}
}
return super.onKeyDown(keyCode, event);
}
Good luck!
For the new searchers, as creating a new BitmapDrawable is not allowed now(The constructor BitmapDrawable() is deprecated) , so that you have to change it to a new ShapeDrawable(), so that you will change :
pw.setBackgroundDrawable(new BitmapDrawable());
To :
pw.setBackgroundDrawable(new ShapeDrawable());
And the whole work will be like :
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() { // or whatever you want
#Override
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE) // here I want to close the pw when clicking outside it but at all this is just an example of how it works and you can implement the onTouch() or the onKey() you want
{
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
just use this
mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));
which is not deprecated. i'd avoid new ShapeDrawable() as its going to render slowly as it tries to draw a shape when the screen needs to be redrawn.
I hope this will be help for you
pw.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pw.dismiss();
}
return true;
}
});
you need add setBackgroundDrawable(new BitmapDrawable()) for your PopupWindow.
private void initPopupWindow() {
// TODO Auto-generated method stub
View view = getLayoutInflater().inflate(R.layout.main_choice, null);
ListView main_menu_listview = (ListView) view.findViewById(R.id.main_menu_listview);
ShowMainChoice madapter = new ShowMainChoice(context);
main_menu_listview.setAdapter(madapter);
int width = (int)getWindowManager().getDefaultDisplay().getWidth()/2;
popupWindow = new PopupWindow(view, width,WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new BitmapDrawable());//this is important,如果缺少这句将导致其他任何控件及监听都得不到响应
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
main_menu_listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
// TODO Auto-generated method stub
Log.e("++++++>", arg2+"");
}
});
}
This problem is popupwindow底层的消息机制决定的,因为它是阻塞式的。Good luck
pw.setBackgroundDrawable(new ColorDrawable());
must wrote it before setContentView
This works for me.
Are you looking for the combination of the popupwindow dismiss and a good working of the BACK button, then you may consider the below solution.
Solution principle: all button clicks near your popup window will be intercepted, but any BACK button will not be intercepted. So, if you have anything in you popupwindow that takes action, then set an indication just before your call to dismiss(). In your setOnDismissListener() perform an extra action (like getActivity().popupBackStack()).
The advantage of this solution is that you can create your own CustomPopupWindow and implement this strategy. You can hide this implementation in your custom popup window.
Step 1: add near to your instantiation of your Popup Window:
boolean isClickHandled = false;
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new ShapeDrawable());
popupWindow.setTouchInterceptor(new View.OnTouchListener() { // or whatever you want
#Override
public boolean onTouch(View v, MotionEvent event) {
isClickHandled = true;
return false;
}
});
If you have buttons inside your popupWindow, have the setOnClickListener.onClick set the isClickHandled = true and dismiss().
In your onDismissListener do something like:
popupWindow.setOnDismissListener(() -> {
popupWindow.dismiss();
if ( !isClickHandled) {
MainActivity.mainActivity.getSupportFragmentManager().popBackStack();
}
});
Related
I want to clicked back button to dismiss PopupWindow.But I can also click outside to do another thing,the PopupWindow don't miss.
I try popupWindow.setFocusable(true);,but the PopupWindow will dismiss when I click outside.
I try to custom view.
public class OtherBrifeIntroView extends LinearLayout
{
#Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
Toast.makeText(mContext, "test", Toast.LENGTH_SHORT).show();
return true;
}
return super.dispatchKeyEvent(event);
}
}
but it doesn't work.Can you help me?
I solve it.Set TouchModal false,but the setTouchModal is hide,so I use reflect.
public static void setPopupWindowTouchModal(PopupWindow popupWindow, boolean touchModal)
{
if (null == popupWindow)
{
return;
}
Method method;
try
{
method = PopupWindow.class.getDeclaredMethod("setTouchModal", boolean.class);
method.setAccessible(true);
method.invoke(popupWindow, touchModal);
}
catch (Exception e)
{
e.printStackTrace();
}
}
Finally.
setPopupWindowTouchModal(popupWindow, false);
popupWindow.setFocusable(true);
You can call popupWindow.dismiss() to manually dismiss the PopupWindow within your dispatchKeyEvent method. In order to stop it dismissing when you touch outside of the PopupWindow there are a number of things you can try.
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
Have a play about with the above values and see what the outcome is, I am not on my developer computer at the moment so can't test which one it is.
I know how to make android menu using Java or XML and how to use or call but now I am facing a new situation i.e. I want to open menu in a specific place like when I click on image than menu pop-up on that image place.
How can I do it?
Following code will help you to open popup at dynamic place:
public void showMenuPopUp(final View view, final Context mCtx ) {
LayoutInflater layoutInflater = (LayoutInflater) mCtx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.menu_popup, null);
popupWindow = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, true);
popupWindow.setFocusable(true);
popupWindow.update();
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
popupWindow.dismiss();
return true;
}
return false;
}
});
Button btn1= (Button) popupView.findViewById(R.id.btn1);
Button (new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// button click event
popupWindow.dismiss();
}
});
popupWindow.showAsDropDown(view, 0, 0);
}
Where view is your view on which you have to open popup
To open this popup on Image click write onClickLsitener of your Image like this:
ImageView img = (ImageView) findViewById(R.id.myImageId);
img.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// your code here
showMenuPopUp(v,Activity.this);
}
});
I have answered similar question here , I used PopUpWindow in that example, you can also use DialogFragment but slightly minimum option,both supports custom layout which looks like menu. you can perform similar option on Button you clicked in your screen or the Actionbar button
You have two option two do this using popupwindow, on click of a button you can do 1)showAsDropDown(findViewbyId(R.id.menuitem),0,0) for popupwindow which is good cause it looks like it popped down from the button you clicked or
2)showAtLocation() which takes gravity property like X and Y positions, in which you can mention which place on the screen you want the menu to appear
Found two solutions - please see selected answer
When the user clicks in a certain region of an EditText, I want to popup a dialog. I used onClick to capture the click. This partially works: the first time the user taps the EditText, the soft keyboard pops up and the dialog doesn't. Subsequent taps bring up the keyboard and then the dialog (and the keyboard disappears).
I suspect this has something to do with the EditText gaining focus.
Here's a code snip:
public class PrefixEditText extends EditText implements TextWatcher, OnClickListener
{
public PrefixEditText (Context context)
{
super (context);
setOnClickListener (this);
}
#Override
public void onClick(View v)
{
int selStart = getSelectionStart();
if (selStart < some_particular_pos)
bring_up_dialog();
}
}
IMPORTANT: I don't want to completely disable the normal EditText behavior. I want the user to be able to make region selections (for copy & paste). I probably still want it to gain focus (so I don't break the model when people with physical keyboards use the app). And it's ok for the click to set the cursor position. Thus, solutions that override onTouch and block all onTouch actions from the EditText will not work for me.
UPDATE I've discovered a bit more. If the EditText is gaining focus, onFocusChange gets called and onClick does not. If it already has focus, onClick gets called and onFocusChange does not.
Secondly, it's possible to hide the keyboard by calling
setInputType (InputType.TYPE_NULL);
Doing so in onFocusChange works - the keyboard never shows up. Doing so in onClick (assuming the keyboard was hidden before the click) apparently is too late - the keyboard shows up and then disappears.
The next idea to try would be to hide the keyboard during onTouch. However, I'm afraid to mess with that code - seems that whatever I figure out would be very fragile with respect to future versions of EditText.
Any thoughs on this?
May be this can work
EditText e = new EditText(context);
e.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if(hasFocus)
{
//dialogue popup
}
}
});
or u can use e.hasFocus(); and then use e.setFocusable(false); to make it unfocus
/////////////// my code
e.setInputType(InputType.TYPE_NULL);
e.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
AlertDialog.Builder sa = new Builder(ctx);
sa.create().setOnDismissListener(new OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
// TODO Auto-generated method stub
e.setInputType(InputType.TYPE_CLASS_TEXT);
}
});
sa.show();
}
});
try change capture click by onClick to onTouch
this.editText.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//dialogue popup
}
return false;
}
});
try this if it can help u.first time the edittext will behave as a normal editttext and on condition u can show the dialog as needed
EditText editText;
mTim_edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
//statement
if(condition){
AlertDialog diaBox = Utils.showErrorDialogBox( "Term in Months Cannot be 0", context);
diaBox.show();
}
}
}
});
After lots of experiments, here are two working solutions! I tested them on my two devices - Nexus 7 running 4.2.1, Kyocera C5170 runing 4.0.4. My preference is Solution 2.
SOLUTION 1
For the first, the trick was to determine the cursor position in onTouch instead of onClick, before EditText has a chance to do it's work - particularly before it pops up the keyboard.
One additional comment: be sure to set android:windowSoftInputMode="stateHidden" in your manifest for the popup, or you'll get the keyboard along with the popup.
Here's the whole code:
public class ClickText extends EditText implements OnTouchListener
{
public ClickText (Context context, AttributeSet attrs)
{
super (context, attrs);
setOnTouchListener (this);
}
#Override
public boolean onTouch (View v, MotionEvent event)
{
if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
{
int line = getLayout().getLineForVertical ((int)event.getY());
int onTouchCursorPos = getLayout().getOffsetForHorizontal (line, event.getX());
if (onTouchCursorPos < 10) // or whatever condition
showPopup (this); // or whatever you want to do
}
return false;
}
private void showPopup (final EditText text)
{
Intent intent = new Intent (getContext(), Popup.class);
((Activity)getContext()).startActivity (intent);
}
}
SOLUTION 2
This one is actually simpler and, I think, is better - fewer side effects.
Here, the trick is to let EditText do all its click processing and then override it asynchronously. The gist is: wait for the touch to "let go" - MotionEvent.ACTION_UP - and then instead of doing your action right then, post a Runnable to the event queue and do your action there.
The whole code:
public class ClickText extends EditText implements OnTouchListener
{
public ClickText (Context context, AttributeSet attrs)
{
super (context, attrs);
setOnTouchListener (this);
}
#Override
public boolean onTouch (View v, MotionEvent event)
{
switch (event.getActionMasked())
{
case MotionEvent.ACTION_UP:
{
post (new Runnable ()
{
// Do this asynch so that EditText can finish setting the selectino.
#Override
public void run()
{
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
// If selStart is different than selEnd, user has highlighed an area of
// text; I chose to ignore the click when this happens.
if (selStart == selEnd)
if (selStart >= 0 && selStart < 10) // or whatever range you want
showPopup (this);
}
});
break;
}
}
return false;
}
private void showPopup (final EditText text)
{
Intent intent = new Intent (getContext(), Popup.class);
((Activity)getContext()).startActivity (intent);
}
}
use this below code snippet
this.editText.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//dialogue popup
}
return false;
}
});
I have implemented a custom dialog for my application. I want to implement that when the user clicks outside the dialog, the dialog will be dismissed.
What do I have to do for this?
You can use dialog.setCanceledOnTouchOutside(true); which will close the dialog if you touch outside of the dialog.
Something like,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
Or if your Dialog in non-model then,
1 - Set the flag-FLAG_NOT_TOUCH_MODAL for your dialog's window attribute
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Add another flag to windows properties,, FLAG_WATCH_OUTSIDE_TOUCH - this one is for dialog to receive touch event outside its visible region.
3 - Override onTouchEvent() of dialog and check for action type. if the action type is
'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform.
view plainprint?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
For more info look at How to dismiss a custom dialog based on touch points? and
How to dismiss your non-modal dialog, when touched outside dialog region
Simply use
dialog.setCanceledOnTouchOutside(true);
You can use this implementation of onTouchEvent. It prevent from reacting underneath activity to the touch event (as mentioned howettl).
#Override
public boolean onTouchEvent ( MotionEvent event ) {
// I only care if the event is an UP action
if ( event.getAction () == MotionEvent.ACTION_UP ) {
// create a rect for storing the window rect
Rect r = new Rect ( 0, 0, 0, 0 );
// retrieve the windows rect
this.getWindow ().getDecorView ().getHitRect ( r );
// check if the event position is inside the window rect
boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
// if the event is not inside then we can close the activity
if ( !intersects ) {
// close the activity
this.finish ();
// notify that we consumed this event
return true;
}
}
// let the system handle the event
return super.onTouchEvent ( event );
}
Source: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html
Or, if you're customizing the dialog using a theme defined in your style xml, put this line in your theme:
<item name="android:windowCloseOnTouchOutside">true</item>
This method should completely avoid activities below the grey area retrieving click events.
Remove this line if you have it:
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Put this on your activity created
getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
then override the touch event with this
#Override
public boolean onTouchEvent(MotionEvent ev)
{
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
displayYourDialog();
return false; // stop activity closing
}
}
// Touch events inside are fine.
return super.onTouchEvent(ev);
}
dialog.setCanceledOnTouchOutside(true);
to close dialog on touch outside.
And if you don't want to close on touch outside, use the code below:
dialog.setCanceledOnTouchOutside(false);
You can try this :-
AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);
or
alertDialog.setCancelable(true);
And if you have a AlterDialog.Builder Then you can try this:-
alertDialogBuilder.setCancelable(true);
This code is use for when use click on dialogbox that time hidesoftinput and when user click outer side of dialogbox that time both softinput and dialogbox are close.
dialog = new Dialog(act) {
#Override
public boolean onTouchEvent(MotionEvent event) {
// Tap anywhere to close dialog.
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) event.getX(),
(int) event.getY())) {
// You have clicked the grey area
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
dialog.dismiss();
// stop activity closing
} else {
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
}
return true;
}
};
Another solution, this code was taken from android source code of Window
You should just add these Two methods to your dialog source code.
#Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
hide();
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getWindow().getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
This solution doesnt have this problem :
This works great except that the activity underneath also reacts to the touch event. Is there some way to prevent this? – howettl
Following has worked for me:
myDialog.setCanceledOnTouchOutside(true);
Call dialog.setCancelable(false); from your activity/fragment.
You can make a background occupying all the screen size transparent and listen to the onClick event to dismiss it.
I tried some answers still I faced a problem like when I press outside the dialog dialog was hiding but a dimmed view was showing, and pressing again would go to the parent activity. But actually I wanted to go the parent activity after first click.
So what I did was
dialog.setOnCancelListener(this);
and changed my activity to implement DialogInterface.OnCancelListener with
#Override
public void onCancel(DialogInterface dialog) {
finish();
}
And boom, it worked.
Here is the code
dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent ev) {
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
dialog. getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
UiUtils.hideKeyboard2(getActivity());
return false; // stop activity closing
}
}
getActivity().dispatchTouchEvent(ev);
return false;
}
});
Try this one . you can hide the keyboard when you touch outside
I have a listview and when the user presses a button I want to gather the coordinates of the button and place an edittext that I inflate right over top of it on the screen. When the user clicks anywhere else on the screen the edittext will disappear and it will fire a method that uses the data the user entered into the box. How would I go about doing something like this? I would like something similar to QuickActions, but not quite as intrusive. Could someone point me in the direction of at least how to go about getting the button coordinates?
Ok, so here is how i've been able to achieve what i'm looking to do. Is it possible to dynamically place a PopupWindow without having to mess with adjusting margins etc.
public void showPopup(View view, View parentView, final int getId, String getLbs){
int pWidth = 100;
int pHeight = 80;
int vHeight = parentView.getHeight(); //The listview rows height.
int[] location = new int[2];
view.getLocationOnScreen(location);
final View pView = inflater.inflate(R.layout.list_popup, null, false);
final PopupWindow pw = new PopupWindow(pView, pWidth, pHeight, false);
pw.setTouchable(true);
pw.setFocusable(true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.showAtLocation(view, Gravity.NO_GRAVITY, location[0]-(pWidth/4), location[1]+vHeight);
final EditText input = (EditText)pView.findViewById(R.id.Input);
input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
Log.i("Focus", "Focus Changed");
if (hasFocus) {
//Shows the keyboard when the EditText is focused.
InputMethodManager inputMgr = (InputMethodManager)RecipeGrainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
inputMgr.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT);
}
}
});
input.setText("");
input.requestFocus();
Log.i("Input Has Focus", "" + input.hasFocus());
pw.setOnDismissListener(new OnDismissListener(){
#Override
public void onDismiss() {
changeWeight(getId, Double.parseDouble(input.getText().toString()));
Log.i("View Dismiss", "View Dismissed");
}
});
pw.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
Log.i("Background", "Back Touched");
pw.dismiss();
return true;
}
return false;
}
});
}
The pWidth and pHeight are the size of the PopupWindow I chose and the vHeight is the height of the main parent view that I collected from the onCreate context. Keep in mind this is not polished code. I still need to add a few things like animate in and out as well as a nice little arrow or something to show what the window is being associated with. The setBackgroundDrawable is very important and if you don't use it you won't be able to click outside the box to close it.
Right now, its weird. I have to click twice outside the box to close the window. The first click just seems to highlight my textbox and the second click actually closes it out. Anyone have any idea why that might be happening?
Messy, depending on your View hierarchy. The getLeft() method (along with getRight, getTop and getBottom) are all relative to the control's View parent. Take a look at getLocationOnScreen and see if it does what you want.