web-dev-qa-db-fra.com

Changer le nombre de colonnes avec GridLayoutManager et RecyclerView

Dans mon fragment, je configure GridLayout de la manière suivante: mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));

Donc, je veux juste changer cela 2 pour un 4 lorsque l'utilisateur fait pivoter le téléphone/la tablette. J'ai lu sur onConfigurationChanged et j'ai essayé de le faire fonctionner pour mon cas, mais ça ne se passe pas comme prévu. Lorsque 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!

54
fapps

Essayez plutôt de gérer cela dans votre méthode onCreateView, car elle sera appelée à chaque changement d'orientation:

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

Si vous avez plus d'une condition ou utilisez la valeur à plusieurs endroits, cela peut rapidement vous échapper. Je suggère de créer la structure suivante:

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

avec res/values/dimens.xml étant:

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

et res/values-land/dimens.xml étant:

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

Et le code devient alors (et reste pour toujours) comme ceci:

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

Vous pouvez facilement constater à quel point il est facile d’ajouter de nouveaux moyens de déterminer le nombre de colonnes, par exemple en utilisant -w500dp/-w600dp/-w700dp dossiers de ressources au lieu de -land.

Il est également assez facile de regrouper ces dossiers dans un dossier de ressources séparé 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
}
77
TWiStErRob

La vue Recycle prend en charge AutofitRecycleView.

Vous devez ajouter Android:numColumns="auto_fit" dans votre fichier XML.

Vous pouvez vous référer à ceci AutofitRecycleViewLink

7
kattashri

Un moyen plus robuste de déterminer le non. des colonnes serait de le calculer en fonction de la largeur de l'écran et au moment de 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 plus dynamique pour calculer avec précision le non. de colonnes. Cela sera plus adaptatif pour les utilisateurs de différentes tailles d'écran sans se limiter à deux valeurs possibles.

NB: Vous pouvez faire varier la valeur détenue par la variable scalingFactor. Plus c'est petit, plus non. des colonnes que vous pouvez afficher, et plus la valeur est grande moins il y a de des colonnes seront calculées. C'est le facteur d'échelle à adapter à vos besoins.

7
Rowland Mtetezi

Dans l'événement onCreate (), vous pouvez utiliser StaggeredGridLayoutManager.

mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);      

mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(
       1, //number of grid columns
       GridLayoutManager.VERTICAL);      

mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);

Puis, lorsque l'utilisateur fait pivoter l'écran, il capture l'événement et modifie automatiquement le nombre de colonnes.

@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);           
    }
}
2
Vladimir Salguero

J'ai fini par gérer cela 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.

1
user6731701

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 forme 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"/>

Définissez ensuite la variable sur la largeur de chaque élément dans la taille du fichier de valeurs values ​​/ dimens.xml

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

Cela peut être pour différentes résolutions d'écran-xxhdpi/dimens.xml

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

Dans votre activité dans l'événement onCreate, insérez le 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));
}
0
Vladimir Salguero