2012-04-06 2 views
2

Краткая версия: Я хочу, чтобы запустить счетчик времени на onTouchEvent и проверить, прошло ли какое-то время перед ответом, в качестве ручного обнаружения LongTouch.Android: Как реализовать longpress вручную в событии touch?

Объяснение: У меня есть пользовательское изображение, которое скользит по экрану на двухпальцах. Я хочу добавить к нему события перетаскивания, но они должны быть быстрее, чем longpress. Я могу задержать событие перетаскивания, используя счетчик, который обновляется один раз в onTouchEvent и вызывает только перетаскивание, скажем, 10 отсчетов, но счетчик обновляется только при событиях касания, и палец должен двигаться.

Как создать счетчик времени, поле уровня активности, которое увеличивается на 60 раз в секунду или что-то подобное?

ответ

0

Ответ: Использовать системные часы (elapsedRealtime()) и измерить миллисекунды, поскольку пресса была инициирована. Легко, как только вы начнете его повесить.

1

Просто посмотрите исходный код android.

Длительное нажатие кнопки GestureDetector запускает сообщение с задержкой на «нажатие клавиши». Когда это сообщение доходит до «key up», это длинное нажатие.

Просто ссылка на источник http://www.devdaily.com/java/jwarehouse/android/core/java/android/view/GestureDetector.java.shtml

+0

Спасибо, но я не использую жесты. Вручную оценивать события касания более гибкие и удобные для того, что я хочу делать. Система событий касания обеспечивает отличную информацию, кроме времени. Следовательно, необходимо, чтобы простые часы измеряли пресеты в событии касания. ;) –

+0

Несомненно, в противном случае посмотрите на источник GestureDetector покажет, как это решить. Задержка сообщения - это ваши «часы» –

+0

Спасибо за источник. Смотря сейчас. –

1

так, как я бы подойти к этому было бы установить некоторые логическое значение истина, когда происходит Action_Down. Если action_up происходит, установите для boolean значение false. Также запустите установку postDelayed на любую задержку, которую вы хотите, когда произойдет action_down. В postdelayed, если логическое значение, которое вы ранее установили в true, по-прежнему истинно, тогда сделайте то, что вы хотите. Извините за такой многословный ответ, но именно так я и сделал бы это.

+0

Хорошо, я понимаю, что вы говорите. Завершите выполнение и перепутайте его. Я думаю, что это не будет wokr, потому что я не выполняю ActionUp. У меня есть два действия. 1) Перетащите значки из меню. 2) Двумя пальцами перейдите в экран включения/выключения меню. Задержка перетаскивания - только для того, чтобы второй палец мог попасть на экран, иначе перетаскивание будет запущено до того, как будет выполняться двухпальцевый переход. Таким образом, в принципе, если после ACTION_DOWN нет второго указателя 100 мс, тогда сделайте перетаскивание –

+0

. Ах, ладно, я вижу, что вы говорите. Если я правильно помню, первый палец вниз имеет идентификатор 0. Я бы сделал сообщение, указанное выше, но решающим фактором будет то, распознаете ли вы второй палец или нет или второй указательIndex event.getAction = ActionDown или ActionMove , Что-то вроде того. Просто некоторые идеи – testingtester

+0

Я нашел, что могу просто использовать SystemClock и измерить разницу во времени с момента первого прикосновения.: D –

7

Я не уверен в вашем вопросе, но кажется, что вы пытаетесь реализовать событие long click click в вашем onTouchListener, за исключением того, что вам нужно выполнить какую-то логику до того, как произойдет событие ACTION_UP? Если это так, это та же самая проблема, с которой я столкнулся. Я также пытался использовать System.nanoTime(), но я нашел менее сложный метод. Вы можете использовать таймер, вам просто нужно запланировать его в первом событии ACTION_DOWN и отменить его, когда произойдет что-либо неблагоприятное (например, ACTION_UP, что означает, что это не длинное нажатие, а просто щелчок или ACTION_MOVE со смещением по определенный порог). Что-то вроде следующего:

layout.seyOnTouchListener(new OnTouchListener(){ 
    private Timer longpressTimer; //won't depend on a motion event to fire 
    private final int longpressTimeDownBegin = 500; //0.5 s 
    private Point previousPoint; 

    switch(event.getAction()){ 

    case MotionEvent.ACTION_DOWN:{ 
     longPressTimer = new Timer(); 
     longpressTimer.schedule(new TimerTask(){ 
      //whatever happens on a longpress 
     }, longpressTimeDownBegin); 
     return true; //the parent was also handling long clicks 
    } 
    case MotionEvent.ACTION_MOVE:{ 
     Point currentPoint = new Point((int)event.getX(), (int)event.getY()); 

     if(previousPoint == null){ 
      previousPoint = currentPoint; 
     } 
     int dx = Math.abs(currentPoint.x - previousPoint.x); 
     int dy = Math.abs(currentPoint.y - previousPoint.y); 
     int s = (int) Math.sqrt(dx*dx + dy*dy); 
     boolean isActuallyMoving = s >= minDisToMove; //we're moving 

     if(isActuallyMoving){ //only restart timer over if we're actually moving (threshold needed because everyone's finger shakes a little) 
      cancelLongPress(); 
      return false; //didn't trigger long press (will be treated as scroll) 
     } 
     else{ //finger shaking a little, so continue to wait for possible long press 
      return true; //still waiting for potential long press 
     } 
    } 
    default:{ 
     cancelLongPress(); 
     return false; 
    } 
    } 
} 
+0

Наверное, это не большая разница, но в качестве оптимизации я бы рекомендовал удалить функцию Math.sqrt(), поскольку вычисление квадратного корня числа имеет тенденцию быть медленным. Просто измените minDisToMove на minSquareDisToMove и назначьте в качестве порога квадрат расстояния. Также см. Этот [ответ] (http://stackoverflow.com/a/11679788/996298) в качестве альтернативы обнаружению longpress. – manu3d

Смежные вопросы