Changement du nombre de colonnes avec GridLayoutManager et RecyclerView
a L'intérieur de mon fragment je mets mon GridLayout de la manière suivante:
mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));
Donc, je veux juste changer 2
4
lorsque l'utilisateur fait pivoter le téléphone/tablette. J'ai lu sur onConfigurationChanged
et j'ai essayé de faire en sorte que ça marche pour mon affaire, mais ça ne va pas dans le bon sens. Quand je tourne mon téléphone, l'application se bloque...
Pourriez-vous me dire comment résoudre ce problème?
Voici mon approche pour trouver la solution, qui ne fonctionne pas correctement:
@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));
}
}
Merci d'avance!
7 réponses
essayez de gérer cela dans votre méthode onCreateView à la place car il sera appelé chaque fois qu'il y a un changement d'orientation:
if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
}
else{
mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
}
si vous avez plus d'une condition ou utilisez la valeur dans plusieurs endroits cela peut devenir hors de contrôle assez rapidement. Je suggère de créer la structure suivante:
res
- values
- dimens.xml
- values-land
- dimens.xml
res/values/dimens.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="gallery_columns">2</integer>
</resources>
et res/values-land/dimens.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="gallery_columns">4</integer>
</resources>
Et le code devient alors (et toujours séjours) comme ceci:
final int columns = getResources().getInteger(R.integer.gallery_columns);
mRecycler.setLayoutManager(new GridLayoutManager(mContext, columns));
Vous pouvez facilement voir combien il est facile d'ajouter de nouvelles façons de déterminer le nombre de colonnes, par exemple à l'aide de -w500dp
/-w600dp
/-w700dp
dossiers de ressources au lieu de -land
.
il est aussi assez facile de regrouper ces dossiers dans des dossiers de ressources séparés au cas où vous ne voudriez pas encombrer vos autres ressources (plus pertinentes):
android {
sourceSets.main.res.srcDir 'src/main/res-overrides' // add alongside src/main/res
}
La Vue Recycle supporte la vue AutofitRecycleView.
Vous devez ajouter android:numColumns="auto_fit"
dans votre fichier xml.
vous pouvez Vous référer à ce AutofitRecycleViewLink
une façon plus robuste de déterminer le non. de colonnes serait de le calculer basé sur la largeur de l'écran et à l'exécution. J'utilise normalement la fonction suivante pour cela.
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
}
C'est une méthode dynamique pour calculer avec précision le pas. des colonnes. Ce sera plus souple pour les utilisateurs de différentes tailles d'écran sans être réglementé à seulement deux valeurs possibles.
NB: Vous pouvez varier la valeur détenue par le scalingFactor variable. Plus il est petit, plus il est non. des colonnes que vous pouvez afficher, et plus la valeur est grande moins Non. des colonnes sera calculée. Il est le facteur d'échelle pour l'ajuster à vos besoins.
mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(
1, //number of grid columns
GridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);
puis quand l'utilisateur tourne l'écran capturez l'événement, et changez le nombre de colonnes automatiquement
@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);
}
}
j'ai fini par gérer ça dans la méthode 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();
}
cela a parfaitement fonctionné pour mon application.
vous pouvez implémenter la méthode dans votre recyclerView onMeasure. Tout d'abord, créez la classe 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);
}
}}
dans votre fichier de mise en page 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"/>
puis définissez la variable à la largeur de chaque élément dans la taille de fichier du dossier valeurs valeurs/dimensions.xml
<resources>
<dimen name="column_width">250dp</dimen>
</resources>
il peut être pour des résolutions d'écran différentes valeurs-xxhdpi / dimensions.xml
<resources>
<dimen name="column_width">280dp</dimen>
</resources>
dans votre activité dans le lieu de l'événement code suivant
@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));
}