ListView - 可点击(不是每个图标,而是整个视图)

时间:2015-01-27 10:03:17

标签: android listview android-listview onclicklistener

我尝试点击ListView。我使用一个不可点击的项目的适配器,每当用户触摸列表视图时,我想显示一个弹出窗口。我不想委托项目点击,因为我想要抓住ListView的完整区域,而不仅仅是所有项目的区域。我想要边界等等也做出反应。所以我很简单需要像listView.setOnItemClickListener()一样的东西,它不能用于ListView ......

我的适配器使其项目无法点击:

@Override
public boolean isEnabled(int pos)
{
    return false;
}

我想对ListView ...

上的所有点击做出反应

1)OnClickListener(抛出异常,不可用)

使用此方法将导致以下异常:

java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead

2)OnTouchListener(错误,至少是我的实现)

我使用它如下:

 lv.setClickable(false);
 lv.setFocusable(false);
 lv.setFocusableInTouchMode(false);
 lv.setOnTouchListener(new TouchClickListener()
    {
        @Override
        public void handleClick(View v)
        {
            onClick(v);
        }

        @Override
        public void handleLongClick(View v)
        {
            onLongClick(v);
        }
    });

我写了以下OnTouchListener

public abstract class TouchClickListener implements OnTouchListener
{
    private View view = null;
    private final Handler handler = new Handler();
    Runnable mLongPressed = new Runnable()
    {
        public void run()
        {
            handleLongClick(view);
        }
    };
    private static final int MAX_CLICK_DURATION = 200;
    private static final int MIN_LONG_CLICK_DURATION = 1000;
    private long startClickTime;
    private boolean moveDetected;

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        if (event.getAction() == MotionEvent.ACTION_MOVE)
        {
            moveDetected = true;
            cancelLongClick();
        }
        else if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            startClickTime = Calendar.getInstance().getTimeInMillis();
            moveDetected = false;

            cancelLongClick();

            view = v;
            handler.postDelayed(mLongPressed, MIN_LONG_CLICK_DURATION);
        }
        else if (event.getAction() == MotionEvent.ACTION_UP)
        {
            cancelLongClick();
            if (!moveDetected)
            {
                long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                if (clickDuration < MAX_CLICK_DURATION)
                    handleClick(v);
            }
        }
        else if (event.getAction() == MotionEvent.ACTION_CANCEL)
        {
            cancelLongClick();
        }
        return false;
    }

    private void cancelLongClick()
    {
        handler.removeCallbacks(mLongPressed);
        view = null;
    }

    public abstract void handleClick(View v);

    public abstract void handleLongClick(View v);
}

这很有效,但它很有问题......就像10个触摸中只有2个或3个被正确识别一样......似乎无法将点击与滑动区分开来......

1 个答案:

答案 0 :(得分:0)

关注OnTouchListener工作......

但是,它的常数有什么好的值?我选择的那些似乎工作......但可能有更好的解决方案甚至更好...

public abstract class TouchClickListener implements OnTouchListener
{
    private View view = null;
    private final Handler handler = new Handler();
    Runnable mLongPressed = new Runnable()
    {
        public void run()
        {
            handleLongClick(view);
        }
    };
    private static final int MAX_CLICK_DURATION = 200;
    private static final int MIN_LONG_CLICK_DURATION = 1000;
    private static final int MAX_TOUCH_DISTANCE_IN_DP = 10;
    private long startClickTime;
    private boolean moveDetected;

    private float startX;
    private float startY;

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        if (event.getAction() == MotionEvent.ACTION_MOVE)
        {
            moveDetected = true;
            cancelLongClick();
        }
        else if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            startX = event.getX();
            startY = event.getY();

            startClickTime = Calendar.getInstance().getTimeInMillis();
            moveDetected = false;

            cancelLongClick();

            view = v;
            handler.postDelayed(mLongPressed, MIN_LONG_CLICK_DURATION);
        }
        else if (event.getAction() == MotionEvent.ACTION_UP)
        {
            float endX = event.getX();
            float endY = event.getY();

            cancelLongClick();

            int maxTouchDistance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MAX_TOUCH_DISTANCE_IN_DP, v.getContext().getResources().getDisplayMetrics());
            if (!moveDetected || (Math.abs(startX - endX) < MAX_TOUCH_DISTANCE && Math.abs(startY - endY) < MAX_TOUCH_DISTANCE))
            //if (!moveDetected)
            {
                long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                if (clickDuration < MAX_CLICK_DURATION)
                    handleClick(v);
            }
        }
        else if (event.getAction() == MotionEvent.ACTION_CANCEL)
        {
            cancelLongClick();
        }
        return false;
    }

    private void cancelLongClick()
    {
        handler.removeCallbacks(mLongPressed);
        view = null;
    }

    public abstract void handleClick(View v);

    public abstract void handleLongClick(View v);
}