简言:仿微信做了一个对话列表,长按每个列表项弹出popupwindow进行删除操作,最终效果如下:
第一步:制作列表界面,可以是ListView,也可以是RecyclerView,布局大家可以自己设计,本文采用的是ListView
第二步:为ListView添加setOnItemLongClickListener,可以考虑用ButterKnife,在LongClick事件中,我们做两件事:1.被选中的Item背景加深;2.弹出PopupWindow
// 不使用butterKnife lvChat.setOnItemLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 返回true则执行完长按事件不会继续响应click事件,返回false则会产生冒泡,执行完longClick后响应click return true; } });
@OnItemLongClick(R.id.lv_chat) boolean itemLongClick(View view,int Position) { // 将当前item及其position放入全局变量 curItem = view; curPosition = Position; // 设置当前item的背景颜色 curItem.setBackgroundColor(Color.parseColor("#e9e9eb")); // 显示popupWindow showPopupWindow(); return true; }
第三步:popupWindow是如何显示的
下为popupWindow中布局的xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="14dp" android:paddingLeft="23dp" android:paddingRight="23dp" android:paddingTop="14dp"> <TextView android:id="@+id/tv_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:gravity="center" android:textColor="#000000" android:text="置顶" android:textSize="16sp" /> <TextView android:id="@+id/tv_mark" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:gravity="center" android:text="已读" android:textSize="16sp" android:textColor="#000000"/> <TextView android:id="@+id/tv_delete_chat" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="删除" android:textSize="16sp" android:textColor="#000000"/> </LinearLayout>
private void showPopupWindow() { // popupWindow中的布局 View view = LayoutInflater.from(this).inflate(R.layout.operate_chat, null); operateWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, true); // 只有绘制完后才能获取到正确的popupWindow的宽高 operateWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); operateWindow.setBackgroundDrawable(getResources().getDrawable(R.mipmap.border_shadow)); operateWindow.setTouchable(true); operateWindow.setOutsideTouchable(true); // 获取当前item在window中的坐标 int[] curPositionInWindow = new int[2]; curItem.getLocationInWindow(curPositionInWindow); // 每个item的高度 int itemHeight = curItem.getHeight(); // popupWindow的高度 final int operateWindowHeight = view.getMeasuredHeight(); int xOff = curItem.getWidth() * 6 / 11; int yOffDown = -itemHeight * 3 / 11; int yOffUp = -(itemHeight + operateWindowHeight) + itemHeight * 3 / 11; // 窗口的宽高 DisplayMetrics metric = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metric); int windowHeight = metric.heightPixels; // 判断popupWindow出现在上方还是下方,根据窗口高-item高坐标是否大于item高度加popupWindow高度,从而对应不同的y偏移量 boolean isShowUp = (windowHeight - curPositionInWindow[1]) < (itemHeight + operateWindowHeight); if (isShowUp) { operateWindow.showAsDropDown(curItem, xOff, yOffUp); } else { operateWindow.showAsDropDown(curItem, xOff, yOffDown); } // 对popupWindow的dismiss监听,关闭时将被选中item的颜色恢复 operateWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { curItem.setBackgroundColor(Color.parseColor("#ffffff")); } }); // popupWindow中控件的点击事件 TextView tvDelete = view.findViewById(R.id.tv_delete_chat); tvDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { adapter.remove(chatList.get(curPosition)); operateWindow.dismiss(); } }); }
总结:
1.功能的实现并不难,但是实现有很多种方法,比如dialog,自定义view等都可以,
2.实现的过程也有很多衍生问题,比如获取getLocationInWindow和getLocationOnScreen的区别,如何获取toolbar和statusbar的高度等
3.本文尝试在点击popupWindow中的控件(比如点击“删除”)设置背景,但并没有生效,原因还在寻找中。。。。