Jimson
Jimson

Reputation: 211

Android Nougat PopupWindow showAsDropDown(...) Gravity not working

I have this code.

PopupWindow popUp = new PopupWindow();
popUp.setFocusable(true);
popUp.setOutsideTouchable(true);        
popUp.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
popUp.setHeight(600);

popUp.setContentView(anchorView);
popUp.showAsDropDown(anchorView);
popUp.update();

And its perfectly works on Android Version < Android Nougat. But in Android Nougat, the popup is being displayed at the top of the screen instead of relative to the anchor view.

Upvotes: 13

Views: 15293

Answers (6)

Kalu Khan Luhar
Kalu Khan Luhar

Reputation: 1074

In Android API 29, I fixed by replacing popup width and height as WRAP_CONTENT. As in my code in Kotlin.

private fun createSpinnerLikePopUp() {
        val inflater = context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val vw = inflater.inflate(R.layout.dialog_window, null, false)
            popUp = PopupWindow(context).apply {
            isFocusable = true
            width = WindowManager.LayoutParams.WRAP_CONTENT
            height = WindowManager.LayoutParams.WRAP_CONTENT
            contentView = vw
            setBackgroundDrawable(null)
        }
        vw!!.recyclerView.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = RecyclerAdapter(context, myArray)
        }
    }

And button click as follows:

displayPopupBtn.setOnClickListener { view ->
            if (popUp != null) {
                if (popUp.isShowing) {
                    popUp.dismiss()
                } else {
                    popUp.showAsDropDown(view)
                }
            }
        }

Upvotes: 0

NhatVM
NhatVM

Reputation: 2124

This code worked for me. Please try it

    protected void showSortPopup(View anchorView) {


    if (Build.VERSION.SDK_INT >= 25) {
        Rect rectf = new Rect();
        anchorView.getGlobalVisibleRect(rectf);
        int offsetY = (rectf.top + anchorView.getHeight());
        WindowManager wm = (WindowManager) Manager.getInstance().getCurrentActivity().getSystemService(Context.WINDOW_SERVICE);
        int screenHeight = wm.getDefaultDisplay().getHeight();
        mPopup.setHeight(screenHeight - offsetY);
    }
    mPopup.showAsDropDown(anchorView);

}

Upvotes: 0

Liang Steve
Liang Steve

Reputation: 184

It seems a bug in android 7.0. But you can solve it with a compatible way.

PopupWindow popUp = new PopupWindow();
popUp.setFocusable(true);
popUp.setOutsideTouchable(true);        
popUp.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
popUp.setHeight(600);

popUp.setContentView(anchorView);
  if (android.os.Build.VERSION.SDK_INT >=24) {
     int[] a = new int[2]; //getLocationInWindow required array of size 2
     anchorView.getLocationInWindow(a);
     popUp.showAtLocation(((Activity) mContext).getWindow().getDecorView(), Gravity.NO_GRAVITY, 0 , a[1]+anchorView.getHeight());
    } else{
     popUp.showAsDropDown(anchorView);
}

popUp.update();

Google will fix this bug in the future build. And there is a final workaround. You need give the height when creating pop.

PopupWindow popup = new PopupWindow(contentView, with, height);

Init pop as above, and you can only use popUp.showAsDropDown(anchorView) show this popup. In this way, you can ignore the version of the Android API.

Upvotes: 17

x1876631
x1876631

Reputation: 69

7.0 and 7.1 to achieve different, so to be dealt with separately.

The following method I tested in the virtual machine(7.0 and 7.1), no problem.

public void showFilterWindow(Context context, PopupWindow popupWindow,View showView, int xoff, int yoff) {
        if (Build.VERSION.SDK_INT < 24) {
            //7.0 The following system is used normally
            popupWindow.showAsDropDown(showView, xoff, yoff);
        } else {
            int[] location = new int[2];
            showView.getLocationOnScreen(location);
            int offsetY = location[1] + showView.getHeight() + yoff;
            if (Build.VERSION.SDK_INT == 25) {
                //【note!】Gets the screen height without the virtual key
                WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
                int screenHeight = wm.getDefaultDisplay().getHeight();
                /*
                 * PopupWindow height for match_parent,
                 * will occupy the entire screen, it needs to do special treatment in Android 7.1
                */
                popupWindow.setHeight(screenHeight - offsetY);
            }
            //Use showAtLocation to display pop-up windows
            popupWindow.showAtLocation(showView, Gravity.NO_GRAVITY, 0, offsetY);
        }
    }

Upvotes: 6

Volodymyr Buberenko
Volodymyr Buberenko

Reputation: 668

Looks like this problem appears only in Android 7.0 (API 24). In 7.1.1 (API 25) everything is OK on same devices. After some research defined that the problem caused by popUp.update(), like it is already mentioned by Marilia. But if you just remove popUp.update(), the popup won't appear in versions prior to API 24. In order to avoid this the only way now is to use version check and don't use update() method only on devices with API 24. Here is the solution, which worked for me:

if (Build.VERSION.SDK_INT != 24) {
   popup.update(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
}

Tested it on different devices and APIs and it works well everywhere from API 18 and up to API 25.

Upvotes: 2

Marilia
Marilia

Reputation: 1991

Do you really need that popUp.update(); in your code? I was having a similar problem, in my case I didn't need the popUp.update(); and removing it made the popup gravity behave as expected.

Also, this is most likely a related issue, reported about PopupWindow.showAtLocation():

https://code.google.com/p/android/issues/detail?id=221001

Upvotes: 1

Related Questions