Подтвердить что ты не робот

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

У меня есть ViewPager внутри a 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);
    }
});
4b9b3361

Ответ 1

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

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

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);
    } 
}

Ответ 2

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

Два решения:

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), если rimes с вашим пользовательским интерфейсом, создайте кнопку или кнопку изображения или что-нибудь для полного просмотра и установите для него onClick.

Удачи.

Ответ 3

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

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

Ответ 4

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

@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;
    }
}

Ответ 5

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

 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;
            }
        });

Ответ 6

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

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

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

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

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

 System.out.println("CLICKED ");

в

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

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

Ответ 7

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

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

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