Как я могу обнаружить клик в приемнике onTouch?

У меня есть ViewPager внутри ScrollView . Мне нужно прокручивать как по горизонтали, так и по вертикали. Для достижения этой цели пришлось отключить вертикальную прокрутку всякий раз, когда мой ViewPager коснулся ( v.getParent().requestDisallowInterceptTouchEvent(true); ), чтобы он мог прокручиваться по горизонтали.

Но в то же время мне нужно щелкнуть viewPager, чтобы открыть его в полноэкранном режиме.

Проблема в том, что onTouch вызывается перед onClick, и мой OnClick никогда не вызывается.

Как я могу реализовать оба касания onClick?

 viewPager.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { System.out.println("TOUCHED "); if(event.getAction() == MotionEvent.???){ //open fullscreen activity } v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed return false; } }); viewPager.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("CLICKED "); Intent fullPhotoIntent = new Intent(context, FullPhotoActivity.class); fullPhotoIntent.putStringArrayListExtra("imageUrls", imageUrls); startActivity(fullPhotoIntent); } }); 

Solutions Collecting From Web of "Как я могу обнаружить клик в приемнике onTouch?"

Ответ Масуда Дадаши помог мне разобраться.

Вот как это выглядит в конце.

 viewPager.setOnTouchListener(new OnTouchListener() { private int CLICK_ACTION_THRESHOLD = 200; private float startX; private float startY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_UP: float endX = event.getX(); float endY = event.getY(); if (isAClick(startX, endX, startY, endY)) { launchFullPhotoActivity(imageUrls);// WE HAVE A CLICK!! } break; } v.getParent().requestDisallowInterceptTouchEvent(true); //specific to my project return false; //specific to my project } private boolean isAClick(float startX, float endX, float startY, float endY) { float differenceX = Math.abs(startX - endX); float differenceY = Math.abs(startY - endY); return !(differenceX > CLICK_ACTION_THRESHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHOLD); } } 

Разработка обоих – неправильная идея. Когда пользователь может делать разные вещи, прикоснувшись к экрану, понимание цели пользователя немного изящно, и вам нужно разработать кусок кода для него.

Два решения:

1- (лучшая идея) в вашем событии onTouch, если есть движение. Вы можете сделать это, проверив, есть ли какое-либо движение, используя:

 ACTION_UP ACTION_DOWN ACTION_MOVE 

делай это так

 if(event.getAction() != MotionEvent.ACTION_MOVE) 

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

 switch(event.getAction()) { case MotionEvent.ACTION_DOWN: if(isDown == false) { startX = event.getX(); startY = event.getY(); isDown = true; } Break; case MotionEvent.ACTION_UP { endX = event.getX(); endY = event.getY(); break; } } 

Считайте, что это щелчок, если ничего из вышеперечисленного не произошло и делать то, что вы хотите сделать с кликом.

2) если вы используете свой интерфейс, создайте кнопку или кнопку изображения или что-нибудь для полного просмотра и установите для него onClick.

Удачи

Я сделал что-то очень просто, записав время, когда пользователь коснулся экрана.

 private long lastTouchDown; private static int CLICK_ACTION_THRESHHOLD = 200; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastTouchDown = System.currentTimeMillis(); break; case MotionEvent.ACTION_UP: if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD) { Log.w("App", "You clicked!"); } break; } return true; } 

Также стоит отметить, что GestureDetector имеет встроенный интерфейс. Посмотрите onSingleTapUp

Возможно, вам придется различать щелчок пользователя и долгое нажатие. В противном случае вы обнаружите, что и то же самое. Я сделал это, чтобы сделать это возможным:

 @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); bClick = true; tmrClick = new Timer(); tmrClick.schedule(new TimerTask() { public void run() { if (bClick == true) { bClick = false; Log.d(LOG_TAG, "Hey, a long press event!"); //Handle the longpress event. } } }, 500); //500ms is the standard longpress response time. Adjust as you see fit. return true; case MotionEvent.ACTION_UP: endX = event.getX(); endY = event.getY(); diffX = Math.abs(startX - endX); diffY = Math.abs(startY - endY); if (diffX <= 5 && diffY <= 5 && bClick == true) { Log.d(LOG_TAG, "A click event!"); bClick = false; } return true; default: return false; } } 

Я думаю, что время / позиция совместного решения должны быть лучше:

  private float initialTouchX; private float initialTouchY; private long lastTouchDown; private static int CLICK_ACTION_THRESHHOLD = 100; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastTouchDown = System.currentTimeMillis(); //get the touch location initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); return true; case MotionEvent.ACTION_UP: int Xdiff = (int) (event.getRawX() - initialTouchX); int Ydiff = (int) (event.getRawY() - initialTouchY); if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD && (Xdiff < 10 && Ydiff < 10)) { //clicked!!! } return true; } return false; } }); 

Я думаю, что ваша проблема исходит из строки:

 v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed 

Взгляните на документацию . Вы пытались удалить линию? В чем заключается просьба не удалять эту строку?

Примите во внимание, согласно документации , что если вы вернете true из вашего onTouchListener, событие будет уничтожено, а если вы вернете значение false, будет распространено, чтобы вы могли использовать это для распространения события.

Кроме того, вы должны изменить свой код:

  System.out.println("CLICKED "); 

чтобы:

  Log.d("MyApp", "CLICKED "); 

Получить правильный вывод в logcat.

Я считаю, что вы мешаете вашему восприятию получать событие касания таким образом, потому что TouchListener перехватывает его. Вы также можете

  • Отправляйте событие внутри своего ToucheListener, вызывая v.onTouchEvent(event)
  • Вместо этого переопределите ViewPager.onTouchEvent(MotionEvent) чтобы не перехватывать событие

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

Вы можете использовать OnTouchClickListener

https://github.com/hoffergg/BaseLibrary/blob/master/src/main/java/com/dailycation/base/view/listener/OnTouchClickListener.java

Применение:

 view.setOnTouchListener(new OnTouchClickListener(new OnTouchClickListener.OnClickListener() { @Override public void onClick(View v) { //perform onClick } },5));