【问题标题】:Android Nougat PopupWindow showAsDropDown(...) Gravity not workingAndroid Nougat PopupWindow showAsDropDown(...) 重力不起作用
【发布时间】:2017-02-02 01:00:13
【问题描述】:

我有这个代码。

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 popupwindow android-7.0-nougat


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      这段代码对我有用。请尝试一下

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

      【讨论】:

        【解决方案3】:

        这似乎是 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 将在未来的版本中修复此错误。还有一个最终的解决方法。创建pop时需要给出高度。

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

        如上初始化pop,只能使用 popUp.showAsDropDown(anchorView) 显示此弹出窗口。这样就可以忽略Android API的版本了。

        【讨论】:

        【解决方案4】:

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

        【讨论】:

        • Oreo 上仍然存在该错误,至少在模拟器上是这样。我建议将 Build.VERSION.SDK_INT 检查更改为 >=25
        【解决方案5】:

        看起来这个问题只出现在 Android 7.0 (API 24) 中。在 7.1.1 (API 25) 中,在同一设备上一切正常。经过一些研究确定由popUp.update()引起的问题,就像Marilia已经提到的那样。但是如果你只是删除popUp.update(),弹出窗口将不会出现在 API 24 之前的版本中。为了避免这种情况,现在唯一的方法是使用版本检查并且不要仅在具有 API 的设备上使用update() 方法24. 这是对我有用的解决方案:

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

        在不同的设备和 API 上对其进行了测试,从 API 18 到 API 25 都可以正常工作。

        【讨论】:

        【解决方案6】:

        您的代码中真的需要popUp.update(); 吗?我遇到了类似的问题,在我的情况下,我不需要 popUp.update(); 并且删除它会使弹出重力按预期运行。

        另外,这很可能是一个相关问题,据报道PopupWindow.showAtLocation()

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-30
          • 2013-09-01
          • 2021-05-05
          • 1970-01-01
          • 2012-07-10
          • 1970-01-01
          相关资源
          最近更新 更多