Android Nougat PopupWindow showAsDropDown () Gravity не работает

У меня есть этот код.

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

И он отлично работает на версии Android ‹Android Nougat. Но в Android Nougat всплывающее окно отображается вверху экрана, а не относительно представления привязки.


person Jimson    schedule 24.09.2016    source источник


Ответы (6)


Кажется ошибка в android 7.0. Но вы можете решить это совместимым способом.

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 исправит эту ошибку в будущей сборке. И есть последний обходной путь. При создании попа нужно указать высоту.

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

Запустите pop, как указано выше, и вы можете использовать только popUp.showAsDropDown (anchorView), чтобы показать это всплывающее окно. Таким образом, вы можете игнорировать версию Android API.

person Liang Steve    schedule 28.09.2016
comment
Он работает только в api 24, а не в 25. Пожалуйста, предоставьте, если кто-нибудь знает ответ на эту проблему. - person Ganesh Krishnamoorthy; 22.10.2016
comment
Я задал вопрос специально для API 25: stackoverflow.com/questions/41973893/ - person Kim Montano; 01.02.2017

7.0 и 7.1 для достижения разных, поэтому разбираться отдельно.

Следующий метод, который я тестировал на виртуальной машине (7.0 и 7.1), без проблем.

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);
        }
    }
person x1876631    schedule 09.05.2017
comment
Ошибка все еще существует в Oreo, по крайней мере, в эмуляторах. Я бы рекомендовал изменить проверку Build.VERSION.SDK_INT на ›= 25 - person katie; 11.07.2018

Похоже, эта проблема появляется только в Android 7.0 (API 24). В 7.1.1 (API 25) все в порядке на тех же устройствах. После некоторых исследований выяснилось, что проблема вызвана popUp.update(), как это уже упоминалось Марилией. Но если вы просто удалите popUp.update(), всплывающее окно не появится в версиях до API 24. Чтобы избежать этого, единственный способ сейчас - использовать проверку версии и не использовать метод update() только на устройствах с API 24. Вот решение, которое сработало для меня:

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

Протестировал его на разных устройствах и API, и он хорошо работает везде, от API 18 до API 25.

person Volodymyr Buberenko    schedule 25.12.2016
comment
Пожалуйста, разместите полный код. У меня возникли проблемы с API 25, когда я создал аналогичное исправление: stackoverflow.com/questions/41973893/ - person Kim Montano; 01.02.2017

Вам действительно нужно это popUp.update(); в вашем коде? У меня была аналогичная проблема, в моем случае мне не понадобился popUp.update();, и его удаление заставило всплывающее окно гравитации вести себя так, как ожидалось.

Кроме того, это, скорее всего, связанная проблема, о которой сообщалось о PopupWindow.showAtLocation():

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

person Marilia    schedule 29.10.2016

Этот код работал у меня. Пожалуйста, попробуйте

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

}
person NhatVM    schedule 08.04.2019

В Android API 29 я исправил, заменив ширину и высоту всплывающего окна на WRAP_CONTENT. Как в моем коде в 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)
        }
    }

И нажмите кнопку следующим образом:

displayPopupBtn.setOnClickListener { view ->
            if (popUp != null) {
                if (popUp.isShowing) {
                    popUp.dismiss()
                } else {
                    popUp.showAsDropDown(view)
                }
            }
        }
person Kalu Khan Luhar    schedule 20.02.2020