android - ListView 上的 SwipeListener 和 ListView 项目上的 ClickListener

标签 android android-listview swipe

这是我的 old question .不过这次我也提供了我的代码。

我有一个包含不同类型行的 ListView。该行可能包含文本、图像、视频或其他内容。如果我单击 ImageView(行内),我将转到另一个 Activity 以全屏显示图像,如果我单击视频(行内),我将转到另一个 Activity 以播放他的视频。

我已经在我的 ListView 上实现了从右到左滑动监听器。如果我从 ListView 中的空白区域开始 ListView 滑动,则滑动有效(下图中的第一行和第二行)。但是,如果我从 ListView 行的项目开始 ListView 滑动,则滑动不起作用(下图中的第三行和第四行)。如果我从 ImageView 和 Video 中删除点击事件,那么即使我从 ListView 行的项目开始滑动,滑动也会起作用,即在这种情况下,无论我在哪一行进行滑动,滑动都适用于整个 ListView。

enter image description here

我怎样才能摆脱这个问题?我认为如果我禁用 ListView 中所有项目的所有点击事件,就可以实现这一点。怎么能这样呢?还有其他办法吗?

我想同时在 ListView 上滑动并单击 ListView 的项目。

SwipeDetector.java - 用于检测 ListView 上的滑动

public class SwipeDetector implements View.OnTouchListener {

private SwipeListener swipeListener;
private ListView mListView;
private int hundred;
private boolean motionInterceptDisallowed = false;

public static enum Action {
    LR, // Left to right
    RL, // Right to left
    TB, // Top to bottom
    BT, // Bottom to top
    None // Action not found
}

private static final int HORIZONTAL_MIN_DISTANCE = 30; // The minimum
// distance for
// horizontal swipe
private static final int VERTICAL_MIN_DISTANCE = 80; // The minimum distance
// for vertical
// swipe
private float downX, downY, upX, upY; // Coordinates
private Action mSwipeDetected = Action.None; // Last action

public SwipeDetector(Context context, ListView listView) {
    hundred = (int) context.getResources().getDimension(R.dimen.hundred);
    mListView = listView;
}

public boolean swipeDetected() {
    return mSwipeDetected != Action.None;
}

public Action getAction() {
    return mSwipeDetected;
}

/**
 * Swipe detection
 */@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        {
            downX = event.getX();
            downY = event.getY();
            mSwipeDetected = Action.None;
            return false; // allow other events like Click to be processed
        }
        case MotionEvent.ACTION_MOVE:
        {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            float absX = Math.abs(deltaX);
            float absY = Math.abs(deltaY);

            if((absX >= (3 * absY)) && absX > HORIZONTAL_MIN_DISTANCE && mListView != null && !motionInterceptDisallowed) {
                mListView.requestDisallowInterceptTouchEvent(true);
                motionInterceptDisallowed = true;
            }

            if((absX >= (3 * absY)) && absX <= hundred) {
                if (deltaX > 0) {
                    mSwipeDetected = Action.RL;
                    swipeListener.onSwipe(MotionEvent.ACTION_MOVE, Action.RL, absX);
                }
            }


            return false;
        }
        case MotionEvent.ACTION_UP:
            swipeListener.onSwipe(MotionEvent.ACTION_UP, Action.BT, 0);
            if (mListView != null) {
                mListView.requestDisallowInterceptTouchEvent(false);
                motionInterceptDisallowed = false;
            }
            return false;
        case MotionEvent.ACTION_CANCEL:
            return true;
    }
    return false;
}

/**
 * Set chat send listener
 * @param listener
 */
public void setSwipeListener(SwipeListener listener) {
    swipeListener = listener;
}

public interface SwipeListener {
    void onSwipe(int event, Action action, float x);
}

}

这就是我在 ListView 上设置 SwipeDetector 的方式

final SwipeDetector swipeDetector = new SwipeDetector(SwipeActivity.this, mListView);
    swipeDetector.setSwipeListener(mSwipeListener);
    mListView.setOnTouchListener(swipeDetector);

我的 Activity 实现了 SwipeDetector.SwipeListener

下面重写了 onSwipe() 方法

@Override
public void onSwipe(int event, SwipeDetector.Action action, float x) {
    switch (event) {
            case MotionEvent.ACTION_MOVE:
                System.out.println("list move");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("list up");
                break;
        }
}

在我的适配器中,我在我的 TextView、ImageView 和 VideoView 上设置了 onClickListener()

holder.mTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            System.out.println("item textview click");
        }
    });

holder.mImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            System.out.println("item imageview click");
        }
    });

holder.mVideoView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            System.out.println("item videoview click");
        }
    });

当我从 ListView 的空白区域开始滑动时,ListView 的滑动监听器会捕获它。但是,当我从 TextView/ImageView/VideoView 开始滑动时,View 的 onClickListener 被触发,而不是父级(ListView 的)onTouchListener()。

我该如何实现?我希望当我点击 ListView 的项目时应该触发该项目的 onClick,当我在 ListView 的项目上滑动时应该触发 ListView 的 onSwipe。

最佳答案

listitemonClickListenerListSwipeListener 是不可能的,因为它在两者之间产生歧义触摸查看以考虑

您使用实现了 onTouchListenerOnSwipeTouchListener

OnSwipeTouchListener.java

import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                    }
                    result = true;
                } 
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom();
                        } else {
                            onSwipeTop();
                        }
                    }
                    result = true;

            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}

并在 listitem 上使用 OnSwipeTouchListener

  listitem.setOnTouchListener(new OnSwipeTouchListener() {

        public void onSwipeLeft() {
            //stuff to do list view left swipe 
            Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
        }


        public boolean onTouch(View v, MotionEvent event) {
            //stuff to do on list item click
            return gestureDetector.onTouchEvent(event);
        }
    });

}); //to get click events 

关于android - ListView 上的 SwipeListener 和 ListView 项目上的 ClickListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32866357/

相关文章:

android - ViewPager 中的滑动方向

android - 创建产品 flavor 的构建类型

android - ListView:如何等到它加载完毕?

java - Actionbarsherlock 和 searchview 不起作用。应用程序崩溃

jquery - 使用适用于 Android 的 jquerymobile 向左/向右滑动事件不起作用

ios - Swift Swipe 手势识别器使程序崩溃

android - OnRestart 与 OnResume - Android 生命周期问题

android - 此应用程序或其使用的库正在使用已弃用的 NSQuickDrawView。应用程序应该停止使用 QuickDraw 并转移到 Quartz

java - 在 ListView 中完整显示列表

android - 我们如何使用 Android 在平板电脑中滚动 ListView