staggeredgridlayoutmanager - recyclerview android studio ejemplo
Cambiando el nĂºmero de columnas en RecyclerView gridlayout (4)
Estoy intentando cambiar el número de columnas que aparecen en la vista del reciclador (diseño de cuadrícula) según el tamaño de la pantalla. Sin embargo, no pude encontrar una manera adecuada de lograrlo. En este momento estoy usando treeViewObserver
para cambiar el número de columnas según el cambio en el tamaño de la pantalla (durante la orientación). Entonces, si la aplicación se abre en modo vertical, la cantidad de columnas (en el teléfono) decide ser una, lo que se ve bien, pero este método no funciona cuando la aplicación se abre directamente en modo horizontal, donde una única tarjeta estirada en la cuadrícula se muestra en la pantalla.
Aquí recList es RecyclerView y glm es GridLayoutManager utilizado en 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();
Atentamente
Aquí está mi solución.
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;
}
}
Puedes usarlo ya sea con 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" />
O Java:
ResponsiveGridLayoutManager layoutManager = new ResponsiveGridLayoutManager(
this,
GridLayoutManager.VERTICAL,
false,
TypedValue.COMPLEX_UNIT_DIP,
148f
);
Podría crear un archivo de recursos dependiente de la pantalla y cargarlo. Un archivo booleans.xml en la carpeta values-w820p, por ejemplo. O posiblemente solo cree un diseño para pantallas grandes y termine con él.
Si proporciona un ancho de columna fijo, puede ampliar RecyclerView
y establecer el recuento de intervalos en onMeasure
en consecuencia:
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);
}
}
Ver mi blog para más información: http://blog.sqisland.com/2014/12/recyclerview-autofit-grid.html
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);
}}