Поиск по этому блогу

четверг, 3 января 2013 г.

Событие долгого нажатия на карте

Сегодня мне понадобилось сделать событие длинного нажатия на карте, и я подумал что ничего сложного в этом нет, а оказалось что не так все просто… Начал пробовать события onLongClick, onLongPress и остальные события но оно совсем ничего не выдавало, я уже начал беситься и хотел уже забить на это дело, но наткнулся на пример который как раз у меня и заработал в нем все очень просто, давайте его рассмотрим.

Вот такой вот класс разрешает и находит длинные нажатия на карту. Объяснение что и как делается в классе будет после кода:

import android.os.Bundle;
import android.os.Looper;
import android.view.MotionEvent;
 import com.google.android.maps.MapActivity;
 public class Map extends MapActivity {
    private boolean isPotentialLongPress;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
 
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        handleLongPress(event);
        return super.dispatchTouchEvent(event);
    }
 
    private void handleLongPress(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
 
            new Thread(new Runnable() {
                public void run() {
                    Looper.prepare();
                    if (isLongPressDetected()) {
                        //тутачки делаем то что ходим после долгого нажатия
                    }
                }
            }).start();
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            if (event.getHistorySize() < 1)
                return;
 
            float diffX = event.getX()
                    - event.getHistoricalX(event.getHistorySize() - 1);
            float diffY = event.getY()
                    - event.getHistoricalY(event.getHistorySize() - 1);
 
            if (Math.abs(diffX) > 0.5f || Math.abs(diffY) > 0.5f) {
                isPotentialLongPress = false;
            }
        } else {
            isPotentialLongPress = false;
        }
    }

    public boolean isLongPressDetected() {
        isPotentialLongPress = true;
        try {
            for (int i = 0; i < (50); i++) {
                Thread.sleep(10);
                if (!isPotentialLongPress) {
                    return false;
                }
            }
            return true;
        } catch (InterruptedException e) {
            return false;
        } finally {
            isPotentialLongPress = false;
        }
    }
 
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
 }


Итак давайте рассмотрим что происходит.
MapActivity.dispatchTouchEvent (MotionEvent e), обрабатывает все события прикосновений к экрану. При переопределении этого метода, мы должны позаботиться о следующих элементах для обработки «длинных нажатий»:
  1. Если палец только что прикоснулся к экрану, мы начинаем проверку, как долго он держится. Мы должны сделать это в отдельном потоке, иначе интерфейс будет заблокирован. Если проверки в следующей точке не будет в течение заданного порога, говорим что у нас есть событие долгого нажатия и вызываем нужное событие, в моем случае это было, вызов калибровки акселерометра.
  2. Если некоторые движения — событие, которое не может быть частью долгого нажатия была выполнена, отменить регистрацию пункт 2.
Этими событиями есть:
  • Палец был удален с экрана
  • Палец переместился на более чем заданное пороговое значение