Android

Detect touch press vs long press vs movement?

Обнаружение сенсорного нажатия по сравнению с долгим нажатием по сравнению с движением?

В настоящее время я занимаюсь программированием для Android, но у меня небольшая проблема с обнаружением различных событий касания, а именно обычного сенсорного нажатия (нажмите на экран и сразу отпустите), длительного нажатия (коснитесь экрана и удерживайте на нем палец) и перемещения (перетаскивание по экрану).

Что я хотел сделать, так это иметь изображение (круга) на моем экране, которое я могу перетаскивать. Затем, когда я нажимаю его один раз (короткое / обычное нажатие), появляется всплывающее окно с некоторой базовой информацией о нем. Когда я долго нажимаю на него, появляется AlertDialog со списком для выбора другого изображения (круга, прямоугольника или треугольника).

Я создал пользовательский вид с помощью моего собственного OnTouchListener для обнаружения событий и рисования изображения в onDraw. OnTouchListener.onTouch выглядит примерно так:

// has a touch press started?
private boolean touchStarted = false;
// co-ordinates of image
private int x, y;

public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
touchStarted = true;
}
else if (action == MotionEvent.ACTION_MOVE) {
// movement: cancel the touch press
touchStarted = false;

x = event.getX();
y = event.getY();

invalidate(); // request draw
}
else if (action == MotionEvent.ACTION_UP) {
if (touchStarted) {
// touch press complete, show toast
Toast.makeText(v.getContext(), "Coords: " + x + ", " + y, 1000).show();
}
}

return true;
}

Проблема в том, что нажатие работает не совсем так, как ожидалось, потому что, когда я случайно касаюсь экрана, оно также обнаруживает небольшое движение и отменяет сенсорное нажатие и вместо этого перемещается по изображению.

Я немного "взломал" это, введя новую переменную "mTouchDelay", которой я установил значение 0 при ACTION_DOWN, увеличиваю ПЕРЕМЕЩЕНИЕ, и если оно > = 3 при ПЕРЕМЕЩЕНИИ, я выполняю свой код "перемещения". Но у меня такое чувство, что на самом деле это не тот путь.

Я также не выяснил, как определить длительное нажатие. На самом деле виновником является ПЕРЕМЕЩЕНИЕ, которое, кажется, всегда срабатывает.

Пример того, чего я примерно хочу, смотрите в приложении для Android "DailyStrip": оно показывает изображение комикса. Вы можете перетащить его, если оно слишком большое для экрана. Вы можете нажать на него один раз, чтобы появились некоторые элементы управления, и долго нажимать на него, чтобы вызвать меню опций.

PS. Я пытаюсь заставить это работать на Android 1.5, поскольку мой телефон работает только на 1.5.

Переведено автоматически
Ответ 1

Этот код может различать щелчок и перемещение (перетаскивание, прокрутку). В onTouchEvent установите флаг isOnClick и начальные координаты X, Y в ACTION_DOWN . Снимите флаг с ACTION_MOVE (учитывая, что часто обнаруживается непреднамеренное движение, которое может быть решено с помощью порогового значения const ).

private float mDownX;
private float mDownY;
private final float SCROLL_THRESHOLD = 10;
private boolean isOnClick;

@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
isOnClick = true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (isOnClick) {
Log.i(LOG_TAG, "onClick ");
//TODO onClick code
}
break;
case MotionEvent.ACTION_MOVE:
if (isOnClick && (Math.abs(mDownX - ev.getX()) > SCROLL_THRESHOLD || Math.abs(mDownY - ev.getY()) > SCROLL_THRESHOLD)) {
Log.i(LOG_TAG, "movement detected");
isOnClick = false;
}
break;
default:
break;
}
return true;
}

Для длительного нажатия, как предлагалось выше, подойдет GestureDetector. Проверьте эти вопросы и ответы:

Обнаружение длительного нажатия с Android

Ответ 2

Из документации Android -

onLongClick()

Из просмотра.OnLongClickListener. Это вызывается, когда пользователь либо касается элемента и удерживает его (в сенсорном режиме), либо фокусируется на элементе с помощью клавиш навигации или трекбола и нажимает и удерживает подходящую клавишу "enter", либо нажимает и удерживает трекбол (в течение одной секунды).

onTouch ()

Из View.OnTouchListener. Это вызывается, когда пользователь выполняет действие, квалифицируемое как событие касания, включая нажатие, отпускание или любой жест движения на экране (в пределах элемента).

Что касается "перемещение происходит, даже когда я касаюсь", я бы установил дельту и убедился, что вид был перемещен хотя бы на дельту, прежде чем вводить код перемещения. Если этого не произошло, запустите код касания.

Ответ 3

Я обнаружил это после долгих экспериментов.

При инициализации вашего действия:

setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View view) {
activity.openContextMenu(view);
return true; // avoid extra click events
}
});
setOnTouch(new View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent e){
switch(e.getAction & MotionEvent.ACTION_MASK){
// do drag/gesture processing.
}
// you MUST return false for ACTION_DOWN and ACTION_UP, for long click to work
// you can return true for ACTION_MOVEs that you consume.
// DOWN/UP are needed by the long click timer.
// if you want, you can consume the UP if you have made a drag - so that after
// a long drag, no long-click is generated.
return false;
}
});
setLongClickable(true);
Ответ 4

Я искал похожее решение, и это то, что я бы предложил. В методе onTouch запишите время для события MotionEvent .Событие ACTION_DOWN, а затем для события MotionEvent .ACTION_UP, запишите время еще раз. Таким образом, вы также можете установить свой собственный порог. После нескольких экспериментов вы узнаете максимальное время в миллисекундах, необходимое для записи простого касания, и вы можете использовать это в move или другим методом по своему усмотрению.

Надеюсь, это помогло. Пожалуйста, прокомментируйте, использовали ли вы другой метод и решили ли вашу проблему.

java android