2

Я делаю меню, где элементы должны реагировать на два типа событий:Android - Ручка нажмите и проведите пальцем по пунктам ListView

OnClick
Если пользователь нажимает на элемент, он должен начать работу. Каждая кнопка запускает другое действие.

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

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

То, что я делаю прямо сейчас устанавливая OnClick ручки для каждого элемента в методе getView моего пользовательский адаптер и установкой gestureListener на моем ListView и обработку метода onFling, но он не действует, как ожидался: большинство из раз, когда я пытаюсь ударить и жест обрабатывается как щелчок ...

Я знаю, что я мог бы использовать реализацию как this, но я думаю, что я не могу использовать трюк события onTouch в этом случае, потому что мне нужно посмотреть позицию, чтобы я мог обрабатывать, какую деятельность следует запускать (onTouch/click) или которая TextView shou ld становятся видимыми.

Вот фрагменты кода, которые у меня есть до сих пор:

final GestureDetector gestureDetector = new GestureDetector(
      new GestureListener()); 

    lvMenu.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(final View view, final MotionEvent event) { 
      if (gestureDetector.onTouchEvent(event)) { 
       return false; 
      } 

      return true; 
     } 
    }); 

Внутренний класс:

class GestureListener extends SimpleOnGestureListener { 
    protected MotionEvent mLastOnDownEvent = null; 

    @Override 
    public boolean onDown(final MotionEvent e) { 
     return true; 
    } 

    @Override 
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, 
      final float velocityX, final float velocityY) { 
     Log.d("OnFling", "Called"); 
     final int SWIPE_MIN_DISTANCE = 20; 
     final int SWIPE_MAX_OFF_PATH = 250; 
     final int SWIPE_THRESHOLD_VELOCITY = 200; 
     try { 
      if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) { 
       return false; 
      } 
      if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE 
        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       Log.i("A", "Right to Left"); 
      } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE 
        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       Log.i("B", "Left to Right"); 
      } 
     } catch (final Exception e) { 
      // nothing 
     } 
     return super.onFling(e1, e2, velocityX, velocityY); 
    } 
} 

И onClick() метод внутри моего пользовательского адаптера:

public void onClick(final View v) { 
       Intent i = null; 
       switch (position) { 
       case 0: 
        i = new Intent(parent.getContext(), 
          ProfileActivity.class); 
        break; 
       case 1: 
        i = new Intent(parent.getContext(), 
          CatalogActivity.class); 
        break; 
       case 2: 
        i = new Intent(parent.getContext(), GuideActivity.class); 
        break; 
       case 3: 
        i = new Intent(parent.getContext(), 
          EventsActivity.class); 
        break; 
       default: 
        Log.d("MenuActivity", "Switch default case."); 
        break; 
       } 
       if (i != null) { 
        parent.getContext().startActivity(i); 
       } 

      } 

Спасибо)

EDIT 1: Теперь я пытаюсь установить OnTouchListener для каждого представления в моем пользовательском адаптере. Но он не работает ... Я не могу понять причину.

Это, как я устанавливаю вверх TouchListener:

  convertView.setOnTouchListener(new MenuGestureHandler() { 

      @Override 
      public boolean onSwipeRight() { 
       Log.d("Swipe Right", "OK!"); 
       return true; 
      } 

      @Override 
      public void onClick() { 
       Log.d("Click", "OK!"); 
      } 

     }); 

И это класс (с каким-то бесполезным кодом, как swipeUp, swipeDown):

public class MenuGestureHandler implements OnTouchListener { 

GestureDetector gestureDetector = new GestureDetector(new GestureListener()); 

@Override 
public boolean onTouch(final View v, final MotionEvent event) { 
    return gestureDetector.onTouchEvent(event); 
} 

private final class GestureListener extends SimpleOnGestureListener { 

    private static final int SWIPE_THRESHOLD = 100; 
    private static final int SWIPE_VELOCITY_THRESHOLD = 100; 

    @Override 
    public boolean onSingleTapConfirmed(final MotionEvent e) { 
     onClick(); // my method 
     return super.onSingleTapConfirmed(e); 
    } 

    @Override 
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, 
      final float velocityX, final float velocityY) { 
     boolean result = false; 
     try { 
      final float diffY = e2.getY() - e1.getY(); 
      final float diffX = e2.getX() - e1.getX(); 
      if (Math.abs(diffX) > Math.abs(diffY)) { 
       if (Math.abs(diffX) > SWIPE_THRESHOLD 
         && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { 
        if (diffX > 0) { 
         result = onSwipeRight(); 
        } else { 
         result = onSwipeLeft(); 
        } 
       } 
      } else { 
       if (Math.abs(diffY) > SWIPE_THRESHOLD 
         && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { 
        if (diffY > 0) { 
         result = onSwipeBottom(); 
        } else { 
         result = onSwipeTop(); 
        } 
       } 
      } 
     } catch (final Exception exception) { 
      exception.printStackTrace(); 
     } 
     return result; 
    } 
} 

public boolean onSwipeRight() { 
    return false; 
} 

public boolean onSwipeLeft() { 
    return false; 
} 

public void onClick() { 
} 

public boolean onSwipeTop() { 
    return false; 
} 

public boolean onSwipeBottom() { 
    return false; 
} 

EDIT 2 я мог заставить его работать, просто переопределив метод onDown() в моем классе GestureListener и установив его, чтобы он всегда возвращал true. Я действительно не понимаю, зачем мне это нужно, но похоже, что он работает сейчас!

ответ

4

Здесь может быть несколько проблем, но в первую очередь это иерархия сенсорных событий.

Из того, что я понимаю, то GestureDetector прикрепляется к ListView через OnTouchListener и OnClickListener устанавливается на отдельные элементы списка - которые являются мнения ребенка о ListView.

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

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

Вы можете также рассмотреть возможность просмотра моих разговоров на Android Touch System, чтобы дать вам более подробное представление о том, с чем вы имеете дело.

+0

Хорошо, прекрасно. Теперь я понимаю проблему ... Но я не могу прикрепить OnTouchListener к каждому элементу, я не знаю почему! Это просто не работает ... Можете ли вы мне помочь? Я редактировал свой пост с самым новым кодом. Огромное спасибо. –

Смежные вопросы