StaggeredGridLayoutManager
ne semble pas permettre de personnaliser une largeur de cellule ou de s'étendre sur plusieurs colonnes (sauf la pleine portée) pour une orientation verticale.
Quel est le LayoutManager
préféré pour organiser les cellules comme indiqué ci-dessus?
PS Je veux juste savoir comment personnaliser la largeur des cellules et non la hauteur avec StaggeredGridLayoutManager
. Je sais que la hauteur peut être personnalisée comme implémentée dans ce exemple .
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();
}
}
Adaptateur
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)
n'affecte pas la largeur des cellules.
Pour simplifier, je mets à jour ma disposition de grille en
Comment augmenter la largeur de la cellule 0 par rapport à la cellule 1 dans un StaggeredGridLayoutManager
ou tout autre gestionnaire de disposition?
Vous pouvez utiliser StaggeredGridLayoutManager.LayoutParams
pour modifier la largeur et la hauteur des cellules, ce que vous prévoyez de concevoir suit un modèle simple, si vous attribuez à chaque cellule un index (dans l'ordre que StaggeredGridLayoutManager
les organise par défaut), vous obtiendrez ceci:
index % 4 == 3 ---> full span cell
index % 8 == 0, 5 ---> half span cell
index % 8 == 1, 2, 4, 6 ---> quarter span cell
déclarez d'abord quelques constantes dans l'adaptateur pour définir les types d'étendue:
private static final int TYPE_FULL = 0;
private static final int TYPE_HALF = 1;
private static final int TYPE_QUARTER = 2;
Remplacez ensuite la méthode getItemViewType
dans votre adaptateur comme ceci:
@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;
}
Tout ce que vous devez faire est de modifier les paramètres de mise en page en tenant compte de viewType
du 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;
}
Mon adaptateur renvoie toujours 50 pour le nombre d'articles (juste un test) et j'ai utilisé un fichier de mise en page simple pour les articles, il contient un LinearLayout
et un TextView
pour montrer la position du titulaire, rappelez-vous que vous devriez passez 2 pour spanCount
(dans le constructeur StaggeredGridLayoutManager
) à cause de votre conception.
@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));
}
[~ # ~] ps [~ # ~] : Pour les paresseux comme moi, c'est peut-être un moyen plus simple que d'étendre ma coutume LayoutManager
, Mais je suis sûr qu'il existe de meilleures façons d'y parvenir.
Mise à jour : Une partie mise à jour de votre question est plus simple, vous pouvez utiliser 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);
De cette façon, vous définissez 3 pour la taille de travée par défaut, puis en considérant la position de votre travée, chaque élément occupe 1, 2 ou 3 travées, quelque chose comme ceci:
Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1.width
Pour tout le monde, à la recherche d'une solution sans simplifier votre mise en page, vous pouvez consulter ma réponse ici , ou vous pouvez en savoir plus.
Un grand merci à Nick Butcher ! Son gestionnaire de mise en page appelé SpannableGridLayoutManager
est capable de le faire.
Télécharger SpannableGridLayoutManager d'ici
Pour une raison quelconque, j'ai dû changer cette ligne:
while (availableSpace > 0 && lastVisiblePosition < lastItemPosition) {
à
while (lastVisiblePosition < lastItemPosition) {
pour faire travailler le manager.
Définissez SpannableGridLayoutManger sur votre RecyclerView
Dans ton cas:
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
);
Ce qui vous donnera exactement ce qu'il y a dans la première image de la question.