2011-01-01 10 views
5

Das Ziel besteht darin, eine Gallery zu implementieren, deren Adapter ListViews zurückgibt (mit anderen Worten, vertikal scrollende ListViews, die in einer horizontal scrollenden Gallery eingebettet sind). Es funktioniert nach ein bisschen Arbeit, aber wenn man versucht, horizontal zu scrollen, sieht das ListView sehr nervös aus, als ob es eine gewisse Klebrigkeit dafür wäre, zentriert zu sein. Ich habe dieses Verhalten mit keinem anderen in einer Galerie eingebetteten View beobachtet. HierEinbetten von ListView in Gallery

ist, was ich habe versucht:

Am Anfang fand ich, dass die Listview-Touch-Ereignisse zerquetscht, so dass die Geste Zuhörer auf der Galerie wird nie ausgelöst.

So in der onCreate() -Methode der Aktivität, habe ich eine GestureDetector:

galleryGestureDetector = new GestureDetector(this, gallery);

Dann in dem getView() -Methode des Galerie-Adapters, nachdem der Listview aufgeblasen und konfiguriert wurde ich habe einige Code wie folgt aus:

listView.setOnTouchListener(new OnTouchListener() { 
    public boolean onTouch(View v, MotionEvent event) { 
     galleryGestureDetector.onTouchEvent(event); 
     return true; 
    } 
}); 

In diesem Fall habe ich auch bis zum äußersten Schritt wahr gegangen sind vom OnTouchListener zurückzukehren, um sicherzustellen, dass die onTouchEvent() -Methode des Listview wird eigentlich nie genannt. Das gleiche nervöse Verhalten tritt auf. Als Ergebnis kann ich ausschließen, dass konkurrierende touchEvent() - Implementierungen zwischen den beiden Ansichten möglich sind.

Ich habe versucht, das TouchDelegate-Konzept auch zu missbrauchen, indem ich das Touch-Rechteck der Galerie um die ListView erweitert und dann die ListView gezwungen habe, zu delegieren, aber das war auch ein vergeblicher Versuch.

Ich würde meine Hände werfen und sagen, dass es derzeit nicht möglich ist, aber die Social Networking App, die mit dem DroidX packt, schafft es irgendwie!

+0

Überprüfen Sie, ob Ihre Listenansichten nicht jedes Mal, wenn die Galerie gerendert wird, Tonnen von Ansichten erstellen/aufblasen. Versuchen Sie, sie zu cachen (oder verwenden Sie nur ein einzelnes statisches Feld), nur um zu sehen, ob das das Problem ist. – monkjack

+0

Guter Gedanke Monkjack, und in der Tat sieht es so aus, als würde die Galerie die ListViews, die von ihrem Adapter zurückgegeben wurden, wiederverwenden, nachdem sie nicht mehr in der Auswahl waren. Ich habe versucht, die Ansichten so zu speichern, wie Sie vorgeschlagen und überprüft haben, dass von den drei Elementen, die ich verwende, um Lösungen für dieses Problem zu testen, nur 3 Ansichten jemals aufgeblasen werden. Leider sehe ich das gleiche Ergebnis ... Nachdem die Ansicht über eine kleine Menge rutscht, fängt es an zu zittern wie verrückt. – jkschneider

+0

Noch mysteriöser - Ich habe heute bemerkt, dass die Galerie manchmal zwischen zwei Ansichten stecken bleibt, wenn ich weiterhin versuche, horizontal zu scrollen, nachdem der ListView zu zittern begonnen hat. – jkschneider

Antwort

5

Das Problem ist, dass ListView Touch-Ereignisse aus der Galerie abfangen und dann die Ansichtsposition selbst ändern. Dies führt zu dem hin und her wackelnden Effekt, den ich sehe, wenn ich die Widgets so verwende, wie es ist. Ich halte dies für einen Fehler in der Galerie-Widget, aber in der Zwischenzeit kann es durch Subklassen Galerie wie folgt festgesetzt:

public class BetterGallery extends Gallery { 
private boolean scrollingHorizontally = false; 

public BetterGallery(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
} 

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

public BetterGallery(Context context) { 
    super(context); 
} 

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    super.onInterceptTouchEvent(ev); 
    return scrollingHorizontally; 
} 

@Override 
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
    scrollingHorizontally = true; 
    return super.onScroll(e1, e2, distanceX, distanceY); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch(event.getAction()) { 
    case MotionEvent.ACTION_UP: 
    case MotionEvent.ACTION_CANCEL: 
     scrollingHorizontally = false; 
    } 

    return super.onTouchEvent(event); 
} 

}

Wenn Sie BetterGallery anstelle der Galerie zu verwenden, das Ganze funktioniert einfach fein!