if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { int dropLocation = UIUtils.dip2Px(1) + viewHeight+ screenLocation[1]; mPopupWindow.showAtLocation(this, Gravity.NO_GRAVITY, 0, dropLocation); } else { mPopupWindow.showAsDropDown(this, 0, UIUtils.dip2Px(1)); }
注意这个不应该 在
onWindowFocusChanged 获取以下的信息 因为在25 也会获取不到
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(!isFirst){ isFirst=true; getLocationOnScreen(screenLocation); viewHeight=getMeasuredHeight(); } if(changed){ isFirst=false; } }1是一条分割线 ,screenLocation是这个视图位置相对于屏幕的左上角 x,y ,viewHeight 就是视图的高
效果:
为什么
showAsDropDown 方法就不行呢
在断点调试的时候发现 在23和25findDropDownPosition(....) 方法是不一样的.
23.版本
private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff,
int yoff, int gravity) {
final int anchorHeight = anchor.getHeight();
final int anchorWidth = anchor.getWidth();
if (mOverlapAnchor) {
yoff -= anchorHeight;
}
anchor.getLocationInWindow(mDrawingLocation);
p.x = mDrawingLocation[0] + xoff;
p.y = mDrawingLocation[1] + anchorHeight + yoff;
final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
& Gravity.HORIZONTAL_GRAVITY_MASK;
if (hgrav == Gravity.RIGHT) {
// Flip the location to align the right sides of the popup and
// anchor instead of left.
p.x -= mPopupWidth - anchorWidth;
}
boolean onTop = false;
p.gravity = Gravity.LEFT | Gravity.TOP;
anchor.getLocationOnScreen(mScreenLocation);
final Rect displayFrame = new Rect();
anchor.getWindowVisibleDisplayFrame(displayFrame);
final int screenY = mScreenLocation[1] + anchorHeight + yoff;
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.
if (mAllowScrollingAnchorParent) {
final int scrollX = anchor.getScrollX();
final int scrollY = anchor.getScrollY();
final Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
scrollY + mPopupHeight + anchorHeight + 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] + anchorHeight + yoff;
// Preserve the gravity adjustment.
if (hgrav == Gravity.RIGHT) {
p.x -= mPopupWidth - anchorWidth;
}
// Determine whether there is more space above or below the anchor.
anchor.getLocationOnScreen(mScreenLocation);
onTop = (displayFrame.bottom - mScreenLocation[1] - anchorHeight - yoff) <
(mScreenLocation[1] - yoff - displayFrame.top);
if (onTop) {
p.gravity = Gravity.LEFT | Gravity.BOTTOM;
p.y = root.getHeight() - mDrawingLocation[1] + yoff;
} else {
p.y = mDrawingLocation[1] + anchorHeight + yoff;
}
}
if (mClipToScreen) {
final int displayFrameWidth = displayFrame.right - displayFrame.left;
final int right = p.x + p.width;
if (right > displayFrameWidth) {
p.x -= right - displayFrameWidth;
}
if (p.x < displayFrame.left) {
p.x = displayFrame.left;
p.width = Math.min(p.width, displayFrameWidth);
}
if (onTop) {
final int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
if (popupTop < 0) {
p.y += popupTop;
}
} else {
p.y = Math.max(p.y, displayFrame.top);
}
}
p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
return onTop;
}
25. 版本
private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
int xOffset, int yOffset, int width, int height, int gravity) {
final int anchorHeight = anchor.getHeight();
final int anchorWidth = anchor.getWidth();
if (mOverlapAnchor) {
yOffset -= anchorHeight;
}
// Initially, align to the bottom-left corner of the anchor plus offsets.
final int[] drawingLocation = mTmpDrawingLocation;
anchor.getLocationInWindow(drawingLocation);
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
final Rect displayFrame = new Rect();
anchor.getWindowVisibleDisplayFrame(displayFrame);
if (width == MATCH_PARENT) {
width = displayFrame.right - displayFrame.left;
}
if (height == MATCH_PARENT) {
height = displayFrame.bottom - displayFrame.top;
}
// Let the window manager know to align the top to y.
outParams.gravity = computeGravity();
outParams.width = width;
outParams.height = height;
// If we need to adjust for gravity RIGHT, align to the bottom-right
// corner of the anchor (still accounting for offsets).
final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
& Gravity.HORIZONTAL_GRAVITY_MASK;
if (hgrav == Gravity.RIGHT) {
outParams.x -= width - anchorWidth;
}
final int[] screenLocation = mTmpScreenLocation;
anchor.getLocationOnScreen(screenLocation);
// First, attempt to fit the popup vertically without resizing.
final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
displayFrame.bottom, false);
// Next, attempt to fit the popup horizontally without resizing.
final boolean fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
displayFrame.right, false);
// If the popup still doesn't fit, attempt to scroll the parent.
if (!fitsVertical || !fitsHorizontal) {
final int scrollX = anchor.getScrollX();
final int scrollY = anchor.getScrollY();
final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
scrollY + height + anchorHeight + yOffset);
if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
// Reset for the new anchor position.
anchor.getLocationInWindow(drawingLocation);
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
// Preserve the gravity adjustment.
if (hgrav == Gravity.RIGHT) {
outParams.x -= width - anchorWidth;
}
}
// Try to fit the popup again and allowing resizing.
tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
screenLocation[1], displayFrame.top, displayFrame.bottom, mClipToScreen);
tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
screenLocation[0], displayFrame.left, displayFrame.right, mClipToScreen);
}
// Return whether the popup's top edge is above the anchor's top edge.
return outParams.y < drawingLocation[1];
}
这个两个版本的方法都是通过outParams.y=screenLocation[1]+anchorHeight+yOffset 来确定其Popup...的位置.所以我也使用了这个方式.
25.版本的 findDropDownPosition(....)里面的tryFitVertical(...)方法使用outParam.y发生了改变
所以25 版本不管用. 网上说的是什么手机问题,不过是sdk 的更新而已.