Android的PopupWindow的使用,根据点击位置显示弹窗
16lz
2021-01-25
Android的PopupWindow的使用,根据点击位置显示弹窗
在使用PopupWindow弹窗时遇见的一个问题,我这边列表中长按Item时需要显示一个弹窗,但是因为item的高度太大,导致弹窗出现的位置可能距离用户点击的坐标较大,所以需要对PopupWindow弹窗的位置做一些偏移,类似微信的聊天列表长按时出现的弹窗。解决方法来自于: http://www.cnblogs.com/popfisher/p/5608436.html.
基本使用
首先是初始化PopupWindow设置一些参数:
/** * 创建popupWindow弹窗 * * @param context * @param anchor 用于弹出PopupWindow的View * @param x 点击坐标到屏幕左边的距离 * @param y 点击坐标到屏幕上边的距离 * @param listener popupWindow中的点击事件接口 */ public PopupWindow createPopupWindow(Context context, View anchor, int x, int y, OnPopupClickListener listener) { // 自定义的布局View View view = LayoutInflater.from(context) .inflate(R.layout.popup_item_active, null, false); view.findViewById(R.id.tv_update).setOnClickListener(v -> listener.onPopupClick(v.getId())); view.findViewById(R.id.tv_delete).setOnClickListener(v -> listener.onPopupClick(v.getId())); PopupWindow popupWindow = new PopupWindow(); popupWindow.setContentView(view); popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setWidth(dip2px(context, 160)); popupWindow.setBackgroundDrawable(new ColorDrawable()); // 需要设置一个背景setOutsideTouchable(true)才会生效 popupWindow.setFocusable(true); // 防止点击事件穿透 popupWindow.setOutsideTouchable(true); // 设置点击外部时取消 int windowPos[] = PopupUtils.calculatePopWindowPos(anchor, view, x, y); int[] location = new int[2]; view.getLocationOnScreen(location); popupWindow.showAtLocation(anchor, Gravity.TOP | Gravity.START, windowPos[0], windowPos[1]); return popupWindow; } int x; int y; /** * 获取点击坐标的方法 * * @param view 点击的View */ public void clickXY(View view) { view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { x = (int) event.getRawX(); y = (int) event.getRawY(); return false; } }); }
上面的参数可以根据自己的需求添加,需要注意的是setFocusable(true)可以用来获取焦点,防止点击事件传递给后面的控件,这样在点击外部时则会取消弹窗,而不是响应后面按钮的点击事件。下面的方法是用来获取点击坐标的xy,在初始化点击View的地方添加即可。
设置PopupWindow弹出位置
显示Popup有两种方式:
1.依附于指定的View:showAsDropDown( )
2.相对父控件的做偏差显示:showAtLocation( )
这次使用的showAtLocation()方法。
/** * 计算popupWindow在长按view 的什么位置显示 * * @param anchorView 长按锚点的view * @param contentView 弹出框的布局View * @param touchX 锚点距离屏幕左边的距离 * @param touchY 锚点距离屏幕上方的距离 * @return popupWindow在长按view中的xy轴的偏移量 */ public static int[] calculatePopWindowPos(final View anchorView, final View contentView, int touchX, int touchY) { final int windowLoc[] = new int[2]; int offset = 144; // 获取屏幕的高宽 final int screenHeight = getScreenHeight(anchorView.getContext()); final int screenWidth = getScreenWidth(anchorView.getContext()); // 测量弹出框View的宽高 contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); final int popHeight = contentView.getMeasuredHeight(); final int popWidth = contentView.getMeasuredWidth(); // 判断需要向上弹出还是向下弹出显示 // 屏幕高度-触点距离左上角的高度 < popupWindow的高度 // 如果小于弹出框的高度那么说明下方空间不够显示 popupWindow,需要放在触点的上方显示 final boolean isNeedShowTop = (popHeight + touchY > screenHeight); // 判断需要向右边弹出还是向左边弹出显示 //判断触点右边的剩余空间是否够显示popupWindow 大于就说明够显示 final boolean isNeedShowRight = (touchX < (screenWidth / 2)); if (isNeedShowTop) { //如果在上方显示 则用 触点的距离上方的距离 - 弹框的高度 windowLoc[1] = touchY - popHeight; } else { //如果在下方显示 则用 触点的距离上方的距离 windowLoc[1] = touchY; } if (isNeedShowRight) { windowLoc[0] = touchX; } else { //显示在左边的话 那么弹出框的位置在触点左边出现,则是触点距离左边距离 - 弹出框的宽度 windowLoc[0] = touchX - popWidth - offset; } return windowLoc; }
因为弹窗设置的是默认在左上方显示,所以计算偏移也是按照这个计算的。
注意:offset是我根据弹窗出现的位置出现偏差增加的偏差值,这个可以根据自己的偏差进行调整,这里出现的偏差值也不知道是什么原因造成的。
用到的工具类中的方法:
/** * dp转px */ public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } /** * 获取屏幕高度(px) */ public static int getScreenHeight(Context context) { return context.getResources().getDisplayMetrics().heightPixels; } /** * 获取屏幕宽度(px) */ public static int getScreenWidth(Context context) { return context.getResources().getDisplayMetrics().widthPixels; }
当时查找了很多资料才找到了解决方法,所以在此记录一下。
更多相关文章
- Android实现系统级屏幕录制(下)
- android中像素单位dp、px、pt、sp转换
- 傳 Google Nexus Prime 將於10月發表
- Android获取屏幕分辨率及DisplayMetrics简介 和java获得屏幕宽度
- Android(安卓)播放视频(四)VideoView全屏视频播放
- Android(安卓)屏幕适配全攻略
- Android中List的padding设置
- ReactNative与Android中的屏幕适配
- Android的几种分辨率