Условно потреблять MotionEvents

public class CalendarEventView extends LinearLayout {
public CalendarEventView(Context context) {
    super(context);
}

public CalendarEventView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CalendarEventView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);

    if((event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP)  && event.getAction() != MotionEvent.ACTION_MOVE){
        Log.v("move", "click");
        return true;
    }

    return false;
}
}

У меня есть 2 окна просмотра, которые я синхронизирую. Один содержит CalendarEventViews. Они оставались синхронизированными, пока я не добавил onClick и onLongClick к своему CalendarEventView (я установил эти слушатели в viewpager).

Моя проблема в том, что я могу получить либо клики, либо прокрутку, но не оба. Другими словами, как мне разрешить моему CalendarEventView потреблять клики, но позволить его родительскому элементу обрабатывать перемещение / прокрутку.

Примечание: я не возражаю, если и CalendarEventView, и родитель (viewpager) способны обрабатывать событие, пока они оба получают его.

3 ответа

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

        // Synchronise both ViewPagers
//        headerColumnViewPager.setOnTouchListener(new OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                contentColumnViewPager.onTouchEvent(event);
//                return false;
//            }
//        });
//        contentColumnViewPager.setOnTouchListener(new OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                headerColumnViewPager.onTouchEvent(event);
//                return false;
//            }
//        });

    headerColumnViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        private int mScrollState = ViewPager.SCROLL_STATE_IDLE;

        @Override
        public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                return;
            }
            contentColumnViewPager.scrollTo(headerColumnViewPager.getScrollX(), contentColumnViewPager.getScrollY());
        }

        @Override
        public void onPageSelected(final int position) { }

        @Override
        public void onPageScrollStateChanged(final int state) {
            mScrollState = state;
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                contentColumnViewPager.setCurrentItem(headerColumnViewPager.getCurrentItem(), false);
            }
        }
    });

    contentColumnViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        private int mScrollState = ViewPager.SCROLL_STATE_IDLE;

        @Override
        public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                return;
            }
            headerColumnViewPager.scrollTo(contentColumnViewPager.getScrollX(), headerColumnViewPager.getScrollY());
        }

        @Override
        public void onPageSelected(final int position) { }

        @Override
        public void onPageScrollStateChanged(final int state) {
            mScrollState = state;
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                headerColumnViewPager.setCurrentItem(contentColumnViewPager.getCurrentItem(), false);
            }
        }
    });

Источник: Синхронизация двух ViewPager с помощью OnPageChangeListener

ViewGroup, который является родительским, получает сначала interceptTouchEvent, и если какой-либо дочерний элемент возвращает true, тогда родительский не получит другие события.

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

Попробуй это:

long eventStarted;
long threshold = 500; //500ms
@Override
public boolean onTouchEvent(MotionEvent event) {
  super.onTouchEvent(event);
  switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      eventStarted = System.currentTimeMillis();
      Log.v("move", "action down");
      return (true);
    case MotionEvent.ACTION_MOVE:
      return (System.currentTimeMillis() > (eventStarted + threshold));
    case MotionEvent.ACTION_UP:
      if (System.currentTimeMillis() <= (eventStarted + threshold)) {
        //This is a click
      }
      eventStarted = 0;
      return (true);
  }
  return false;
}

В основном вы меняете значение по умолчанию OnClickListener реализовать свою версию, чтобы вы не использовали события перемещения.

Другие вопросы по тегам