1.先看一下效果图
动图还不会上传,各位凑合着看吧,意思和微信的那个长按应该是一样的

2.上代码
public class TestActivity extends Activity implements View.OnLongClickListener, View.OnTouchListener { private Button mTopMBtn; private Button mBottomMBtn; private RelativeLayout mRelativeLayout; private int mWindowHeight; private int mParentHeight; private int mViewHeight; private int mTitleHeight; private int mDialogHeight; private int point_width; private Activity mActivity; private PopupWindow mPopupWindow; private View dialogView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_test); mActivity = this; initView(); dialogView = LayoutInflater.from(this).inflate(R.layout.location_pop,null,false); mPopupWindow = new PopupWindow(dialogView, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); mPopupWindow.setOutsideTouchable(true); getWindow().getDecorView().addOnAttachStateChangeListener(mOnAttachStateChangeListener); } private void initView() { mTopMBtn = (Button) findViewById(R.id.mBtn_top); mBottomMBtn = (Button) findViewById(R.id.mBtn_bottom); mRelativeLayout = (RelativeLayout) findViewById(R.id.mRel); //OnTouch事件 监听手指的位置 来具体的显示窗口 mTopMBtn.setOnTouchListener(this); mBottomMBtn.setOnTouchListener(this); mTopMBtn.setOnLongClickListener(this); mBottomMBtn.setOnLongClickListener(this); } @Override public boolean onLongClick(View v) { switch (v.getId()){ case R.id.mBtn_top: showPop(v); break; case R.id.mBtn_bottom: showPop(v); break; } return true; } /** * 显示pop * @param view */ private void showPop(View view){ if (dealLocation(view)){ mPopupWindow.showAsDropDown(view,point_width,-(mViewHeight+mDialogHeight)); }else { mPopupWindow.showAsDropDown(view,point_width,0); } } /** * 根据控件的位置和弹窗的高度控制弹窗的显示位置 * true 显示在上边 false 显示在下边 * @param view * @return */ private boolean dealLocation(View view){ int [] location = new int[2]; view.getLocationOnScreen(location); int height = location[1]; return height-mTitleHeight+mDialogHeight>mParentHeight; } /** * 获得整体高度 * @param activity * @return */ private int getWindowHeight(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.heightPixels; } /** * 获得单个view的高度 * * @param view * @return */ private int getViewHeight(View view) { int width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int height = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(width, height); return view.getMeasuredHeight(); } /** * 获得标题栏和状态栏的高度 * * @param activity * @param view --->父容器 * @return */ private int getTitleHeight(Activity activity, View view) { return getWindowHeight(activity) - getViewHeight(view); } View.OnAttachStateChangeListener mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { mWindowHeight = getWindowHeight(mActivity); mParentHeight = getViewHeight(mRelativeLayout); mViewHeight = getViewHeight(mTopMBtn); mTitleHeight = getTitleHeight(mActivity,mRelativeLayout); mDialogHeight = getViewHeight(dialogView); } @Override public void onViewDetachedFromWindow(View v) { } }; @Override public boolean onTouch(View v, MotionEvent event) { point_width = (int) event.getX(); return false; } }其实很简单,注释写的也挺详细的,理解了就很容易了