Showing a delete button on swipe in a listview for Android

Andy picture Andy · Oct 3, 2012 · Viewed 23.1k times · Source

Expanding on another Stackoverflow question, I've implemented some gesture detection code so that I can detect when a row in my listview (which is in a FrameLayout) has been swiped. I followed the question/answer by Damian here about how to get the individual row/view from the adapter. How to get location (on screen) of row in listview

I have code in my onFling that gets the view for the row, and tries to make a delete button that is set as invisible in my xml layout to visible. However, this doesn't happen. I was wondering how I make a button visible in a listview on a swipe?

class MyGestureDetector extends SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        try {

            if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                int itemId = MyClass.this.lv.pointToPosition(
                        (int) e1.getX(), (int) e1.getY());

                Log.v("item id", String.valueOf(itemId));
                View v = MyClass.this.adapter
                        .getViewOnScreen(itemId);
                Button delete = (Button) v.findViewById(R.id.button_delete);

                delete.setVisibility(View.VISIBLE);
                //MyClass.this.adapter.notifyDataSetChanged();


            }

        } catch (Exception e) {
            // nothing
        }
        return false;
    }
}

My list adapter code is the same as the referenced question.

Edit: I tried using getChildAt() on the listview to get the row's view, and this works when there is one screen or less of items, but when there's more than the wrong view is returned and therefore the wrong delete button becomes visible.

Edit 2: I used the answer on the question here to get it to work:

Answer

Heskja picture Heskja · Oct 4, 2012

I implemented something like this in my app once. The way I did it:

public class MyGestureDetector extends SimpleOnGestureListener {
    private ListView list;

    public MyGestureDetector(ListView list) {
        this.list = list;
    }

    //CONDITIONS ARE TYPICALLY VELOCITY OR DISTANCE    
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (INSERT_CONDITIONS_HERE)
            if (showDeleteButton(e1))
                return true;
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    private boolean showDeleteButton(MotionEvent e1) {
        int pos = list.pointToPosition((int)e1.getX(), (int)e1.getY());
        return showDeleteButton(pos);
    }

    private boolean showDeleteButton(int pos) {
        View child = list.getChildAt(pos);
        if (child != null){
            Button delete = (Button) child.findViewById(R.id.delete_button_id);
            if (delete != null)
                if (delete.getVisibility() == View.INVISIBLE)
                    delete.setVisibility(View.VISIBLE);
                else
                    delete.setVisibility(View.INVISIBLE);
            return true;
        }
        return false;
    }
}

This worked for me, hope you'll get it to work or that it at least gives you some hint.