studio staggeredgridlayoutmanager recyclerview gridlayout ejemplo cardview android android-orientation android-gridlayout android-recyclerview

android - staggeredgridlayoutmanager - Cambio del número de columnas con GridLayoutManager y RecyclerView



recyclerview gridlayout (7)

Dentro de mi fragmento, estoy configurando mi GridLayout de la siguiente manera: mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));

Entonces, solo quiero cambiar ese 2 por un 4 cuando el usuario gira el teléfono / tableta. He leído sobre onConfigurationChanged y traté de que funcione para mi caso, pero no está yendo de la manera correcta. Cuando giro mi teléfono, la aplicación falla ...

¿Podría decirme cómo resolver este problema?

Aquí está mi enfoque para encontrar la solución, que no funciona correctamente:

@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); int orientation = newConfig.orientation; if (orientation == Configuration.ORIENTATION_PORTRAIT) { mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2)); } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) { mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4)); } }

¡Gracias por adelantado!


En el evento onCreate () puede usar StaggeredGridLayoutManager

mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerView); mStaggeredGridLayoutManager = new StaggeredGridLayoutManager( 1, //number of grid columns GridLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);

Luego, cuando el usuario gire la pantalla, capture el evento y cambie el número de columnas automáticamente

@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { mStaggeredGridLayoutManager.setSpanCount(1); } else { //show in two columns mStaggeredGridLayoutManager.setSpanCount(2); } }


Intente manejar esto dentro de su método onCreateView, ya que se llamará cada vez que haya un cambio de orientación:

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2)); } else{ mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4)); }


La vista de reciclaje admite AutofitRecycleView.

android:numColumns="auto_fit" agregar android:numColumns="auto_fit" en su archivo xml.

Puede referirse a este AutofitRecycleViewLink


Puede implementar el método en su recyclerView onMeasure. Primero, cree la clase java AutofitRecyclerView

public class AutofitRecyclerView extends RecyclerView { //private GridLayoutManager manager; private StaggeredGridLayoutManager manager; private int columnWidth = -1; public AutofitRecyclerView(Context context) { super(context); init(context, null); } public AutofitRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs); } private void init(Context context, AttributeSet attrs) { if (attrs != null) { int[] attrsArray = { android.R.attr.columnWidth }; TypedArray array = context.obtainStyledAttributes(attrs, attrsArray); columnWidth = array.getDimensionPixelSize(0, -1); array.recycle(); } manager = new StaggeredGridLayoutManager(1, GridLayoutManager.VERTICAL); setLayoutManager(manager); } @Override protected void onMeasure(int widthSpec, int heightSpec) { super.onMeasure(widthSpec, heightSpec); if (columnWidth > 0) { int spanCount = Math.max(1, getMeasuredWidth() / columnWidth); manager.setSpanCount(spanCount); } }}

En su archivo de diseño xlm activity_main.xml

<yourpackagename.AutofitRecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:columnWidth="@dimen/column_width" android:clipToPadding="false"/>

Luego configure la variable al ancho de cada elemento en el tamaño del archivo de la carpeta de valores values ​​/ dimens.xml

<resources> <dimen name="column_width">250dp</dimen> </resources>

Puede ser para diferentes resoluciones de pantalla valores-xxhdpi / dimens.xml

<resources> <dimen name="column_width">280dp</dimen> </resources>

En su actividad en el evento onCreate, coloque el siguiente código

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); recyclerView.addItemDecoration(new MarginDecoration(this)); recyclerView.setHasFixedSize(true); recyclerView.setAdapter(new NumberedAdapter(50)); }


Si tiene más de una condición o usa el valor en varios lugares, esto puede salirse de control bastante rápido. Sugiero crear la siguiente estructura:

res - values - dimens.xml - values-land - dimens.xml

con res/values/dimens.xml siendo:

<?xml version="1.0" encoding="utf-8"?> <resources> <integer name="gallery_columns">2</integer> </resources>

y res/values-land/dimens.xml es:

<?xml version="1.0" encoding="utf-8"?> <resources> <integer name="gallery_columns">4</integer> </resources>

Y el código se convierte (y permanece para siempre) así:

final int columns = getResources().getInteger(R.integer.gallery_columns); mRecycler.setLayoutManager(new GridLayoutManager(mContext, columns));

Puede ver fácilmente lo fácil que es agregar nuevas formas de determinar el recuento de columnas, por ejemplo, utilizando las carpetas de recursos -w500dp / -w600dp / -w700dp lugar de -land .

También es bastante fácil agrupar estas carpetas en una carpeta de recursos separada en caso de que no desee saturar sus otros recursos (más relevantes):

android { sourceSets.main.res.srcDir ''src/main/res-overrides'' // add alongside src/main/res }


Terminé manejando esto en el método onCreate.

private RecyclerView recyclerView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); recyclerView.setHasFixedSize(true); Configuration orientation = new Configuration(); if(this.recyclerView.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); } else if (this.recyclerView.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { recyclerView.setLayoutManager(new GridLayoutManager(this, 4)); } connectGetApiData(); }

Funcionó perfectamente para mi aplicación.


Una forma más robusta de determinar el no. de columnas sería calcularlo en función del ancho de la pantalla y en tiempo de ejecución. Normalmente uso la siguiente función para eso.

public static int calculateNoOfColumns(Context context) { DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); float dpWidth = displayMetrics.widthPixels / displayMetrics.density; int scalingFactor = 200; // You can vary the value held by the scalingFactor // variable. The smaller it is the more no. of columns you can display, and the // larger the value the less no. of columns will be calculated. It is the scaling // factor to tweak to your needs. int columnCount = (int) (dpWidth / scalingFactor); return (columnCount>=2?columnCount:2); // if column no. is less than 2, we still display 2 columns }

Es un método más dinámico para calcular con precisión el no. de columnas Esto será más adaptable para usuarios de diferentes tamaños de pantalla sin restringirse a solo dos valores posibles.

NB: puede variar el valor que posee la variable scalingFactor . Cuanto más pequeño es, más no. de columnas que puede mostrar, y cuanto mayor sea el valor, menos no. de columnas se calculará. Es el factor de escala para ajustar a sus necesidades.