How to detect double taps on ListView items in And

2019-07-01 15:46发布

问题:

i want to do some thing like instagram app when user double tab on photo it make like and while he just tab one time it open as full screen

回答1:

I think this answers to Your question as well. Check this link:

how to implement double click in android



回答2:

If you don't need to prevent single click to be fired, you can do much more simple:

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
    long currTime = System.currentTimeMillis();
    if (currTime - mLastClickTime < ViewConfiguration.getDoubleTapTimeout()) {
        onItemDoubleClick(adapterView, view, position, l);
    }
    mLastClickTime = currTime;
}

public void onItemDoubleClick(AdapterView<?> adapterView, View view, int position, long l) {
    ToastHelper.showToast("Double click");
}


回答3:

If you don't want to use a GestureListener for every list item or a GestureListener for the ListView which then needs to determine the item located under the double tap area you can use the following extension to the onItemClickListener.

This implementation waits to confirm a single click so it introduces single click latency.

private Object mClickedItem;
@Override
public void onItemClick(final AdapterView<?> adapter, final View view, final int index, final long id) {
    synchronized (DoubleClickAdapter.this) {        
        if(mClickedItem != null && mClickedItem.equals(getItem(index))) {
            mClickedItem = null;
            onDoubleClick(adapter, view, index, id);
            return;
        }
        mHandler.postDelayed(new Runnable() {

            @Override
            public void run() {
                synchronized (DoubleClickAdapter.this) {
                    if(mClickedItem != null) {
                        mClickedItem = null;
                        DoubleClickAdapter.super.onItemClick(adapter, view, index, id);
                    }
                }
            }
        }, ViewConfiguration.getDoubleTapTimeout());    
        mClickedItem = getItem(index);
    }
}

This implementation doesn't wait to confirm a single click, it fires a single click event on the first click of a double click:

private Object mClickedItem;
@Override
public void onItemClick(final AdapterView<?> adapter, final View view, final int index, final long id) {
    synchronized (DoubleClickAdapter.this) {        
        if(mClickedItem != null && mClickedItem.equals(getItem(index))) {
            mClickedItem = null;
            onDoubleClick(adapter, view, index, id);
            return;
        }
        mHandler.postDelayed(new Runnable() {

            @Override
            public void run() {
                synchronized (DoubleClickAdapter.this) {
                    mClickedItem = null;
                }
            }
        }, ViewConfiguration.getDoubleTapTimeout());    
        mClickedItem = getItem(index);
        DoubleClickAdapter.super.onItemClick(adapter, view, index, id);
    }
}


回答4:

I made this one based on Graeme's answer, it's works for me.

class VibinOnItemClickListener implements OnItemClickListener {

    private boolean nonDoubleClick = true;
    private long firstClickTime = 0L;
    private final int DOUBLE_CLICK_TIMEOUT = 200;//ViewConfiguration.getDoubleTapTimeout();

    @Override
    public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
        // @TODO check and catch the double click event
        synchronized(VibinOnItemClickListener.this) {
            if(firstClickTime == 0) {
                firstClickTime = SystemClock.elapsedRealtime();
                nonDoubleClick = true;
            } else {
                long deltaTime = SystemClock.elapsedRealtime() - firstClickTime;
                firstClickTime = 0;
                if(deltaTime < DOUBLE_CLICK_TIMEOUT) {
                    nonDoubleClick = false;
                    this.onItemDoubleClick(parent, view, position, id);
                    return;
                }
            }

            view.postDelayed(new Runnable() {

                @Override
                public void run() {
                    if(nonDoubleClick) {
                        // @TODO add your logic for single click event
                    }
                }

            }, DOUBLE_CLICK_TIMEOUT);
        }
    }

    public void onItemDoubleClick(AdapterView<?> parent, View view, int position, long id) {
        // @TODO override this method with your own logic
    }
}


回答5:

You can use the code below (lvData is a ListView variable):

