2015-07-21 8 views
7

Wie kann ich die Ansicht finden, die ein MotionEvent ACTION_CANCEL verursacht? Ich habe eine Ansicht "A", die ACTION_CANCEL empfängt und ich möchte nicht, dass das passiert. Irgendwo "verbraucht" eine Ansicht "B" das MotionEvent. Ich hoffe, dass es einen Weg gibt, herauszufinden, wer "B" ist, damit ich diese Fehlfunktion angehen kann.So finden Sie die Quellansicht eines MotionEvent ACTION_CANCEL

Ich habe versucht, durch meinen Code für verschiedene OnTouchEvent() und OnInterceptTouchEvent() Handler zu suchen, aber noch keinen Schuldigen gefunden.

Ich habe auch einen Breakpoint an der problematischen ACTION_CANCEL gesetzt, kann aber nichts im MotionEvent erkennen, das "B" darstellen könnte.

+0

Erhalten Sie das erste "ACTION_DOWN" -Ereignis? – Barend

+0

Ja, und eine Reihe von ACTION_MOVE. –

+0

Ich wollte Sie fragen, ob Sie unter dem ersten Event nur die View sehen könnten, aber ich habe inzwischen gemerkt, dass das nicht helfen wird, also machen Sie sich nichts daraus, tut mir leid. – Barend

Antwort

2

Wenn Ihre Frage korrekt ist, erhalten Sie wahrscheinlich in der übergeordneten und Sie müssen diese Ansicht finden. Bei gegebenem Ereignis X und Y können Sie eine Ansicht finden, die diese Koordinaten zum ersten Mal enthält, aufgetreten ist. Versuchen Sie, diese Methode entweder mit dem obersten Elternteil (android.R.id.content) oder dem ViewGroup, mit dem Sie zu tun haben, aufzurufen.

private View findViewAt(View contentView, int eventX, int eventY) { 
      ArrayList<View> unvisited = new ArrayList<View>(); 
      unvisited.add(contentView); 
      while (!unvisited.isEmpty()) { 
       View child = unvisited.remove(0); 
       if(isViewContains(child, eventX, eventY) { 
        Log.i(TAG, "view found! "); 
        unvisited.clear(); 
        return child; 
       } 
       if (!(child instanceof ViewGroup)){ 
        continue; 
       } 
       ViewGroup group = (ViewGroup) child; 
       final int childCount = group.getChildCount(); 
       for (int i=0; i< childCount; i++){ 
        unvisited.add(group.getChildAt(i)); 
       } 
      } 
     return null; 
    } 


private boolean isViewContains(View view, int eventX, int eventY) { 
    int[] location = new int[2]; 
    view.getLocationOnScreen(location); 
    int x = location[0]; 
    int y = location[1]; 
    int width = view.getWidth(); 
    int height = view.getHeight(); 
    return eventX < x || eventX > x + width || eventY < y || eventY > y + height; 
} 
+0

Das ist eine gute Idee. Allerdings zwei Kommentare. (1) Sind nicht eventX, eventY in sicht-lokalen Koordinaten? Damit isViewContains() funktioniert, benötigen wir Bildschirmkoordinaten. (2) Ich denke, dass der Algorithmus direkt mit einem Baumspaziergang durchgeführt werden kann - keine Notwendigkeit für eine Warteschlange - oder fehlt mir etwas. –

+0

Dadurch werden alle Ansichten in der Hierarchie durchlaufen. –

+0

Einverstanden, obwohl Punkt 2 immer noch gilt. Unabhängig davon ist Punkt 1 der entscheidende Punkt. Wenn eventX, eventY in lokalen Koordinaten sind, sehe ich keine Möglichkeit zu sagen, aus welcher Sicht sie stammen. –

1

Auf meiner Erfahrung, ein Fall, der eine Ansicht eines ACTION_CANCEL Ereignis erhalten macht, ist nach A von Nutzern berührt und sie zieht ihre Finger aus Bereich A, Wenn Sie diesen Fall konfrontiert, Fügen Sie eine Methode zu überprüfen Die Position auf dispatchTouchEvent() kann helfen.

6

Wenn ein übergeordnetes Element das Bewegungsereignis abfängt, kann dies nur verhindert werden, indem verhindert wird, dass das übergeordnete Objekt dieses Ereignis abfängt. Dies kann auf zwei Arten gut verwaltet werden.

Ohne spezifischen Code zu sehen und eine generalisierte Lösung zu wollen, würde ich Folgendes vorschlagen.

Ich würde vorschlagen, Ihre Touch-Ereignisse für die Eltern und das Kind der Verwaltung durch die Verwaltung der
requestDisallowInterceptTouchEvent(boolean) und

onInterceptTouchEvent(android.view.MotionEvent) Event-Handler jeder Ansicht/Viewgroup in den betroffenen Ansichten A, B C.

von Wenn Sie Elternabschnitte im Kind nicht zulassen, hilft dies Ihnen dabei, Elternabschnitte abzufangen, die Sie nicht berücksichtigt haben, und auch die untergeordneten Elemente innerhalb eines Elternteils anzupassen und zu variieren.

Dies muss von Ihrem obersten übergeordneten Element Ihrer view/viewGroup verwaltet und über alle untergeordneten und untergeordneten Beziehungen verwaltet werden.

Auf Listviews überprüfen, jedes Element, das eine integrierte Touch-Ereignisse hat.

zu Kind Ansicht

Gehen Sie durch die einzelnen Eltern auf das Kind/Eltern:

android.com/training/gestures/viewgroup

In Bezug auf die problematische Ansicht zu finden, die das Ereignis abfängt, dass mit Ausnahme von der Logik der kann nicht beantwortet werden. Überprüfen Sie methodisch die Handhabung von ontouch in jeder Ansicht/Ansichtsgruppe wie in meinem Diagramm gezeigt.

View diagram

Es gibt einige weiteren Details in diesen Antworten hier:
https://stackoverflow.com/a/30966413/3956566
https://stackoverflow.com/a/6384443/3956566

Ich bin sicher, dass Sie das verstehen, aber für mich, es ist die einfachste Lösung.

Darüber hinaus müssen wir uns Ihren Code anschauen, um Fehler zu beheben.

+0

zurück Nun, es scheint, dass die Antwort auf meine Frage lautet: "Es gibt kein direktes Methode". Mit anderen Worten, zu dem Zeitpunkt, zu dem ACTION_CANCEL von einer beliebigen Ansicht empfangen wird, ist die Quelle von ACTION_CANCEL verloren. Schade. Ich schätze Ihre vorgeschlagene Methodik und es ist in der Tat mehr oder weniger, was ich getan habe - im Grunde die Kette der Eltern zu sehen, wer abbrechen könnte. Sehr wenig davon ist mein Code (es sind Android-Layouts und Widgets), so dass es schwierig wird, durch "fremden" Quellcode zu surfen, um auf den ACTION_CANCEL-Ursprung zu spekulieren. –

+0

Ich habe nicht wirklich das Gefühl, dass du die Frage beantwortet hast, aber du bist am nächsten gekommen und hast dich sehr angestrengt. Ich hasse es, auch die Kopfgelder zu sehen. Also, Prost! –

+0

@PeriHartman Danke! Ich weiß, dass ich diese spezielle Lösung für dich nicht bekommen habe, ich mochte und habe die andere Antwort aufgefrischt.Du hast mir Denkanstöße gegeben und wenn ich mir einen Weg durch den View Tree mache, werde ich updaten und dich wissen lassen. –

Verwandte Themen