自定义View —— 可删除 item 的 ListView (事件分发)

本文所用源码:https://github.com/HeXiaosa/ItemDeletableListView
本文由看这篇文章 https://blog.csdn.net/lmj623565791/article/details/22961279 以及结合 Andorid 开发艺术探索而来。

事件分发概述

Android 中触摸事件主要由 dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent 来控制。

触摸屏幕时,首先会触发 ViewGroup 的 dispathTouchEvent 方法,自定义 View 时,如果它在 ACTION_DOWN 返回 false, 则表示不再继续向下执行,事件到此结束,如果返回了 true, 则下次继续执行 dispatchTouchEvent 方法,返回 super.dispatchTouchEvent(ev) 则会执行 onInterceptTouchEvent/onTouchEvent.

View 是没有 onInterceptTouchEvent 方法的,因为事件传递到 View 之后是一定交给自己处理了。ViewGroup 的 onInterceptTouchEvent 方法 返回 true 表示 要拦截事件,给自己处理,返回 false 表示不拦截,传递给子 View 处理,执行子 View 的 dispatchTouchEvent 方法。

执行到 onTouchEvent 方法,返回 true 表示不再给它的 ViewGroup 处理,自己处理完就结束,返回 false 表示自己可以做一些操作,再执行它的 ViewGroup 的 onTouchEvent 方法。

可删除 item 的 ListView 思路

理解上面的描述之后,就可以结合上面文章中的例子来自己动手实现一个

  1. 从右向左滑动时,需要我们来处理(弹出PopupWindow),其余的交由 ListView 处理
  2. PopupWindow 是弹出状态时,再次触摸,则需要消失 PopupWindow, 事件到此结束

这里贴出 dispatchTouchEvent 和 onTouchEvent 的代码:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    Log.e("ItemDeletableListView", "dispatchTouchEvent action : " + ev.getAction() + ", handleTouchEvent:" + handleTouchEvent + ", isPopupShow:" + isPopupShow);
    Log.e("ItemDeletableListView", "dispatchTouchEvent mPwDelete.isShowing:" + mPwDelete.isShowing());
    if (!handleTouchEvent) {
        // 如果不需要处理触摸事件,那么久不做处理
        return super.dispatchTouchEvent(ev);
    }
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (isPopupShow) {
                // 已经展示了 popup 的话,再次触发 down 事件,则消失,并不再分发事件
                mPwDelete.dismiss();
                isPopupShow = false;
                return false;
            }
            downX = ev.getX();
            downY = ev.getY();
            downPosition = pointToPosition(((int) downX), ((int) downY));
            break;
        case MotionEvent.ACTION_MOVE:
            if (isPopupShow) {
                // 如果 move 过程中展示了 popupwindow, 那么不再分发事件
                return false;
            }
            x = ev.getX();
            y = ev.getY();
            if (downX-x > touchSlop && downX-x > Math.abs(downY-y)) {
                isSliding = true;
            } else {
                isSliding = false;
            }
            break;
        case MotionEvent.ACTION_UP:
            isSliding = false;
            break;
    }
    return super.dispatchTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Log.e("ItemDeletableListView", "onTouchEvent action : " + ev.getAction() + ", isSliding:" + isSliding + ", downPosition:" + downPosition);
    switch (ev.getAction()) {
        case MotionEvent.ACTION_MOVE:
            if (isSliding) {
                View child = getChildAt(downPosition);
                if (child == null) {
                    return super.onTouchEvent(ev);
                }
                isPopupShow = true;
                int x = getWidth()/2+mPwDelete.getWidth()/2;
                int y = child.getTop()+child.getHeight()/2;
                Log.e("TAG", "popup x:" + x + ", y:" + y);
                mPwDelete.showAtLocation(child, Gravity.TOP | Gravity.LEFT, x, y);
                mPwDelete.update();
                mTvDelete.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mDeleteItemListener.deleteItem(downPosition);
                        mPwDelete.dismiss();
                        isPopupShow = false;
                    }
                });
            }
            break;
        case MotionEvent.ACTION_UP:
            break;
    }
    return super.onTouchEvent(ev);
}

你可能感兴趣的:(Android)