我尝试点击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个被正确识别一样......似乎无法将点击与滑动区分开来......
答案 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);
}