Android ACTION_MOVE Порог

Я пишу приложение, которое включает в себя запись на экране одним пальцем или, в конце концов, стилусом. У меня есть эта работа. В ACTION_DOWN начинается рисование; на ACTION_MOVE, добавляет сегменты линии; на ACTION_UP, завершает линию.

Проблема заключается в том, что после ACTION_DOWN, по-видимому, указатель должен перемещаться более чем на 10 пикселей от того места, где он был запущен (в основном, поле 20x20 вокруг начальной точки), чтобы начать отправлять события ACTION_MOVE. После выхода из коробки события перемещения все довольно точны. (Я выяснил 10-пиксельную вещь, протестировав ее.) Поскольку это предназначено для записи или рисования, 10 пикселей - довольно значительная потеря: в зависимости от того, насколько малы вы пытаетесь написать, вы можете потерять первую букву или два. Я ничего не смог найти - только пару сообщений на форуме или два, например http://android.modaco.com/topic/339694-touch-input -задача-не-обнаруживать-очень-малых движений /page _pid_1701028 # entry1701028. Кажется, что он присутствует на некоторых устройствах или системах, а не на других. Нет никаких идей относительно того, как избавиться от него, когда у вас есть это.

Я использую Galaxy Tab 10.1, с Android 3.1. Я попробовал несколько разных вещей, чтобы попытаться избавиться от него: я пробовал установить козыри событий на что-то еще, чтобы увидеть, могу ли я обмануть его, думая, что курсор находится в другом месте; Я попробовал перераспределить событие с измененными координатами (мой обработчик отреагировал на новые точки, но все же не ответил на движения в радиусе 10 пикселей). Я искал исходный код для любых ссылок на эффект, и не нашел никого (хотя я думаю, что это из другой версии Android-кода для 3.1 еще не выпущено, не так ли?) Я искал методы запроса текущего состояния указателей, поэтому я мог бы просто иметь таймер уловить изменения до тех пор, пока указатель не пересечет порог. Не удалось найти способ получить указательные координаты без соответствующего события движения. Ничего не получилось. Кто-нибудь знает что-нибудь об этом или имеет какие-то идеи или проблемы? Спасибо.

- Обновление: события перетаскивания показывают один и тот же порог.

Ответ 1

Я согласен частично с сообщением @passsy, но пришел к другому выводу. Во-первых, как уже упоминалось, mTouchSlop - это значение, которое нас интересует и которое выставляется через ViewConfiguration.get(context).getScaledTouchSlop();

Если вы проверяете источник Android для ViewConfiguraton, значение по умолчанию для TOUCH_SLOP 8dip, но в комментариях упоминается, что это значение является только резервным, и фактическое значение определяется при создании ОС Android для этого конкретного устройства. (это может быть больше или меньше этого значения. Оно, как представляется, справедливо для устройств Galaxy Tab)

Более конкретно для образца кода значение mTouchSlop считывается из ViewConfiguration, когда инициализируется View, но значение доступно только в методе onTouchEvent. Если вы расширяете View и переопределяете этот метод (без вызова super), поведение mTouchSlop в классе View больше не актуально.

Более того, нам стало известно, что при изменении настроек Android для наложения сенсорных событий на экране прикосновение с небольшим сопротивлением не регистрируется как событие движения, подчеркнутое тем фактом, что перекрестие от ОС Android не двигаться. Из этого можно сделать вывод, что минимальное расстояние перетаскивания выполняется на уровне ОС, и ваше приложение никогда не будет знать о событиях перетаскивания, меньших значения TOUCH_SLOP. Вы также должны знать, что TOUCH_SLOP не следует использовать напрямую, а API обесценивает метод getTouchSlop и рекомендует getScaledTouchSlop, который учитывает размер экрана и плотность пикселей устройства. Побочным эффектом этого является то, что фактическая минимальная длина хода, воспринимаемая на разных устройствах, может различаться. например, на Galaxy Tab 2.0 7.0 "кажется, что мы можем делать короткие минимальные штрихи с использованием той же базы кода, что и при работе на Galaxy Tab 2.0 10.1"

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

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

Ответ 2

Проблема заключается в строке 6549 в классе View https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java

if (!pointInView(x, y, mTouchSlop)) {...}

 /**
 * Utility method to determine whether the given point, in local coordinates,
 * is inside the view, where the area of the view is expanded by the slop factor.
 * This method is called while processing touch-move events to determine if the event
 * is still within the view.
 */
private boolean pointInView(float localX, float localY, float slop) {
    return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
            localY < ((mBottom - mTop) + slop);
}

mTouchSlop устанавливается в конструкторе

mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

Вы можете расширить View и установить mTouchSlop на ноль. Я не вижу другого способа установить mTouchSlop. Нет такой функции, как getApplicationContext.setScaledTouchSlop(int n).