Android - ListView using onItemClick and onTouch

2019-09-06 16:02发布

问题:

I try to implement something like a "drag and drop" for a ListView. The task is simple. I have a "side menu" where I put some objects in a list. They are all shown there. What I want is to drag and drop one of them to the screen.

I first tried to use the OnTouchListener which offers me the drag&drop functionality I seek. So I do something like

@Override
public boolean onTouch(View view, MotionEvent movEv) {
    if (movEv.getAction() == MotionEvent.ACTION_DOWN)
        // DRAG
    else if (movEv.getAction() == MotionEvent.ACTION_UP)
        // DROP
    return false;
}

The point is, this simply gives me the information of the MotionEvent like X and Y position. What I need is the know WHICH item was clicked. Something like the OnItemClickListener

The problem is, the OnItemClickListener only works if I "click" on an item, implying I don't move the finger. The moment I move and release it, the Listener doesn't recognize this as a click any more. Therefore using

 @Override
 public void onItemClick(AdapterView<?> parent, View view,
          int position, long id) {
   // I know which item was pressed -> position
 }

doesn't work.

Does anyone have any idea how to solve this? Can I somehow use the onItemClick already at the "onPressed" moment?

Thanks for any help!

回答1:

Instead of OnItemClickListener you can use pointToPosition method in your OnTouchListener. It can be something like this:

@Override
public boolean onTouch(View view, MotionEvent movEv) {
    if (movEv.getAction() == MotionEvent.ACTION_DOWN) {
        int itemPosition = listView.pointToPositon(movEv.getX(), movEv.getY());
        // DRAG
    }
    else if (movEv.getAction() == MotionEvent.ACTION_UP)
        // DROP
    return false;
}


回答2:

One solution would be to register a touch listener for every item in your adapter and save it's position so it's available in the listener.

Here's an example:

private class MyAdapter extends ArrayAdapter<String> implements View.OnTouchListener {

    public MyAdapter(Context context, int resource) {
        super(context, resource);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = super.getView(position, convertView, parent);
        v.setOnTouchListener(this);
        v.setTag(position);
        return v;
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        Integer position = (Integer) view.getTag();
        // Do something with item at "position"

        return false;
    }
}