2016-02-03 12 views
11

Utilizzo un layout di visualizzazione riciclato sfalsato per un elenco di foto. Voglio che la spaziatura sui lati sia zero mentre c'è ancora spazio tra le due colonne. Sto usando una sottoclasse di decorazione oggetto per ottenere la spaziatura vista nella foto allegata. So di avere il controllo sulla spaziatura destra e sinistra, ma il problema è che non so mai in quale colonna è inserita la foto. Sembra che il gestore di layout sfalsato esegua un po 'del proprio riordino. Ho provato a utilizzare getChildAdapterPosition ma sembra che restituisca la posizione nell'array dell'origine dati e non la posizione effettiva della foto nel layout. Qualche idea su come dovrei avvicinarmi a questo? enter image description hereCome determinare la posizione della colonna nel gestore di layout griglia sfalsato

+0

Questo è anche quello che sto cercando di capire. Il manager posiziona le visualizzazioni a seconda delle loro dimensioni e non sarai mai sicuro che per esempio le posizioni dispari saranno sulla sinistra e le posizioni pari saranno sulla destra. È così che ho provato a risolverlo nel mio decoratore di oggetti, controllando la posizione% 2 == 0 e quindi impostando il margine di rect.left ... ma non funziona così poiché in alcuni casi l'elemento con la posizione 6 può essere sul a destra ea volte a sinistra. – Tooroop

risposta

24

Sono riuscito a farlo funzionare. Quindi nel mio caso non ho bisogno di alcun bordo sui bordi sinistro e destro dello schermo. Avevo solo bisogno di bordi in mezzo e in fondo. La soluzione è ottenere i parametri di layout della vista che sono di tipo StaggeredGridLayoutManager.LayoutParams. In quei parametri puoi ottenere spanIndex che ti dice su quale indice è la vista. Quindi, se si dispone di uno spanCount di 2, la vista a sinistra avrà una spanIndex di 0 e la vista a destra avrà una spanIndex di 1.

Ecco il mio codice in modo forse vi aiuterà a

public class SpaceItemDecoration extends RecyclerView.ItemDecoration { 
private int space; 

public SpaceItemDecoration(int space) { 
    this.space = space; 
} 


@Override 
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
    int position = parent.getChildAdapterPosition(view); 

    StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams)view .getLayoutParams(); 
    int spanIndex = lp.getSpanIndex(); 

    if(position > 0){ 
     if(spanIndex == 1){ 
      outRect.left = space; 
     } else{ 
      outRect.right = space; 
     } 

     outRect.bottom = space * 2; 
    } 
} 

}

Nel mio caso prima devo ottenere la posizione poiché sull'indice 0 ho una vista di intestazione che non ha alcun bordo. Dopo di che ottengo l'indice span e in base ad esso ho impostato il bordo che mi serve su quella vista. E infine ho impostato il bordo inferiore su ogni vista.

+0

Grazie, ho cercato di hackerarlo per il mio layout, che ha un tipo di visualizzazione dell'intestazione, un tipo di visualizzazione dell'intestazione secondaria e un tipo di visualizzazione dell'elemento.Questa è una soluzione davvero elegante e funziona anche con GridLayoutManager. – kvgr

+0

Avete un esempio funzionante di questo codice? Ho provato nel mio progetto, per alcuni motivi che non capisco, spanIndex è sempre 0. Sembra che StaggeredGridLayoutManager chiama getItemOffsets prima che decida quale estensione si estende alla vista secondaria. – LiuJian

+0

Funziona come un fascino ................... – Vicky

2

quindi la soluzione che ho potuto usare è stato con un decoratore voce ma sicuramente è un po 'strana sensazione/hacky.

In pratica si regola il rettangolo esterno dell'elemento in base alla posizione della colonna (o qualcosa di simile). La mia comprensione è che il rettangolo esterno è più o meno la spaziatura che si desidera modificare. Dare il codice qui sotto una prova, ovviamente, avrete bisogno di fare le proprie regolazioni e la logica di 'Calcola' quale colonna l'articolo è su, ma questo dovrebbe essere sufficiente per capirlo, si spera:

recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 
     public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
      int left = outRect.left; 
      int right = outRect.right; 
      int top = outRect.top; 
      int bottom = outRect.bottom; 
      int idx = parent.getChildPosition(view); 
      int perRow = gridLayoutManager.getSpanCount(); 

      int adj = blahh... // some adjustment 

      if (idx < itemsPerRow) { 
       // on first row, adjust top if needed 
      } 

      if(idx % perRow == 0){ 
       // on first column, adjust. Left magically adjusts bottom, so adjust it too... 
       left += adj; 
       bottom -= adj; 
      } 

      if(idx % itemsPerRow == perRow - 1){ 
       // on last column, adjust. Right magically adjusts bottom, so adjust it too... 
       right += adjustment; 
       bottom -= adjustment; 
      } 

      outRect.set(left, top, right, bottom); 
     } 
    }); 

Anche in questo caso è hacky e richiede un po 'di prove ed errori per avere ragione.

Un'altra soluzione che ho provato con un certo successo è quella di definire viste diverse per le diverse colonne. Nel tuo caso le colonne avranno viste con margini negativi diversi, a sinistra ea destra per ottenere l'effetto desiderato.

Come nota a margine, presumo che si stia utilizzando un prospetto sulla vista del biglietto. Una cosa che ho notato è che se la vista della carta NON ha elevazione e invece la gestisci tu stesso (sì, lo so, non è il punto di non gestire l'elevazione tu stesso) gran parte di questa difficoltà scompare e le cose iniziano a comportarsi , probabilmente a causa dei calcoli di elevazione/ombra. Ma comunque ... Spero che questo sia almeno un po 'utile ...

+0

Ehi, dov'è riportato 'itemsPerRow'? Grazie –

Problemi correlati