Возвращая true
из onTouch
, вы потребляете событие касания, поэтому ваша кнопка даже не видит его.Причина, по которой больше не происходит сенсорных событий, заключается в том, что никакой View фактически не обработал событие down.
Так что вам нужно вернуть false
из onTouch
в ваш слушатель.(И надеюсь, что базовое представление продолжает возвращать true
, потому что, если кнопка View - в этом случае - возвращает false из своего onTouchEvent
, то больше никаких событий не будет отправлено вашему слушателю - для кнопки это нормально, но длядругие представления переопределяют onTouchEvent
вместо использования слушателя для большего контроля и надежности).
Что-то вроде следующего OnTouchListener
должно быть примерно правильным (это должен быть внутренний класс Activity, и donТакже не устанавливайте OnClickListener
, потому что он также будет вызываться!):
private abstract class LongTouchActionListener implements OnTouchListener {
/**
* Implement these methods in classes that extend this
*/
public abstract void onClick(View v);
public abstract void onLongTouchAction(View v);
/**
* The time before we count the current touch as
* a long touch
*/
public static final long LONG_TOUCH_TIME = 500;
/**
* The interval before calling another action when the
* users finger is held down
*/
public static final long LONG_TOUCH_ACTION_INTERVAL = 100;
/**
* The time the user first put their finger down
*/
private long mTouchDownTime;
/**
* The coordinates of the first touch
*/
private float mTouchDownX;
private float mTouchDownY;
/**
* The amount the users finger has to move in DIPs
* before we cancel the touch event
*/
public static final int TOUCH_MOVE_LIMIT_DP = 50;
/**
* TOUCH_MOVE_LIMIT_DP converted to pixels, and squared
*/
private float mTouchMoveLimitPxSq;
/**
* Is the current touch event a long touch event
*/
private boolean mIsLongTouch;
/**
* Is the current touch event a simple quick tap (click)
*/
private boolean mIsClick;
/**
* Handlers to post UI events
*/
private LongTouchHandler mHandler;
/**
* Reference to the long-touched view
*/
private View mLongTouchView;
/**
* Constructor
*/
public LongTouchActionListener(Context context) {
final float scale = context.getResources().getDisplayMetrics().density;
mTouchMoveLimitPxSq = scale*scale*TOUCH_MOVE_LIMIT_DP*TOUCH_MOVE_LIMIT_DP;
mHandler = new LongTouchHandler();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// down event
mIsLongTouch = false;
mIsClick = true;
mTouchDownX = event.getX();
mTouchDownY = event.getY();
mTouchDownTime = event.getEventTime();
mLongTouchView = view;
// post a runnable
mHandler.setEmptyMessageDelayed(LongTouchHandler.MESSAGE_LONG_TOUCH_WAIT, LONG_TOUCH_TIME);
break;
case MotionEvent.ACTION_MOVE:
// check to see if the user has moved their
// finger too far
if (mIsClick || mIsLongTouch) {
final float xDist = (event.getX() - mTouchDownX);
final float yDist = (event.getY() - mTouchDownY);
final float distanceSq = (xDist*xDist) + (yDist*yDist);
if (distanceSq > mTouchMoveLimitSqPx) {
// cancel the current operation
mHandler.removeMessages(LongTouchHandler.MESSAGE_LONG_TOUCH_WAIT);
mHandler.removeMessages(LongTouchHandler.MESSAGE_LONG_TOUCH_ACTION);
mIsClick = false;
mIsLongTouch = false;
}
}
break;
case MotionEvent.ACTION_CANCEL:
mIsClick = false;
case MotionEvent.ACTION_UP:
// cancel any message
mHandler.removeMessages(LongTouchHandler.MESSAGE_LONG_TOUCH_WAIT);
mHandler.removeMessages(LongTouchHandler.MESSAGE_LONG_TOUCH_ACTION);
long elapsedTime = event.getEventTime() - mTouchDownTime;
if (mIsClick && elapsedTime < LONG_TOUCH_TIME) {
onClick(v);
}
break;
}
// we did not consume the event, pass it on
// to the button
return false;
}
/**
* Handler to run actions on UI thread
*/
private class LongTouchHandler extends Handler {
public static final int MESSAGE_LONG_TOUCH_WAIT = 1;
public static final int MESSAGE_LONG_TOUCH_ACTION = 2;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_LONG_TOUCH_WAIT:
mIsLongTouch = true;
mIsClick = false;
// flow into next case
case MESSAGE_LONG_TOUCH_ACTION:
if (!mIsLongTouch) return;
onLongTouchAction(mLongTouchView); // call users function
// wait for a bit then update
takeNapThenUpdate();
break;
}
}
private void takeNapThenUpdate() {
sendEmptyMessageDelayed(MESSAGE_LONG_TOUCH_ACTION, LONG_TOUCH_ACTION_INTERVAL);
}
};
};
А вот пример реализации
private class FastForwardTouchListener extends LongTouchActionListener {
public void onClick(View v) {
// Next track
}
public void onLongTouchAction(View v) {
// Fast forward the amount of time
// between long touch action calls
mPlayer.seekTo(mPlayer.getCurrentPosition() + LONG_TOUCH_ACTION_INTERVAL);
}
}