2016-04-09 13 views
14

StaggeredGridLayoutManager scheint keine Anpassung einer Zellenbreite zuzulassen oder mehrere Spalten (außer Vollspanne) für vertikale Ausrichtung zu überspannen.LayoutManager für RecyclerView Grid mit unterschiedlicher Zellenbreite

enter image description here

Was ist ein LayoutManager bevorzugte Zellen für die Organisation, wie oben gezeigt?

P.S. Ich möchte nur wissen, wie Zellenbreite anpassen und nicht Höhe mit StaggeredGridLayoutManager. Ich weiß, Höhe kann wie in dieser sample implementiert angepasst werden.

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

Adapter

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) wirkt sich nicht auf Zellenbreite.

zu vereinfachen, ich mein Grid-Layout zu

enter image description here

aktualisieren Wie Zelle 0 Breite zu erhöhen, wie 1 in einem StaggeredGridLayoutManager zu Zelle im Vergleich oder einem anderen Layout-Manager?

Antwort

31

können Sie StaggeredGridLayoutManager.LayoutParams verwenden, um die Breite und Höhe der Zellen zu ändern, Was erwarten Sie zu entwerfen ein einfaches Muster folgt, wenn Sie jede Zelle einen Index zuordnen (in der Reihenfolge, in StaggeredGridLayoutManager sie standardmäßig arrangiert), liegt diese haben:

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

zunächst einige Konstanten in Adapter deklarieren Spanne Typen zu definieren:

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

Dann getItemViewType Methode in Ihrem Adapter wie diese außer Kraft setzen:

@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; 
} 

Alles, was Sie tun müssen, ist layoutparams Änderung viewType der holder Berücksichtigung

@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; 
} 

Mein Adapter gibt immer 50 für Artikel (nur einen Test) zählen und ich für Elemente eine einfache Layout-Datei, Es enthält eine LinearLayout und eine TextView, um die Position des Halters zu zeigen, Denken Sie daran, Sie sollten 2 für spanCount (int StaggeredGridLayoutManager Konstruktor) aufgrund Ihres Designs passieren.

@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: für faule Leute wie mich vielleicht ist es ein einfacher Weg, anstatt erstreckt meine Gewohnheit LayoutManager, aber ich bin sicher, es gibt bessere Möglichkeiten, dies zu erreichen.

aktualisieren: Aktualisiert Teil Ihrer Frage ist einfacher, können Sie GridLayoutManager verwenden:

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

Auf diese Weise können Sie 3 für Standard-Spanne Größe festgelegt, dann die Position Ihrer Spanne unter Berücksichtigung Jeder Artikel belegt 1, 2 oder 3 Spannweiten, so etwas wie folgt aus:

enter image description here

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

Sind Sie in der Lage Zellenbreite auf 1/4 oder 3/4 oder sagen spezifische Größe in dp für ein Gitter mit Spannweite 2 Größe einstellen? Ich war in der Lage, benutzerdefinierte Höhe, aber nicht Breite mit staggeredgridlayoutmanager. Sie werden feststellen, dass die Zellen in meinem Bild in der ersten Zeile nicht die gleiche Breite haben. Ich werde deine Lösung auch in einiger Zeit versuchen und zurückkommen. – random

+0

Das ist genau das, was ich getan habe, wenn Sie die Methode "CreateViewHolder" aktiviert haben. –

+0

Können Sie den Code in Ihrer Antwort für das von mir bereitgestellte Rasterbild aktualisieren? Ich werde Ihre Lösung erst morgen ausprobieren können. – random

3

Für alle anderen, die nach einer Lösung suchen, ohne Ihr Layout zu vereinfachen, können Sie einen Blick auf my answer here werfen, oder Sie können mehr lesen.

Vielen Dank an Nick Butcher! Sein Layout Manager namens SpannableGridLayoutManager ist dazu in der Lage.

  1. Herunterladen SpannableGridLayoutManager from here

    Aus irgendeinem Grund habe ich diese Zeile ändern musste:

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

    zu

    while (lastVisiblePosition < lastItemPosition) { 
    

    den Manager bekam arbeiten.

  2. Set SpannableGridLayoutManger auf Ihre RecyclerView

In Ihrem Fall:

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

, die genau geben wird, was im ersten Bild von der Frage.

enter image description here

Verwandte Themen