Android Nougat PopupWindow showAsDropDown (...) Гравитация не работает

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

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

Ответы

Ответ 1

Кажется, ошибка в 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[];
     anchorView.getLocationInWindow(a);
     popUp.showAtLocation(((Activity) mContext).getWindow().getDecorView(), Gravity.NO_GRAVITY, 0 , a[1]+anchorView.getHeight());
    } else{
     popUp.showAsDropDown(anchorView);
}

popUp.update();

Google исправит эту ошибку в будущей сборке. И есть окончательное решение. Вам нужно указать высоту при создании pop.

PopupWindow popup = new PopupWindow (contentView, с, высота);

Инициализировать, как указано выше, и вы можете использовать popup.showAsDropDown(anchorView) показывает это всплывающее окно. Таким образом, вы можете игнорировать версию Android api.

Ответ 2

Похоже, эта проблема появляется только в Android 7.0 (API 24). В 7.1.1 (API 25) все работает на одних и тех же устройствах. После некоторых исследований выяснилось, что проблема, вызванная popUp.update(), как уже упоминалось Marilia. Но если вы просто удалите 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.

Ответ 3

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

Ответ 4

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

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

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