天天看點

仿微信實作ListView長按删除

簡言:仿微信做了一個對話清單,長按每個清單項彈出popupwindow進行删除操作,最終效果如下:

仿微信實作ListView長按删除

第一步:制作清單界面,可以是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中的控件(比如點選“删除”)設定背景,但并沒有生效,原因還在尋找中。。。。