简言:仿微信做了一个对话列表,长按每个列表项弹出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中的控件(比如点击“删除”)设置背景,但并没有生效,原因还在寻找中。。。。