2016-04-09 20 views
14

StaggeredGridLayoutManager non sembra consentire la personalizzazione di una cella larghezza o di più colonne (tranne la campata intera) per l'orientamento verticale.LayoutManager per RecyclerView Grid con larghezza cella diversa

enter image description here

quello che è un preferito LayoutManager per l'organizzazione di cellule come indicato sopra?

P.S. Voglio solo sapere come personalizzare la cella larghezza e non l'altezza con StaggeredGridLayoutManager. So che l'altezza può essere personalizzata come implementata in questo sample.

public class VerticalStaggeredGridFragment extends RecyclerFragment { 

    public static VerticalStaggeredGridFragment newInstance() { 
     VerticalStaggeredGridFragment fragment = new VerticalStaggeredGridFragment(); 
     Bundle args = new Bundle(); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    protected RecyclerView.LayoutManager getLayoutManager() { 
     return new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 
    } 

    @Override 
    protected RecyclerView.ItemDecoration getItemDecoration() { 
     return new InsetDecoration(getActivity()); 
    } 

    @Override 
    protected int getDefaultItemCount() { 
     return 100; 
    } 

    @Override 
    protected SimpleAdapter getAdapter() { 
     return new SimpleStaggeredAdapter(); 
    } 
} 

adattatore

public class SimpleStaggeredAdapter extends SimpleAdapter { 
    @Override 
    public void onBindViewHolder(VerticalItemHolder itemHolder, int position) { 
     super.onBindViewHolder(itemHolder, position); 

     final View itemView = itemHolder.itemView; 
     if (position % 4 == 0) { 
      int height = itemView.getContext().getResources() 
        .getDimensionPixelSize(R.dimen.card_staggered_height); 
      itemView.setMinimumHeight(height); 
     } else { 
      itemView.setMinimumHeight(0); 
     } 
    } 
} 

itemView.setMinimumWidth(customWidth) non influisce larghezza della cella.

Per semplificare, aggiorno il mio layout di griglia per

enter image description here

Come aumentare cella 0 larghezza rispetto alla cella 1 in una StaggeredGridLayoutManager o altro gestore di layout?

risposta

31

È possibile utilizzare StaggeredGridLayoutManager.LayoutParams per modificare la larghezza e l'altezza delle celle, cosa ci si aspetta per la progettazione segue un modello semplice, se si assegna ogni cellula un indice (nell'ordine in cui StaggeredGridLayoutManager li organizza per impostazione predefinita) si avrà questo:

index % 4 == 3   ---> full span cell 
index % 8 == 0, 5  ---> half span cell 
index % 8 == 1, 2, 4, 6 ---> quarter span cell 

prima dichiarare alcune costanti in adattatore per definire i tipi di span:

private static final int TYPE_FULL = 0; 
private static final int TYPE_HALF = 1; 
private static final int TYPE_QUARTER = 2; 

poi sovrascrivere getItemViewType metodo nella scheda come questa:

@Override 
public int getItemViewType(int position) { 
    final int modeEight = position % 8; 
    switch (modeEight) { 
     case 0: 
     case 5: 
      return TYPE_HALF; 
     case 1: 
     case 2: 
     case 4: 
     case 6: 
      return TYPE_QUARTER; 
    } 
    return TYPE_FULL; 
} 

Tutto quello che dovete fare è cambiare layoutparams considerando viewType del holder:

@Override 
public MyHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { 
    final View itemView = 
      LayoutInflater.from(mContext).inflate(R.layout.items, parent, false); 
    itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
     @Override 
     public boolean onPreDraw() { 
      final int type = viewType; 
      final ViewGroup.LayoutParams lp = itemView.getLayoutParams(); 
      if (lp instanceof StaggeredGridLayoutManager.LayoutParams) { 
       StaggeredGridLayoutManager.LayoutParams sglp = 
         (StaggeredGridLayoutManager.LayoutParams) lp; 
       switch (type) { 
        case TYPE_FULL: 
         sglp.setFullSpan(true); 
         break; 
        case TYPE_HALF: 
         sglp.setFullSpan(false); 
         sglp.width = itemView.getWidth()/2; 
         break; 
        case TYPE_QUARTER: 
         sglp.setFullSpan(false); 
         sglp.width = itemView.getWidth()/2; 
         sglp.height = itemView.getHeight()/2; 
         break; 
       } 
       itemView.setLayoutParams(sglp); 
       final StaggeredGridLayoutManager lm = 
         (StaggeredGridLayoutManager) ((RecyclerView) parent).getLayoutManager(); 
       lm.invalidateSpanAssignments(); 
      } 
      itemView.getViewTreeObserver().removeOnPreDrawListener(this); 
      return true; 
     } 
    }); 

    MyHolder holder = new MyHolder(itemView); 
    return holder; 
} 

