Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center a ListPopupWindow/Other views on Android horizontally?

I'm creating a ListPopupWindow like this:

final ListPopupWindow insidelistPopupWindow = new ListPopupWindow(view.getContext());
insidelistPopupWindow.setContentWidth(getResources().getDimensionPixelSize(R.dimen.popupNewWidth));
insidelistPopupWindow.setHeight(getResources().getDimensionPixelSize(R.dimen.size300dp));
insidelistPopupWindow.setVerticalOffset(getResources().getDimensionPixelSize(R.dimen.size0dp));
insidelistPopupWindow.setHorizontalOffset(getPoupHorizontalOffset());
//set adapter...
insidelistPopupWindow.setAnchorView(view);
insidelistPopupWindow.show();

I tried to do simple math

public int getPoupHorizontalOffset() {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    int height = displayMetrics.heightPixels;
    int width = displayMetrics.widthPixels;
    return getResources().getDimensionPixelSize(R.dimen.popupNewWidth) - width/2;
}

to center it horizontally. It worked on my phone but not on others, so I suspect something is wrong about my asumptions. But I also suspect there's a better way of solving this.

How do I simply center something horizontally programatically?

PS: the same ListPopupWindow but with different number of elements is getting placed on different positions on screen. Why this happens?

UPDATE:

Based on the answer below,

I tried

listPopupWindow.setAnchorView(view);

        listPopupWindow.setContentWidth(getResources().getDimensionPixelSize(R.dimen.popupNewWidth));
        listPopupWindow.setHeight(getResources().getDimensionPixelSize(R.dimen.size250dp));
        listPopupWindow.setVerticalOffset(getResources().getDimensionPixelSize(R.dimen.size50dp));
        listPopupWindow.setHorizontalOffset(listPopupWindowWidth(view, listPopupWindow));
        listPopupWindow.setPromptPosition(ListPopupWindow.POSITION_PROMPT_ABOVE);

and did

int listPopupWindowWidth(View view, ListPopupWindow listPopupWindow) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int screenWidth = displayMetrics.widthPixels;
        int horizontalOffset = (screenWidth / 2) - (getRelativeLeft(view) + listPopupWindow.getWidth() / 2);
        return horizontalOffset;
    }

private int getRelativeLeft(View view) {
        if (view.getParent() == view.getRootView()) {
            return view.getLeft();
        } else {
            return view.getLeft() + getRelativeLeft((View) view.getParent());
        }
    }

but my popup is slightly to the left, not exactly centered. My view is in landscape mode, does it have anything to do with it? I tried changing width by height but it didn't work

like image 900
Guerlando OCs Avatar asked Jul 17 '20 17:07

Guerlando OCs


1 Answers

By default, the ListPopupWindow gets horizontally aligned with the left position of the anchor view. So, we should align its left side by calculating the difference of the current center from the screen center:

int screenWidth = getScreenSize().x;
if (isLandscape()) {
     screenWidth += getNavigationBarHeight();
}

int horizontalOffset = (screenWidth / 2) - (getRelativeLeft(view) + insidelistPopupWindow.getWidth() / 2);

insidelistPopupWindow.setHorizontalOffset(horizontalOffset);

getRelativeLeft() helps us to find the real left position of the anchor view regarding the screen (not its parent ViewGroup).

private int getRelativeLeft(View view) {
    if (view.getParent() == view.getRootView()) {
        return view.getLeft();
    } else {
        return view.getLeft() + getRelativeLeft((View) view.getParent());
    }
}

And to get the screen size:

private Point getScreenSize() {
    Point point = new Point();
    WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    if (wm.getDefaultDisplay() != null) {
        wm.getDefaultDisplay().getSize(point);
    }
    return point;
}

private boolean isLandscape() {
    int orientation = getResources().getConfiguration().orientation;
    return (orientation == Configuration.ORIENTATION_LANDSCAPE);
}

In this way, it doesn't matter where is the anchor view horizontally and how it's wrapped in nested layouts, the ListPopupWindow always resides in the middle of the screen.

like image 76
aminography Avatar answered Oct 18 '22 19:10

aminography