简体   繁体   中英

Make android listview clickable while it is scrolling

Is there a way to make a ListView 's onItemClickListener react to touches even if the ListView is currently scrolling?

The default behavior of a scrolling ListView seems to be to do nothing more than to stop scrolling upon a touch.

The reason why I want it to be clickable while scrolling is: I have a ListView that is permanently scrolling automatically and that should allow interactions anwyway. The automatic scrolling is achieved like this:

scrollThread = new Thread() {
    public void run() {
        listView.post(new Runnable() {
            @Override
            public void run() {
                listView.smoothScrollBy(5, 0);
            }
        });
        try {Thread.sleep(100);}
        catch (InterruptedException ignore) {}
    }
}

The ListView's onTouchListener can be triggered even while this Thread is running. I am returning false in onTouch so as not to consume the touch event. But the onItemClickListener can only be triggered if I stop the scrolling first by interrupting the Thread.

Is manually forwarding the ListView's onTouch events the only way to circumvent this? If so, what is the best way to detect the item "below" an onTouch event?

I found out that manually forwarding the touch works quite well. I removed the default onItemClickListener and adapted some custom child view click detection code from Jake Wharton's SwipeDismissListViewTouchListener in my onTouch method as seen below.

It would still be interesting to know whether there is a simple way to make scrolling listviews register item clicks via the default onItemClickListener.

public boolean onTouch(View v, MotionEvent event)
{
    detectItemClick((ListView)v, event);
    // ...
}

private float mDownX;
private float mDownY;
private boolean isClick;

private void detectItemClick(ListView listView, MotionEvent event)
{
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            mDownX = event.getX();
            mDownY = event.getY();
            isClick = true;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            if (isClick) {
                // Find the item view that was touched (perform a hit test)
                Rect rect = new Rect();
                int childCount = listView.getChildCount();
                int[] listViewCoords = new int[2];
                listView.getLocationOnScreen(listViewCoords);
                int x = (int) event.getRawX() - listViewCoords[0];
                int y = (int) event.getRawY() - listViewCoords[1];
                View child;
                for (int i = 0; i < childCount; i++) {
                    child = listView.getChildAt(i);
                    if (child == null) return;
                    child.getHitRect(rect);
                    if (rect.contains(x, y)) {
                        int position = listView.getPositionForView(child);
                        onItemClick(listView, child, position, 0);
                        break;
                    }
                }
            }
            break;
        case MotionEvent.ACTION_MOVE:
            final float SCROLL_THRESHOLD = 10;
            if (isClick && (Math.abs(mDownX - event.getX()) > SCROLL_THRESHOLD
                   || Math.abs(mDownY - event.getY()) > SCROLL_THRESHOLD)) {
                isClick = false;
            }
            break;
        default:
            break;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM