32

I need to show PopupWindow under one Views shown on the screen.

How can I calculate coordinates of needed View and place PopupWindow under it? Code example are more than welcome. Thanks.

Jonik
  • 80,077
  • 70
  • 264
  • 372
Eugene
  • 59,186
  • 91
  • 226
  • 333

3 Answers3

122

Locating an already displayed view is fairly easy - here's what I use in my code:

public static Rect locateView(View v)
{
    int[] loc_int = new int[2];
    if (v == null) return null;
    try
    {
        v.getLocationOnScreen(loc_int);
    } catch (NullPointerException npe)
    {
        //Happens when the view doesn't exist on screen anymore.
        return null;
    }
    Rect location = new Rect();
    location.left = loc_int[0];
    location.top = loc_int[1];
    location.right = location.left + v.getWidth();
    location.bottom = location.top + v.getHeight();
    return location;
}

You could then use code similar to what Ernesta suggested to stick the popup in the relevant location:

popup.showAtLocation(parent, Gravity.TOP|Gravity.LEFT, location.left, location.bottom);

This would show the popup directly under the original view - no guarantee that there would be enough room to display the view though.

zeetoobiker
  • 2,789
  • 1
  • 18
  • 10
  • 2
    +1 for this awsome and useful piece of code. Sorry I can't do more than that ;) – S.Thiongane Mar 18 '14 at 23:48
  • +1 Just needed to add some things, first it might be better to use only Gravity.NO_GRAVITY, then also if you want to have a margin so that the Pop Up Window won't be on edge you can subtract (e.g. location.left - 50). Keep in mind that when using location.right you need to measure your pop up window width. For the popup window measurement go here http://stackoverflow.com/questions/15862052/get-the-measures-of-popup-window. Final code for window with margin: location.left - popUpWindowWidth - 50 – Kim Montano Feb 19 '16 at 11:02
  • 1
    Does this solution applies to the RTL layouts? If not what modifications are required to make it work with Right-To-Left configuration? – A.B. Jan 24 '17 at 10:15
  • @ A. B. You need to handle condition for RTL. The above reflects same for both layouts means RTL and LTR. – arshad shaikh Aug 09 '17 at 12:48
  • @zeetoobiker Your solution is working perfect! But I am using SwitcherView inside popup. So after swtiching the view it's changing popup's position. Any Idea? – GreenROBO Feb 16 '18 at 07:03
  • @zeetoobiker This is not working for me because I have A text view that is located in a nested linearlayout. Does anyone have suggestions about that? – Irfan Yaqub Mar 18 '22 at 07:09
  • popup.showAtLocation(parent, what this parent means. is the parentView of whole layout or this is the parent view of textView? – Irfan Yaqub Mar 18 '22 at 09:43
8

you have getLeft() and getBottom() to get the exact position of the view in the layout. You also have getWidth() and getHeight() to know the exact space occupied by the view. If you want to position your popup window below a view.

You setLeft() and setTop() methods of the view to position the new popup Window.

Yashwanth Kumar
  • 28,931
  • 15
  • 65
  • 69
2

To get size of the main application screen without stuff like title and notification bars, override the following method in the class generating the screen in question (sizes are measured in pixels):

@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
}

To get the bottom coordinate of the view under which you want to show the popup:

View upperView = ...
int coordinate = upperView.getBottom();

Now as long as height - coordinate is large enough for your popup view, you can simply place the popup like this:

PopupWindow popup = new PopupWindow();

Button button = new Button(this);
button.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        popup.showAtLocation(parent, Gravity.CENTER, 0, coordinate);
    }
});

Here, showAtLocation() takes the parent view as an argument together with gravity and location offsets.

  • This works only if `button` is in the middle of the screen. Even if I would set `offset` manually this won't work on different screen sizes. – Eugene Sep 20 '11 at 15:49
  • The `button` can be everywhere. – Eugene Sep 21 '11 at 10:03
  • Wait - so the solution I proposed shows the popup just below your button. If you put the button lower, the popup will appear lower, too. And since I imagine that the popup is taking the width of the entire screen, it does not really matter if the button is centered horizontally or not. Or am I missing something here? –  Sep 21 '11 at 10:19
  • Good one, View.getBottom(). But there was a minor problem in the code. I have added that change in the edit section – Shaista Naaz Dec 05 '12 at 12:02