2016-04-18 29 views
8

Sto provando a giocare con Parallax e ottenere alcuni bug strani, chiedendo se qualcuno può aggiungere qualche input ad esso. L'unica app che ho visto implementare la parallasse efficacemente è soundcloud. È piuttosto sottile, ma ogni oggetto ha uno sfondo di immagine e ha l'effetto di parallasse mentre scorri.Effetto Parallax su ogni elemento in una visualizzazione riciclatore?

ho creato un RecyclerView personalizzato per gestire questo, ecco cosa ho finora:

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(); 
     } 
    } 
} 

Nel mio RecyclerView dell'adattatore onBindView Ho la seguente così:

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

Infine all'interno del metodo onViewRecycled ho il seguente:

@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

Quindi la parallasse funziona, ma anche le visualizzazioni nel mio RecyclerView si spostano. Ho un CardView sotto l'immagine e si muove, creando grandi spazi tra ogni oggetto. Lo scorrimento è ciò che causa questo, più lo scorrimento sale e scende più grandi diventano gli spazi vuoti e le immagini diventano più piccole man mano che la parallasse le allontana dai loro limiti.

Ho provato a digitare i numeri come scrollSpeed ​​nello OnScrollListener ma mentre riduce il bug riduce anche la parallasse.

Qualcuno ha qualche idea su come posso ottenere un effetto di parallasse privo di bug su ciascun elemento nel mio RecyclerView? Mi sento come se stessi andando in qualche modo con questo, ma è ancora molto buggato e non so quale sia il prossimo passo.

P.s Ho provato a consultare le librerie di terze parti, ma sembra che tutti usino solo la parallasse di intestazione come CoordinatorLayout, non ho trovato nessuna che lo faccia solo su ogni elemento di una lista.

Spero che questa domanda diventi una buona discussione anche se non risolvo il mio problema perché Parallax sembra essere sottoutilizzato in Android e c'è poco intorno a questo.

Grazie per il vostro tempo, apprezzate qualsiasi aiuto.

+0

L'immagine deve essere parallasse allo stesso modo su ogni vista? O vuoi/devi essere in grado di impostarlo per ogni elemento in 'onBindVH'? –

+0

Immagini diverse, quindi sì, è necessario impostarle ogni volta. Ho trovato una libreria che lo fa, pubblicherà presto la mia risposta. –

risposta

4

sono riuscito ad ottenere Parallax lavorare con questa libreria: https://github.com/yayaa/ParallaxRecyclerView

per chiunque fare questo se stessi, è ancora una buona cosa suonare e vedere come funziona.

Simile concetto al mio codice ma in realtà funziona! haha.

1

Sei sulla strada giusta. Devi usare un ScrollListener. Inoltre, è necessario accedere a RecyclerViews LayoutManager e iterare su tutti gli elementi visibili e impostare translateY in base alla quantità di pixel scorrevoli.

Le cose diventano un po 'più complicate, perché non è possibile utilizzare recyclerView.getChildAt(pos) perché LayoutManager è responsabile per gli elementi di layout e potrebbero essere in ordine diverso nel LayoutManager di getChildAt(pos).

Quindi, l'algoritmo in pratica dovrebbe assomigliare a questa (pseudo codice, assumendo LinearLayoutManager è utilizzato):

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

Grazie per la risposta. Non è questo quello che ho già però? Nel mio ascoltatore di scroll sto usando LinearLayoutManager per calcolare le viste. Anche l'uso di setTranslationY non sembra fare nulla. postTranslate crea la parallasse e funziona ma ho ancora il bug delineato nella mia domanda. –

+0

Hai ragione, l'ho trascurato. colpa mia. Quindi la tua domanda è fondamentalmente come calcolare il valore di 'computedParalaxOffset', giusto? – sockeqwe

+0

Alla fine ho trovato una libreria in grado di sistemare tutto. Sembra che abbiano richiesto una visione d'immagine personalizzata che non stavo usando e che è probabilmente parte del mio problema. –