天天看點

Android PopupWindow怎麼合理控制彈出位置(showAtLocation)

主要記錄PopupWindow自己計算彈出位置的方法

小編推薦

  自己開發app到上架應用市場需要經曆什麼?https://www.cnblogs.com/popfisher/p/14218431.html

說到PopupWindow,應該都會有種熟悉的感覺,使用起來也很簡單

// 一個自定義的布局,作為顯示的内容
Context context = null;  // 真實環境中要指派
int layoutId = 0;      // 布局ID
View contentView = LayoutInflater.from(context).inflate(layoutId, null);
      
final PopupWindow popupWindow = new PopupWindow(contentView,
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);

popupWindow.setTouchable(true);
// 如果不設定PopupWindow的背景,有些版本就會出現一個問題:無論是點選外部區域還是Back鍵都無法dismiss彈框
// 這裡單獨寫一篇文章來分析
popupWindow.setBackgroundDrawable(new ColorDrawable());
// 設定好參數之後再show
popupWindow.showAsDropDown(contentView);      

  

如果建立PopupWindow的時候沒有指定高寬,那麼showAsDropDown預設隻會向下彈出顯示,這種情況有個最明顯的缺點就是:彈視窗可能被螢幕截斷,顯示不全,是以需要使用到另外一個方法showAtLocation,這個的坐标是相對于整個螢幕的,是以需要我們自己計算位置。

如下圖所示,我們可以根據螢幕左上角的坐标A,螢幕高寬,點選View的左上角的坐标C,點選View的大小以及PopupWindow布局的大小計算出PopupWindow的顯示位置B

計算方法源碼如下:

/**
     * 計算出來的位置,y方向就在anchorView的上面和下面對齊顯示,x方向就是與螢幕右邊對齊顯示
     * 如果anchorView的位置有變化,就可以适當自己額外加入偏移來修正
     * @param anchorView  呼出window的view
     * @param contentView   window的内容布局
     * @return window顯示的左上角的xOff,yOff坐标
     */
    private static int[] calculatePopWindowPos(final View anchorView, final View contentView) {
        final int windowPos[] = new int[2];
        final int anchorLoc[] = new int[2];
     // 擷取錨點View在螢幕上的左上角坐标位置
        anchorView.getLocationOnScreen(anchorLoc);
        final int anchorHeight = anchorView.getHeight();
        // 擷取螢幕的高寬
        final int screenHeight = ScreenUtils.getScreenHeight(anchorView.getContext());
        final int screenWidth = ScreenUtils.getScreenWidth(anchorView.getContext());
        contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        // 計算contentView的高寬
        final int windowHeight = contentView.getMeasuredHeight();
        final int windowWidth = contentView.getMeasuredWidth();
        // 判斷需要向上彈出還是向下彈出顯示
        final boolean isNeedShowUp = (screenHeight - anchorLoc[1] - anchorHeight < windowHeight);
        if (isNeedShowUp) {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] - windowHeight;
        } else {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] + anchorHeight;
        }
        return windowPos;
    }      

接下來調用showAtLoaction顯示:

View windowContentViewRoot = 我們要設定給PopupWindow進行顯示的View
int windowPos[] = calculatePopWindowPos(view, windowContentViewRoot);
int xOff = 20;// 可以自己調整偏移
windowPos[0] -= xOff;
popupwindow.showAtLocation(view, Gravity.TOP | Gravity.START, windowPos[0], windowPos[1]);
// windowContentViewRoot是根布局View      

上面的例子隻是提供了一種計算方式,在實際開發中可以根據需求自己計算,比如anchorView在左邊的情況,在中間的情況,可以根據實際需求寫一個彈出位置能夠自适應的PopupWindow。

補充上擷取螢幕高寬的代碼ScreenUtils.java:

/**
     * 擷取螢幕高度(px)
     */
    public static int getScreenHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }
    /**
     * 擷取螢幕寬度(px)
     */
    public static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }      

Demo截圖展示:

看完覺得有用記得點選推薦支援一下,謝謝

Demo下載下傳位址:https://github.com/PopFisher/SmartPopupWindow

繼續閱讀