it-swarm.com.ru

Как я могу обнаружить щелчок в слушателе 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);
    }
});
19
code511788465541441

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

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

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

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

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

17
nilsi

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

Два решения:

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.

Удачи

9
Masoud Dadashi

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

@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
Adam Komar

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

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

MotionEvent.ACTION_UP означает, что вы касаетесь первого времени датчика

MotionEvent.ACTION_DOWN означает, что сенсорный датчик больше не обнаруживает

например, MotionEvent.ACTION_MOVE означает, что датчик обнаруживает некоторые движения (например, пролистывание, прокрутка и т. д.)

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

Каждый вид охватывает своего родителя. Так что, если у вашего вида есть слушатель Touch, он работает как перехватчик. Можно продолжить цепочку касаний, вызываемых родительскими представлениями, возвращающими false из логического метода onTouch (View v, MotionEvent).

дополнительно: View.performClick () возвращает true, только если он имеет OnClickListener

yourView.setOnTouchListener(new View.OnTouchListener() {
                int lastEvent;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP && lastEvent == MotionEvent.ACTION_DOWN) {
                        return ~ /**Click detected. Do something and return result**/
                    }
                    lastEvent = event.getAction();
                    return v.performClick();
                }
            });
0
Oleg Bozhko

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

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

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

0
Antoine Marques

вы можете использовать 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));

0
hoffer