簡言:仿微信做了一個對話清單,長按每個清單項彈出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中的控件(比如點選“删除”)設定背景,但并沒有生效,原因還在尋找中。。。。