How to have my ListView catch onLongClick() (not onItemLongClick)

159 Views Asked by At

I have a ListView that is refreshed at a high rate (3 times per second).

I need to catch a long press on such a ListView (as well as on the parent layout); the ListView has it's height set to wrap_content.

I can catch the long click on the parent layout, but I wish the long click on any item to be handled by the parent layout.

OnItemLongClick does not work well due to the high refresh rate, I have tried the onLongClickListener to the ListView but the the long click is not fired.

The rows are set as non-clickable, not-focusable as well as all the items contained in the row.

The question is how to handle a long click anywhere in the ListView if the position / item does not matter?

1

There are 1 best solutions below

3
On

I faced similar issue (with clicks on ImageButtons) when I was updating progress of my downloads in a ListView.

The solution was to update the individual rows instead of calling adapter.notifyDataSetChanged() (as what I understand is it interferes with your click/touch listeners). So to do this I problem was to find the row accurately. I need two things for this:

  1. mapping of URL strings to my Transfer objects (mPathToTransfers),
  2. list of URLs (mPathKeys).

Here's some code from my adapter:

protected LinkedHashMap<String, BaseTransfer> mPathToTransfers;
protected List<String> mPathKeys;

@Override
public int getCount() {
    mPathKeys = new ArrayList<String>(mPathToTransfers.keySet());
    return mPathToTransfers.size();
}

@Override
public BaseTransfer getItem(int position) {
    return mPathToTransfers.get(mPathKeys.get(position));
}

/**
 * Update transfer (download) progress in ListView's specific row
*/
public void setItemTransferredSize(String path, long transferredSize, ListView lv) {
    if (mPathToTransfers.containsKey(path)) {
        BaseTransfer dItem = (BaseTransfer) mPathToTransfers.get(path);
        dItem.setTransferredSize(transferredSize);

        Holder holder = getViewHolderForTransfer(path, lv);
        if (holder != null)
            setTransferProgressUpdate(holder, dItem);
    }
}

/**
 * Use to get the View Holder of the row of the transfer
 *
 * @param path
 * @param lv
 * @return {@linkplain Holder} for row, if it is visible, null otherwise
 */
private Holder getViewHolderForTransfer(String path, ListView lv) {
    int rowIndex = mPathKeys.indexOf(path);
    if (lv.getFirstVisiblePosition() <= rowIndex && lv.getLastVisiblePosition() >= rowIndex)
        return (Holder) lv.getChildAt(rowIndex - lv.getFirstVisiblePosition()).getTag();
    else
        return null;
}

If you have ambiguities, ask in comments below (or in your question's comments). :)