2016-04-18 10 views
8

Ich versuche mit Parallax zu spielen und einige seltsame Bugs zu bekommen, frage mich, ob irgendjemand etwas Input hinzufügen kann. Die einzige App, die Parallax effektiv implementiert, ist Soundcloud. Es ist ziemlich subtil, aber jedes Element hat einen Bildhintergrund und es hat den Parallax-Effekt beim Scrollen.Parallax-Effekt für jedes Objekt in einer Recycler-Ansicht?

ich eine benutzerdefinierte RecyclerView zu handhaben erstellt haben, hier ist das, was ich bisher habe:

public class ParallaxScrollListener extends RecyclerView.OnScrollListener { 

private float scrollSpeed = 0.5f; 

@Override 
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
    super.onScrolled(recyclerView, dx, dy); 
    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); 

    int firstVisible = layoutManager.findFirstVisibleItemPosition(); 
    int visibleCount = Math.abs(firstVisible - layoutManager.findLastVisibleItemPosition()); 

    Matrix imageMatrix; 
    float tempSpeed = -100; 

    if (dy > 0) { 
     tempSpeed = scrollSpeed; 
    } else if (dy < 0) { 
     tempSpeed = -scrollSpeed; 
    } 

    for (int i = firstVisible; i < (firstVisible + visibleCount); i++) { 
     ImageView imageView = ((MyClass.MyAdapter.MyViewHolder) recyclerView.getLayoutManager().findViewByPosition(i).getTag()).image; 
     if (imageView != null) { 
      imageMatrix = imageView.getImageMatrix(); 
      imageMatrix.postTranslate(0, tempSpeed); 
      imageView.setImageMatrix(imageMatrix); 
      imageView.invalidate(); 
     } 
    } 
} 

In meinem RecyclerView Adapters onBindView Ich habe auch die folgenden Möglichkeiten:

Matrix matrix = viewHolder.image.getImageMatrix(); 
matrix.postTranslate(0, 0); 
viewHolder.image.setImageMatrix(matrix); 
viewHolder.itemView.setTag(viewHolder); 

Schließlich Innerhalb der onViewRecycled Methode habe ich folgendes:

@Override 
    public void onViewRecycled(MyViewHolder viewHolder) { 
     super.onViewRecycled(viewHolder); 
     if (viewHolder.image != null) { 
      viewHolder.image.setScaleType(ImageView.ScaleType.MATRIX); 
      Matrix matrix = viewHolder.image.getImageMatrix(); 
      // this is set manually to show to the center 
      matrix.reset(); 
      viewHolder.image.setImageMatrix(matrix); 
     } 
} 

I been working with this code on Github to get the idea

So funktioniert die Parallaxe, aber aber Ansichten in meinem RecyclerView bewegen sich auch. Ich habe ein CardView unter dem Bild und es bewegt sich, wodurch große Lücken zwischen den einzelnen Elementen entstehen. Scrollen ist das, was das verursacht, je mehr die Bildlaufbewegung nach oben und nach unten erfolgt, desto größer werden die Lücken, und die Bilder werden kleiner, wenn die Parallaxe sie aus ihren Grenzen bewegt.

Ich habe versucht, mit den Zahlen wie scrollSpeed ​​in der OnScrollListener zu verwirren, aber während es den Fehler reduziert, reduziert es auch die Parallaxe.

Hat jemand irgendwelche Ideen, wie ich einen fehlerfreien Parallaxeneffekt für jedes Element in meinem RecyclerView erreichen kann? Ich fühle mich, als würde ich etwas damit erreichen, aber es ist immer noch sehr buggy und ich weiß nicht, was der nächste Schritt ist.

Ps. Ich habe versucht, Bibliotheken von Drittanbietern zu suchen, aber sie alle scheinen nur Header-Parallaxe wie der CoordinatorLayout zu verwenden, ich habe keine gefunden, die es nur auf jedem Element in einer Liste tun.

Ich hoffe, dass diese Frage eine gute Diskussion bekommt, auch wenn ich mein Problem nicht lösen kann, weil Parallax in Android zu wenig genutzt wird und es sehr wenig darüber gibt.

Vielen Dank für Ihre Zeit, schätze jede Hilfe.

+0

Ist das Bild, das in jeder Ansicht parallaktisch sein soll, dasselbe? Oder möchten/können Sie es für jedes Element in 'onBindVH' einstellen? –

+0

Verschiedene Bilder, also müssen sie jedes Mal eingestellt werden. Ich habe eine Bibliothek gefunden, die es tut, wird meine Antwort bald posten. –

Antwort

4

ich Parallax Arbeit mit dieser Bibliothek erhalten verwaltet: https://github.com/yayaa/ParallaxRecyclerView

Für alle diese selbst zu tun, es ist immer noch eine gute Sache zu spielen und zu sehen, wie es funktioniert.

Ähnliche Konzept zu meinem Code, aber es funktioniert tatsächlich! Haha.

1

Sie sind auf dem richtigen Weg. Sie müssen einen ScrollListener verwenden. Außerdem müssen Sie auf RecyclerViews LayoutManager zugreifen und über alle sichtbaren Elemente iterieren und translateY entsprechend der Anzahl der gescrollten Pixel einstellen.

Die Dinge werden ein wenig komplizierter, weil Sie recyclerView.getChildAt(pos) nicht verwenden können, da der LayoutManager für das Layout von Elementen verantwortlich ist und sich im LayoutManager in einer anderen Reihenfolge als getChildAt(pos) befinden kann.

So sollte der Algorithmus im Grunde wie folgt aussehen (Pseudo-Code wird unter der Annahme, LinearLayoutManager verwendet):

for (int i = layoutManager.findFirstVisibleItemPosition(); i <= layoutmanager.findLastVisibleItemPosition; i++){ 

    // i is the adapter position 

    ViewHolder vh = recyclerView.findViewHolderForAdapterPosition(i); 
    vh.imageView.setTranslationY(computedParalaxOffset); // assuming ViewHolder has a imageView field on which you want to apply the parallax effect 
} 
+0

Danke für die Antwort. Habe ich das nicht schon? In meinem Scroll-Listener verwende ich den LinearLayoutManager, um die Ansichten zu berechnen. Die Verwendung von setTranslationY scheint auch nichts zu tun. postTranslate erzeugt die Parallaxe und funktioniert, aber ich habe immer noch den Fehler in meiner Frage. –

+0

Sie haben Recht, das habe ich übersehen. mein Fehler. Ihre Frage ist also im Grunde, wie man 'computedParalaxOffset' berechnet, oder? – sockeqwe

+0

Ich habe am Ende eine Bibliothek gefunden, die alles aussortieren konnte. Es scheint, als ob sie eine benutzerdefinierte Bildansicht benötigten, die ich nicht verwendete, was wahrscheinlich Teil meines Problems ist. –

Verwandte Themen