Intereting Posts
Android studio 2.3: Не удалось инициализировать класс org.jetbrains.kotlin.android.actions.NewKotlinActivityAction Как сделать AUTO_INCREMENT в базе данных Android SQLite? Обфускация в Android Studio Вывод фрагмента фрагмента Android Studio Google Map Конфигурация Android Android SDK на Eclipse Как я могу автоматически протестировать функциональность приложений iOS и Android? Android Instant Run В первый раз требуется слишком много времени для запуска приложения после установки Javadoc в Eclipse не распознает пакеты Android. Как изменить активность в одной вкладке Чтение новых атрибутов темы на старой платформе Выберите камеру в загрузке файла в приложении кордовы на андроид без использования камеры cordova Какой самый эффективный способ для Android вызывать вызовы HTTP Web API, которые возвращают ответ JSON? Сбой сборки Android Studio с «Задачей» не найден в корневом проекте «MyProject» ». Исключить несколько символов «%» в Android Android SDK Version 25 – android.support v7: 25 дает «Ресурс не найден, который соответствует @ color / hint_foreground_material_light» Adobe Creative SDK?

ScaleGestureDetector.onTouchEvent всегда возвращает 'true'

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

Я заметил что-то другое: scaleGestureDetector.onTouchEvent () всегда возвращает «true» в моем случае. Следующий фрагмент кода моего класса MyView:

public boolean onTouchEvent(MotionEvent event) { boolean retval = scaleGestureDetector.onTouchEvent(event); Log.v("MyView.onTouchEvent()", "Action: " + event.getAction() + "; PointerCount: " + event.getPointerCount() + "; scaleGestureDetector.onTouchEvent() RetVal: " + retval); return(retval); } 

Выпустил вывод журнала после того, как я коснулся вида в течение приблизительно 1 секунды одним пальцем, затем выполнил масштабный жест с двумя пальцами:

 01-01 19:09:54.484: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:54.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:54.541: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:54.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:54.820: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:54.910: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:55.050: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:55.350: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:55.400: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:09:57.160: INFO/BatteryStatsImpl(96): notePhoneSignalStrengthLocked: 4->3 01-01 19:10:00.060: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false 01-01 19:10:00.060: ERROR/ClockWidget(215): handleUiMessage~ in pause. msg:36867 01-01 19:10:00.070: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false 01-01 19:10:00.090: INFO/PI.Alarms(699): Update Alarms start 01-01 19:10:00.090: INFO/PI.Alarms(699): Task Notifications: Already displaying the same alarms, no update 01-01 19:10:00.100: INFO/PI.Alarms(699): Event Notifications: Already displaying the same alarms, no update 01-01 19:10:00.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.870: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.900: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.922: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.931: VERBOSE/MyView.onTouchEvent()(5930): Action: 261; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:00.950: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.002: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.030: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.060: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.090: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.120: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.140: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.172: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.200: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.230: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.252: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.280: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.310: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.342: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.370: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.390: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.424: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.450: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.480: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.530: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.690: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.780: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.815: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 262; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 01-01 19:10:01.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 

Как я сказал: возвращаемое значение всегда «истинно»! Является ли это ошибкой ScaleGestureDetector.onTouchEvent ()? Что я могу сделать, чтобы другие обработчики обрабатывали все события, не связанные с масштабированием (например, длительное нажатие одним пальцем)? Пожалуйста помоги!

Nemax

Solutions Collecting From Web of "ScaleGestureDetector.onTouchEvent всегда возвращает 'true'"

Не знаю, является ли это ошибкой или преднамеренным, но это определенно то, что делает источник (ScaleGestureDetector.java:156):

 public boolean onTouchEvent(MotionEvent event) { final int action = event.getAction(); boolean handled = true; /* ... bunch of code that never updates 'handled' */ return handled; } 

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

  if (mLongPressGestureDetector != null && mLongPressGestureDetector.onTouchEvent(event)) return true; else if (mIsInMoveMode && mScaleGestureDetector != null) { // Check for a move if (action == MotionEvent.ACTION_MOVE && !mScaleGestureDetector.isInProgress()) { handleMove(event); return true; } // Now a scale mScaleGestureDetector.onTouchEvent(event); return true; } 

ScaleGestureDetector предоставляет метод isInProgress (), который может делать то, что вы хотите …

Вот пример его использования:

 public boolean onTouch(View v, MotionEvent event) { mScaleDetector.onTouchEvent(event); if (!mScaleDetector.isInProgress()) { if (event.getAction() == MotionEvent.ACTION_DOWN || (event.getAction() == MotionEvent.ACTION_MOVE)) { touchX = (int) event.getX(); touchY = (int) event.getY(); isTouched = true; } if (event.getAction() == MotionEvent.ACTION_UP) { isTouched = false; } } else { isTouched = false; } return true; } 

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

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

Было еще несколько проблем: 1. Если пользователь начинает жест масштаба, мне пришлось отменить какие-либо процессы обнаружения длинных кликов, потому что получающее представление получит первое событие DOWN, а затем ничего больше (после того, как второй палец опустится И началось масштабирование), а затем ложно полагают, что выполняется длинное нажатие. 2. Когда было выполнено длинное нажатие и появилось контекстное меню, я должен был предотвратить обнаружение жестов и масштабирования жестов здесь в dispatchOnTouchEvent () до следующего события UP, в противном случае прокрутка и масштабирование выполнялись бы даже при наличии контекстного меню.

Довольно сложно, но я потратил часы и часы и много проб и ошибок, и просто не мог найти более простого решения. Во всяком случае, обработка 1. жестов по шкале, 2. жесты горизонтального прокрутки, 3. вертикальные жесты прокрутки, 4. длинные клики и 5. короткие клики, все на одном и том же целевом представлении, не совсем простая задача выполнить. ,

Вот код (соответствующие его части):

  @Override public boolean dispatchTouchEvent(MotionEvent e) { if (eventInProgress) { // View shall only receive scale gesture event if visible if (targetView.isShown()) scaleGestureDetector.onTouchEvent(e); if (scaleGestureDetector.isInProgress()) motionEventConsumed = true; } if (motionEventConsumed) { if (e.getAction() == MotionEvent.ACTION_UP) motionEventConsumed = false; if (cancelLongPressEvent) { cancelLongPressEvent = false; targetView.cancelLongPress(); } return (true); } // Get the action that was done on this touch event switch (e.getAction()) { case MotionEvent.ACTION_DOWN: { // store the X value when the user's finger was pressed down downXValue = e.getX(); downYValue = e.getY(); cancelLongPressEvent = true; eventInProgress = true; break; } case MotionEvent.ACTION_MOVE: // When having moved by too many x or y pixels, then // cancel any ongoing long klick events if (cancelLongPressEvent && Math.abs(e.getX() - downXValue) + Math.abs(e.getY() - downYValue) > 40) { targetView.cancelLongPress(); cancelLongPressEvent = false; } break; case MotionEvent.ACTION_UP: { if (eventInProgress) { // Get the X value when the user released his/her finger float deltaX = e.getX() - downXValue; float deltaY = e.getY() - downYValue; if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) { // going backwards: pushing stuff to the right if (deltaX > 0) { flipRight(); return (true); } // going forwards: pushing stuff to the left if (deltaX < 0) { flipLeft(); return (true); } break; } } } } // If event was not handled here, then forward it to parent, // ie to view hierarchy return (super.dispatchTouchEvent(e)); } 

[…]

 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater mi = getMenuInflater(); mi.inflate(R.menu.lztv_context_menu, menu); contextMenuTargetView = v; eventInProgress = false; }