La mia scheda restituisce sempre il 50 per contare gli elementi (solo un test) e ho usato un file di layout semplice per gli oggetti, Contiene un LinearLayout e un TextView per mostrare la posizione del titolare, Ricorda che devi passare 2 per spanCount (int con il costruttore StaggeredGridLayoutManager) a causa del tuo progetto.

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    RecyclerView rv = (RecyclerView) findViewById(R.id.rv); 
    StaggeredGridLayoutManager lm = 
      new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 
    rv.setLayoutManager(lm); 
    rv.setAdapter(new MyAdapter(this)); 

} 

enter image description here

PS: per i più pigri come me forse è un modo più semplice, piuttosto che estendere il mio personalizzato LayoutManager, ma sono sicuro che ci sono modi migliori per raggiungere questo obiettivo.

Aggiornamento: Aggiornato parte della tua domanda è più semplice, è possibile utilizzare GridLayoutManager:

GridLayoutManager glm = new GridLayoutManager(this, 3); 
    glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 
     @Override 
     public int getSpanSize(int position) { 
      if (position % 3 == 2) { 
       return 3; 
      } 
      switch (position % 4) { 
       case 1: 
       case 3: 
        return 1; 
       case 0: 
       case 2: 
        return 2; 
       default: 
        //never gonna happen 
        return -1 ; 
      } 
     } 
    }); 
    rv.setLayoutManager(glm); 

In questo modo si imposta 3 per le dimensioni lasso di default, quindi considerando la posizione del vostro arco, ogni elemento occupa 1, 2 o 3 campate, Qualcosa di simile:

enter image description here

Item0.width == 2 X Item1.width 
Item2.width == 3 X Item1.width 
Item0.width == 2/3 X Item1.width 
+0

Siete in grado di impostare larghezza della cella a 1/4 o 3/4 o dicono dimensione specifica in dp per una griglia con dimensioni arco di 2? Sono stato in grado di impostare l'altezza personalizzata ma non la larghezza con scaglionedgridlayoutmanager. Noterai che le celle nella mia immagine non sono di uguale larghezza nella prima riga. Proverò anche la tua soluzione tra qualche tempo e tornerò. – random

+0

Questo è esattamente ciò che ho fatto se si verifica il metodoCreateViewHolder. –

+0

È possibile aggiornare il codice nella risposta per l'immagine della griglia che ho fornito? Non sarò in grado di provare la tua soluzione fino a domani. – random

3

Per tutti gli altri, alla ricerca di una soluzione senza semplificare il layout, è possibile dare un'occhiata a my answer here oppure è possibile leggere ulteriori informazioni.

Grazie mille a Nick Butcher! Il suo gestore di layout chiamato SpannableGridLayoutManager è in grado di farlo.

  1. Scarica SpannableGridLayoutManager from here

    Per qualche motivo ho dovuto cambiare questa linea:

    while (availableSpace > 0 && lastVisiblePosition < lastItemPosition) { 
    

    a

    while (lastVisiblePosition < lastItemPosition) { 
    

    al ottenuto il manager che lavora.

  2. Set SpannableGridLayoutManger al RecyclerView

Nel tuo caso:

SpannedGridLayoutManager manager = new SpannedGridLayoutManager(
      new SpannedGridLayoutManager.GridSpanLookup() { 
       @Override 
       public SpannedGridLayoutManager.SpanInfo getSpanInfo(int position) { 
        switch (position % 8) { 
         case 0: 
         case 5: 
          return new SpannedGridLayoutManager.SpanInfo(2, 2); 

         case 3: 
         case 7: 
          return new SpannedGridLayoutManager.SpanInfo(3, 2); 

         default: 
          return new SpannedGridLayoutManager.SpanInfo(1, 1); 
        } 
       } 
      }, 
      3, // number of columns 
      1f // default size of item 
    ); 

che vi darà esattamente ciò che è nella prima immagine della questione.

enter image description here

Problemi correlati