2014-10-14 3 views
7

ПланКак захватить события onTouch на двух перекрывающихся видах?

! * Container is a relative layout contains two custom views: OuterView1 and InnerView2 * Outer View1 is a custom view, matching the parent’s size (full screen) * Inner View2 is also a custom view, laid on top of OuterView1 overlapping it.

  • Контейнер представляет собой относительное расположение содержит два пользовательских представлений: OuterView1 и InnerView2
  • Внешний View1 обычай вид, соответствующий размер родителя (полный экран)
  • Внутренний View2 также настраиваемое представление, положил поверх OuterView1, перекрывая его.

Как для OuterView1, так и для InnerView2, я хочу захватить эти события касания onSingleTapConfirmed() и onFling(). Область, в которой оба OuterView1 и InnerView2 перекрываются, я хочу, чтобы элемент управления передавался методам сенсорного события обоих представлений.

Я попытался это:

класс Container

@Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     outerView1.onTouchEvent(ev); 
     innerView2.onTouchEvent(ev); 
     return false; 
    } 

OuterView1 класс

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

жест является экземпляром GestureDetector.SimpleOnGestureListener с операторами журнала для onDown(), onFling() и onSingleTapConfirmed()

InnerView2 clas s

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

жест является экземпляром GestureDetector.SimpleOnGestureListener с операторами журнала для onDown(), onFling() и onSingleTapConfirmed() методы

При таком подходе, я последовательно получить обратный вызов в onDown() методы оба вида. Но я не вижу согласованное поведение на onSingleTapConfirmed() и onFling() методы

Когда я постучал в красном круге (на скриншоте) три раза, и я получил три различных поведение

  • First попробуйте (желаемое поведение)

    10-14 09:03:14.155: I/OuterView1(27776): OuterView1.onDown() 
    10-14 09:03:14.155: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:03:14.155: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout 
    10-14 09:03:14.155: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:03:14.460: I/OuterView1(27776): OuterView1.onSingleTapConfirmed() 
    10-14 09:03:14.460: I/InnerView2(27776): InnerView2.onSingleTapConfirmed() 
    
  • Вторая попытка (только один вид получает onSingleTapConfirmed())

    10-14 09:04:11.615: I/OuterView1(27776): OuterView1.onDown() 
    10-14 09:04:11.615: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:04:11.615: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout 
    10-14 09:04:11.615: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:04:11.915: I/OuterView1(27776): OuterView1.onSingleTapConfirmed() 
    
  • Третья попытка (один вид получает onFling() и другой получает onSingleTapConfirmed())

    10-14 09:04:04.180: I/OuterView1(27776): OuterView1.onDown() 
    10-14 09:04:04.180: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:04:04.180: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout 
    10-14 09:04:04.180: I/InnerView2(27776): InnerView2.onDown() 
    10-14 09:04:04.255: I/InnerView2(27776): InnerView2.onFling() 
    10-14 09:04:04.480: I/OuterView1(27776): OuterView1.onSingleTapConfirmed() 
    

Не могли бы вы помочь мне захватить события прикосновения на обоих OuterView1 и InnerView2?

ответ

9

Так что в случае перекрывающихся видов - события касания отправляются от самого верхнего ребенка к одному сзади, затем еще один за вторым ребенком и так далее. Однако, если самый верхний ребенок должен был использовать событие касания (т. Е. Обрабатывать его при его получении), то представления под этим представлением не получат события касания.

Если onTouchEvent возвращает 'true', то он сообщает диспетчеру просмотра, что он обработал прикосновение и не хочет, чтобы событие отправлялось на другие виды. Если вы хотите, чтобы представление под этим представлением также получало прикосновение, вы хотите вернуть «false» из onTouchEvent для первого представления, в вашем случае - Innerview.

Кроме того, в вашем коде я заметил, что вы программно отправляете события касания на 2 вида из класса контейнера. Это приводит к тому, что InnerView получает прикосновение, даже когда ТОЛЬКО используется OuterView. Если вы хотите эту функциональность, тогда все в порядке. Если вы хотите, чтобы InnerView получал события только тогда, когда он был затронут, вы не хотите, чтобы класс контейнера вызывал onTouchEvent явно на этих двух представлениях. Иерархия представлений сделает это за вас.

О получении onFling или onSingleTapConfirmed on BOTH views - (если вы хотите, чтобы события касания также переходили к просмотрам, вы возвращаете «false» из onTouchEvent для InnerView), InnerView уже прошел событие к виду позади него, так что он не заканчивает жест, чтобы понять, что только что произошло, и аналогично для onSingleTapConfirmed. Если вы хотите получить их, вам, возможно, придется автоматически отправлять события касания в конце жестов, как было обнаружено OuterView. Смысл, если OuterView получил жестов fling, то это тоже был для InnerView, и поэтому программно сделать этот жест для InnerView. Это довольно сложно, и диспетчерские обращения назад в иерархии - это не обычная вещь.

Надеюсь, я не смутил вас на этом. Не стесняйтесь спрашивать, не ясно ли я, и попробую еще раз.

Это будет полезно: Handling TouchEvents in a ViewGroup

+0

Hi Mistwalker, Я хочу получить onFling(), onSingleTapConfirmed() на обоих видах. Я просто пытался использовать несколько вариантов, включая onInterceptTouchEvent. Я могу получить эту работу, если у меня есть ссылка на нижний вид сверху. ' \t private View outerView = null; \t public void setOuterView (Просмотреть внешний вид) { \t \t this.outerView = внешний вид; \t} \t \t @Override \t общественного логический onTouchEvent (MotionEvent событие) { \t \t gesture.onTouchEvent (событие); \t \t if (внешний вид! = Null) { \t \t \t внешний вид.onTouchEvent (событие); \t \t} \t \t return true; \t} ' @mistwalker Есть ли лучший способ достичь этого? –

+0

Код в моем предыдущем комментарии испорчен. Тот же код можно найти здесь: https://code.google.com/p/ramp-sample/source/browse/android/OverLayView/src/com/example/overlayview/InnerView2.java#55 –

+0

вы хотите сделать то же самое для 2 просмотров при обнаружении срабатывания/одиночного крана? Тогда было бы целесообразно положить их наложенными в FrameLayout и прослушивать жесты на этом FrameLayout. Иначе, если вы хотите делать разные вещи, когда одни и те же события касания наблюдаются на 2 представлениях, тогда да, вам придется отправлять программные события касания. Не уверен, есть ли другие способы достичь этого. – mistwalker

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