web-dev-qa-db-fra.com

Modification du nombre de colonnes dans RecyclerView gridlayout

J'essaie de modifier le nombre de colonnes qui apparaissent dans la vue du recycleur (disposition de la grille) en fonction de la taille d'affichage. Cependant, je ne pouvais pas trouver un moyen approprié d'y parvenir. Pour le moment, j'utilise treeViewObserver pour modifier le nombre de colonnes en fonction du changement de taille de l'écran (pendant l'orientation). Donc, si l'application s'ouvre en mode portrait, le nombre de colonnes (sur le téléphone) est choisi, ce qui est beau, mais cette méthode ne fonctionne pas lorsque l'application s'ouvre directement en mode paysage où une seule carte extirpée de la grille est affiché à l'écran.

Ici recList est RecyclerView & glm est GridLayoutManager utilisé dans RecyclerView

    viewWidth = recList.getMeasuredWidth();

    cardViewWidthZZ = recList.getChildAt(0).getMeasuredWidth();

    if (oldWidth == 0) {
        oldWidth = cardViewWidthZZ;
    }

    if (oldWidth <= 0)
        return;

    int newSpanCount = (int) Math.floor(viewWidth / (oldWidth / 1.3f));
    if (newSpanCount <= 0)
        newSpanCount = 1;
    glm.setSpanCount(newSpanCount);
    glm.requestLayout();

Meilleures salutations

16
Umer Farooq
public class VarColumnGridLayoutManager extends GridLayoutManager {

private int minItemWidth;

public VarColumnGridLayoutManager(Context context, int minItemWidth) {
    super(context, 1);
    this.minItemWidth = minItemWidth;
}

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler,
        RecyclerView.State state) {
    updateSpanCount();
    super.onLayoutChildren(recycler, state);
}

private void updateSpanCount() {
    int spanCount = getWidth() / minItemWidth;
    if (spanCount < 1) {
        spanCount = 1;
    }
    this.setSpanCount(spanCount);
}}
29
jasxir

Si vous fournissez une largeur de colonne fixe, vous pouvez étendre RecyclerView et définir le nombre d'étendues sur onMeasure en conséquence:

public AutofitRecyclerView(Context context, AttributeSet attrs) {
  super(context, attrs);

  if (attrs != null) {
    // Read Android:columnWidth from xml
    int[] attrsArray = {
        Android.R.attr.columnWidth
    };
    TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
    columnWidth = array.getDimensionPixelSize(0, -1);
    array.recycle();
  }

  manager = new GridLayoutManager(getContext(), 1);
  setLayoutManager(manager);
}

protected void onMeasure(int widthSpec, int heightSpec) {
  super.onMeasure(widthSpec, heightSpec);
  if (columnWidth > 0) {
    int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
    manager.setSpanCount(spanCount);
  }
}

Voir mon article de blog pour plus d'informations: http://blog.sqisland.com/2014/12/recyclerview-autofit-grid.html

15
chiuki

Voici ma solution.

public class ResponsiveGridLayoutManager extends GridLayoutManager {
    boolean hasSetupColumns;
    int columnWidthPx;

    public ResponsiveGridLayoutManager(Context context, int orientation,
        boolean reverseLayout, int columnWidthUnit, float columnWidth) {

        super(context, 1, orientation, reverseLayout);

        Resources r;
        if (context == null) {
            r = Resources.getSystem();
        } else {
            r = context.getResources();
        }

        float colWidthPx = TypedValue.applyDimension(columnWidthUnit,
            columnWidth, r.getDisplayMetrics());

        this.columnWidthPx = Math.round(colWidthPx);
    }

    public ResponsiveGridLayoutManager(Context context, AttributeSet attrs,
        int defStyleAttr, int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);
        int[] requestedValues = {
            Android.R.attr.columnWidth,
        };

        TypedArray a = context.obtainStyledAttributes(attrs, requestedValues);
        this.columnWidthPx = a.getDimensionPixelSize(0, -1);
        a.recycle();
    }

    @Override
    public int getWidth() {
        int width = super.getWidth();
        if (!hasSetupColumns && width > 0) {
            this.setSpanCount((int)Math.floor(width / this.columnWidthPx));
        }

        return width;
    }
}

Vous pouvez l'utiliser avec XML:

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/recycler"
    Android:scrollbars="vertical"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"

    app:layoutManager="com.caff.localflix.ResponsiveGridLayoutManager"
    Android:columnWidth="148dp" />

Ou Java:

ResponsiveGridLayoutManager layoutManager = new ResponsiveGridLayoutManager(
    this,
    GridLayoutManager.VERTICAL,
    false,
    TypedValue.COMPLEX_UNIT_DIP,
    148f
);
1
0xcaff

Vous pouvez créer un fichier de ressources dépendant de l'écran et le charger. Un booleans.xml dans le dossier values-w820p par exemple. Ou éventuellement, créez simplement une mise en page pour les grands écrans et terminez-la. 

0
Mark Miller