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.