本段代碼實際是計算popupWindow相對母視窗內的位移值,即p.x,p.y的最終值 private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { //狀態列或titile欄的高度 final int anchorHeight = anchor.getHeight(); //狀態列或titile欄在視窗中的位置 anchor.getLocationInWindow(mDrawingLocation); p.x = mDrawingLocation[0] + xoff; p.y = mDrawingLocation[1] + anchorHeight + yoff; boolean onTop = false; p.gravity = Gravity.START | Gravity.TOP; //狀態列或titile欄在螢幕中的位置 anchor.getLocationOnScreen(mScreenLocation); //displayFrame最終視窗的可見大小,對service端的window而言,但在qmw中卻是實際的子視窗大小 final Rect displayFrame = new Rect(); anchor.getWindowVisibleDisplayFrame(displayFrame); //screenY是計算相對螢幕,popUpWindow的y位置 int screenY = mScreenLocation[1] + anchorHeight + yoff; //root指decore View,displayFrame.getWidth 和root.getWidth()基本一致 final View root = anchor.getRootView(); if (screenY + mPopupHeight > displayFrame.bottom || p.x + mPopupWidth - root.getWidth() > 0) { // if the drop down disappears at the bottom of the screen. we try to // scroll a parent scrollview or move the drop down back up on top of // the edit box //超過視窗高度了,使能scroolview if (mAllowScrollingAnchorParent) { int scrollX = anchor.getScrollX(); int scrollY = anchor.getScrollY(); Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff, scrollY + mPopupHeight + anchor.getHeight() + yoff); anchor.requestRectangleOnScreen(r, true); } // now we re-evaluate the space available, and decide from that // whether the pop-up will go above or below the anchor. //重新計算 anchor.getLocationInWindow(mDrawingLocation); p.x = mDrawingLocation[0] + xoff; p.y = mDrawingLocation[1] + anchor.getHeight() + yoff; // determine whether there is more space above or below the anchor anchor.getLocationOnScreen(mScreenLocation); //判斷popupwindow是否上下顛倒? onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) < (mScreenLocation[1] - yoff - displayFrame.top); if (onTop) { p.gravity = Gravity.START | Gravity.BOTTOM; p.y = root.getHeight() - mDrawingLocation[1] + yoff; } else { p.y = mDrawingLocation[1] + anchor.getHeight() + yoff; } } //mClipToScreen使視窗是clip到screen上而非母視窗(container) if (mClipToScreen) { final int displayFrameWidth = displayFrame.right - displayFrame.left; int right = p.x + p.width; if (right > displayFrameWidth) { p.x -= right - displayFrameWidth; } //qmw should change here if (p.x < displayFrame.left) { p.x = displayFrame.left; p.width = Math.min(p.width, displayFrameWidth); } if (onTop) { int popupTop = mScreenLocation[1] + yoff - mPopupHeight; if (popupTop < 0) { p.y += popupTop; } } else { //qmw should change here p.y = Math.max(p.y, displayFrame.top); } } p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL; return onTop; }