OnTouchListener会阻止视觉反馈

时间:2015-07-26 14:38:27

标签: android android-listview expandablelistview ontouchlistener

我有一个ListView,它有一个OnItemClickListener。最重要的是,每一行(CardView)都有一个OnTouchListener,以实现滑动手势。

OnTouchListener对ACTION_DOWN,ACTION_CANCEL,ACTION_MOVE和ACTION_UP作出反应。我在ACTION_UP发生时使用performItemClick(),以便在需要时调用OnItemClickListener。

如果我在OnTouchListener中返回true,我通过ACTION_MOVE实现的滑动运动效果很好,单击该项也可以。 然而,视觉反馈为零。通常情况下,Lollipop会出现波纹或ICS背景会发生变化。

如果我返回False(意味着我不想拦截事件),那么就会有视觉反馈并且点击工作......但是我的OnTouchListener从不拦截任何ACTION_MOVE事件。这可以防止任何滑动。

我尝试了各种解决方案,例如使用v.setpressed()但它没有效果。

我很想知道如果我的OnTouchListener没有拦截事件,我将如何保留涟漪(或一般的视觉反馈)。

如果你很好奇,这是我的OnTouchListener。

private final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
    float mDownX;
    private int mSwipeSlop = -1;
    private boolean mItemPressed;
    private VelocityTracker mVelocityTracker = null;
    private HashMap<Long, Integer> mItemIdTopMap = new HashMap<>();

    @Override
    public boolean onTouch(final View v, MotionEvent event) {
        int index = event.getActionIndex();
        int pointerId = event.getPointerId(index);

        if (mSwipeSlop < 0) {
            mSwipeSlop = ViewConfiguration.get(getActivity())
                    .getScaledTouchSlop();
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (mItemPressed) {
                    // Multi-item swipes not handled
                    return false;
                }
                mItemPressed = true;
                mDownX = event.getX();
                if (mVelocityTracker == null) {
                    // Retrieve a new VelocityTracker object to watch the velocity of a motion.
                    mVelocityTracker = VelocityTracker.obtain();
                } else {
                    // Reset the velocity tracker back to its initial state.
                    mVelocityTracker.clear();
                }
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_CANCEL:
                v.setAlpha(1);
                v.setTranslationX(0);
                mItemPressed = false;
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                break;
            case MotionEvent.ACTION_MOVE: {
                mVelocityTracker.addMovement(event);
                float x = event.getX() + v.getTranslationX();
                float deltaX = x - mDownX;
                float deltaXAbs = Math.abs(deltaX);
                if (!mSwiping) {
                    if (deltaXAbs > mSwipeSlop) {
                        mSwiping = true;
                        getListView().requestDisallowInterceptTouchEvent(true);
                        mBackgroundContainer.showBackground(v.getTop(), v.getHeight());
                    }
                }
                if (mSwiping) {
                    v.setTranslationX((x - mDownX));
                    v.setAlpha(1 - deltaXAbs / v.getWidth());
                }
            }
            break;
            case MotionEvent.ACTION_UP: {
                // User let go - figure out whether to animate the view out, or back into place
                if (mSwiping) {
                    float x = event.getX() + v.getTranslationX();
                    float deltaX = x - mDownX;
                    float deltaXAbs = Math.abs(deltaX);
                    float fractionCovered;
                    float endX;
                    float endAlpha;
                    final boolean remove;
                    mVelocityTracker.computeCurrentVelocity(1000);
                    float velocityX = Math.abs(VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
                    if (velocityX > 700 || deltaXAbs > v.getWidth() / 4) {
                        // fixme
                        fractionCovered = deltaXAbs / v.getWidth();
                        endX = deltaX < 0 ? -v.getWidth() : v.getWidth();
                        endAlpha = 0;
                        remove = true;
                    } else {
                        // Not far enough - animate it back
                        fractionCovered = 1 - (deltaXAbs / v.getWidth());
                        endX = 0;
                        endAlpha = 1;
                        remove = false;
                    }
                    mVelocityTracker.clear();

                    int SWIPE_DURATION = 600;
                    long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION);
                    getListView().setEnabled(false);
                    v.animate().setDuration(duration).
                            alpha(endAlpha).translationX(endX).
                            withEndAction(new Runnable() { // fixme replace with AnimationListener
                                @Override
                                public void run() {
                                    // Restore animated values
                                    v.setAlpha(1);
                                    v.setTranslationX(0);
                                    if (remove) {
                                        animateRemoval(getListView(), v);
                                    } else {
                                        mBackgroundContainer.hideBackground();
                                        mSwiping = false;
                                        getListView().setEnabled(true);
                                    }
                                }
                            });
                } else {
                    int position = getListView().getPositionForView(v);
                    if (position != ListView.INVALID_POSITION)
                        getListView().performItemClick(v, position, getListView().getItemIdAtPosition(position));
                }
            }
            mItemPressed = false;
            break;
            default:
                return false;
        }
        return true;
    }

    private void animateRemoval(final ListView listview, View viewToRemove) {
        // irrelevant
    }
};

这是基于几年前Chet Haase的demo

我真的无法理解。帮助

谢谢!

2 个答案:

答案 0 :(得分:8)

对我来说,v.setPressed做了诀窍,其中v是接收触摸事件的视图。这意味着在ACTION_DOWN上我调用了v.setPressed(true)和在ACTION_UP上调用v.setPressed(false)

答案 1 :(得分:0)

我发现导致出现新片段的点击可以防止出现波纹。在点击中添加一个短暂的延迟解决了我的问题。就是这个

      columnViewHolder.rippleLayout.setOnClickListener((v) -> {

            dataManager.setProducts(id, response.getProducts());
            dataManager.setProductListPosition(id, position);
            dataManager.clearCurrentProductItem();
            Log.d(TAG, "product click " + product.toString());
            EventBus.getDefault().post(new ProductDetailEvent(id, product));
            tagManager.hubSpokeClick(product.getCode());

        });

不起作用,但确实如此:

           columnViewHolder.rippleLayout.setOnClickListener((v) -> {

                handler.postDelayed(() -> {
                    dataManager.setProducts(id, response.getProducts());
                    dataManager.setProductListPosition(id, position);
                    dataManager.clearCurrentProductItem();
                    Log.d(TAG, "product click " + product.toString());
                    EventBus.getDefault().post(new ProductDetailEvent(id, product));
                    tagManager.hubSpokeClick(product.getCode());
                }, 200l);
         });