int previousPosition=-1;
int count=0;
long previousMil=0;
private void addEvents() {
    lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if(previousPosition==position)
            {
                count++;
                if(count==2 && System.currentTimeMillis()-previousMil<=1000)
                {
                    Toast.makeText(MainActivity.this,"Double tap at"+position,Toast.LENGTH_SHORT).show();
                    count=1;
                }
            }
            else
            {
                previousPosition=position;
                count=1;
                previousMil=System.currentTimeMillis();
            }
        }
    });
}


回答6:

if ()//add this block

else if(count>=3){previousMil2=System.currentTimeMillis(); 

you can not change click another row thne click selected row.This code prevent click another view then you want to click row.

then change if control

if(count>=2 && (System.currentTimeMillis()-previousMil<=1000 ||System.currentTimeMillis()-previousMil2<=1000) )


回答7:

Using @Graeme's answer I came up with this: DoubleTapListViewItem.class:

import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AdapterView;
import android.widget.ListView;

import com.badoo.mobile.util.WeakHandler; //or any other handler
public class DoubleTapListViewItem {
    private Object mClickedItem;
    private WeakHandler handler;
    private ListView listView;
    private DoubleTapListViewItemInterface doubleTapInterface;

    public DoubleTapListViewItem(final AdapterView<?> parent, final View view, final int position, final long id, final WeakHandler handler, final ListView listView, final DoubleTapListViewItemInterface doubleTap){
        if(handler == null)
            throw new NullPointerException("handler must not be null");
        this.handler = handler;

        if(listView == null)
            throw new NullPointerException("listView must not be null.");
        this.listView = listView;

        if(doubleTap == null)
            throw new NullPointerException("doubleTap must not be null. The calling class should implement DoubleTapListViewItemInterface.java");
        doubleTapInterface = doubleTap;

        onItemTouch(parent,view,position,id);
    }

    public void onItemTouch(final AdapterView<?> parent, final View view, final int position, final long id){
        synchronized (listView){
            if(mClickedItem != null && mClickedItem.equals(parent.getItemAtPosition(position))) {
                mClickedItem = null;
                doubleTapInterface.onItemDoubleClick(parent, view, position, id); //double tap action
                return;
            }
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    synchronized (listView) {
                        if(mClickedItem != null) {
                            mClickedItem = null;
                            doubleTapInterface.onItemClick(parent, view, position, id);  //single tap
                        }
                    }
                }
            }, ViewConfiguration.getDoubleTapTimeout());
            mClickedItem = parent.getItemAtPosition(position);
        }
    }
}

The DoubleTapListViewItemInterface:

import android.view.View;
import android.widget.AdapterView;

public interface DoubleTapListViewItemInterface {
    void onItemClick(AdapterView<?> parent, View view, int position, long id);
    void onItemDoubleClick(AdapterView<?> parent, View view, int position, long id);
}

And to add the feature to and activity (or a fragment):

 public class ExampleActivity extends AppCompatActivity implements DoubleTapListViewItemInterface {

    @BindView(R.id.listViewLayout) ListView listView; //ButterKnife
    private DoubleTapListViewItem doubleTapListViewItem;
    private Adapter listViewAdapter;
    private WeakHandler mainHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);
        ButterKnife.bind(this);
        mainHandler = new WeakHandler();

        //get data, pass to the adapter and call listView.setAdapter(listViewAdapter);
    }

    @Override
    protected void onDestroy(){
        mainHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }

    @OnItemClick(R.id.listViewLayout) //ButterKnife
    public void onItemClickListInstance(final AdapterView<?> parent, final View view, final int position, final long id){
        if(doubleTapListViewItem == null)
            doubleTapListViewItem = new DoubleTapListViewItem(parent, view, position, id, mainHandler, listView,this);
        else
            doubleTapListViewItem.onItemTouch(parent, view, position, id);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id){
        Toast.makeText(getActivityFromWeakReference(),"single tap detected",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onItemDoubleClick(AdapterView<?> parent, View view, int position, long id){
        Toast.makeText(getActivityFromWeakReference(),"double tap detected",Toast.LENGTH_SHORT).show();
    }
}