Android: пользовательский просмотр onClickEvent с X & Y-местоположениями


У меня есть пользовательский вид, и я хочу получить координаты X и Y клика пользователя. Я обнаружил, что могу получить координаты только от onTouchEvent, а onClickEvent не будет стрелять, если у меня есть onTouchEvent. К сожалению, onTouchEvent срабатывает, когда пользователь перетаскивает экран, а также щелкает.

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

 public boolean onTouchEvent(MotionEvent event) {
  int action = event.getAction();
  if (action == MotionEvent.ACTION_DOWN) {
                //fires on drag and click

Я посмотрел на это но, как я уже упоминал выше, я не думаю, что решение там будет работать, так как я не могу заставить события onClick и onTouch работать одновременно. Может быть, я делаю что-то не так в этом отношении, есть ли нормальный способ борьбы с захватом пользовательского ввода на пользовательских событиях? Должен ли я быть в состоянии использовать события onClick и onTouch одновременно?

Спасибо, Мартин

6 2

6 ответов:

Теперь, я не знаю о onTouchEvent короткого замыкания onClick, и я не знаю, может быть, вам нужно установить android:clickable в true (или setClickable(true)). Но, если вы не можете заставить его работать чисто, вы можете использовать логическое значение в onTouchEvent, чтобы имитировать обнаружение щелчка, если все остальное не удается. в ACTION_DOWN установите его в true (isClicking или что-то вроде этого), в ACTION_MOVE установите его в false (потому что пользователь перетаскивает, поэтому не щелкает), а затем в ACTION_UP вы можете проверить его. Если это правда, то это означает, что пользователь придавил, но не потащил. Это банально, но если вы не можете заставить onClick работать, это в основном одно и то же.

Что вы возвращаете в конце вашего onTouchEvent? Согласно документации, возврат true означает "событие было полностью обработано, больше ничего с ним не делать", в то время как возврат false означает, что система продолжит обработку. Я не проверял это с вашей конкретной ситуацией, но это предполагает, что возвращение false может сработать. Это заставило бы систему продолжить обработку касания / щелчка и отправить его в следующий вид "снизу".

Если это не сработает, то я пока не могу подумайте о лучшем решении, чем делать что-то подобное тому, что предложил Рич. Вы можете сделать что-то вроде получения времени на ACTION_DOWN, а затем на ACTION_UP, сравнить время, которое прошло. Если он меньше 100 миллисекунд,то его следует интерпретировать как щелчок. Затем вы можете запустить любой код, который вы хотите поместить в свой прослушиватель кликов.

Например, вот как вы можете это закодировать:

long touchDownTime; // This has to be a class field so that it persists 
                    // between calls to onTouchEvent

public boolean onTouchEvent(MotioNEvent event){
    boolean handled = false;

    int action = event.getAction();
    switch (action){
    case MotionEvent.ACTION_DOWN:
        touchDownTime = SystemClock.elapsedRealtime();
        break;

    case MotionEvent.ACTION_UP:
        if (SystemClock.elapsedRealtime() - touchDownTime <= 100){
            int x = event.getX(); //or event.getRawX();
            int y = event.getY();
            performYourClick(x, y);
            handled = true;
        }
        break;
    }

    return handled;
}

Примечание: я на самом деле не тестировал этот код, так что, возможно, я сделал некоторые синтаксические ошибки. Хотя общая идея все равно должна быть прекрасной.

К вашему сведению, в моих тестах похоже, что onTouch переопределяет onClick для представления, независимо от того, возвращает ли onTouch true или false.

- Frink

Я смог решить эту проблему

Я создал пользовательский вид public class QuestionBuilderView extends View

В файле макета

 < com.example.android.view.QuestionBuilderView

        android:id="@+id/questionbuilderview"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />

В основном действии попробуйте вызвать пользовательский вид и установить прослушиватель событий Onclick / On Touch на вид

 View questionBuilder =  findViewById(R.id.questionbuilderview);
         questionBuilder.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                // TODO Auto-generated method stub
                float touched_x = event.getX();
               float  touched_y = event.getY();
               Toast.makeText(getApplicationContext(), " "+touched_x +","+touched_y, Toast.LENGTH_LONG).show();
              //  int action = event.getAction();


                return true;
            }

Я думаю, ты должен позвонить супер.onTouchEvent (событие), потому что в этом методе обнаружен щелчок.

Вы должны использовать GestureDetector. Подкласс GestureDetector.SimpleOnGestureListener и переопределение метода onDown(MotionEvent event) для возврата true. Затем переопределите onSingleTapConfirmed. Передайте прослушиватель конструктору GestureDetector. Затем вызовите setOnDoubleTapListener с этим слушателем в качестве параметра:

// in your view class constructor
GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
   @Override
   public boolean onDown(MotionEvent e) {
      return true;
   }
   @Override
   public boolean onSingleTapConfirmed(MotionEvent e) {
      // do whatever you want
      return true;
   }
};
mDetector = new GestureDetector(getContext(), listener);
mDetector.setOnDoubleTapListener(listener);

Затем вы можете передать MotionEvents детектору:

@Override
public boolean onTouchEvent(MotionEvent event) {
   return mDetector.onTouchEvent(event);
}