Changing number of columns with GridLayoutManager and RecyclerView

64,654

Solution 1

Try handling this inside your onCreateView method instead since it will be called each time there's an orientation change:

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

Solution 2

If you have more than one condition or use the value in multiple places this can go out of hand pretty fast. I suggest to create the following structure:

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

with res/values/dimens.xml being:

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

and res/values-land/dimens.xml being:

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

And the code then becomes (and forever stays) like this:

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

You can easily see how easy it is to add new ways of determining the column count, for example using -w500dp/-w600dp/-w700dp resource folders instead of -land.

It's also quite easy to group these folders into separate resource folder in case you don't want to clutter your other (more relevant) resources:

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

Solution 3

The Recycle View supports AutofitRecycleView.

You need to add android:numColumns="auto_fit" in your xml file.

You can refer to this AutofitRecycleViewLink

Solution 4

In addition to the answers. It can be also done using XML attributes only. Below is the code.

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/pax_seat_map_rv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:spanCount="3"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" />

Solution 5

A more robust way to determine the no. of columns would be to calculate it based on the screen width and at runtime. I normally use the following function for that.

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
}

It is a more dynamic method to accurately calculate the no. of columns. This will be more adaptive for users of varying screen sizes without being resticted to only two possible values.

NB: 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.

Share:
64,654
fapps
Author by

fapps

Updated on July 05, 2022

Comments

  • fapps
    fapps almost 2 years

    Inside my fragment I'm setting my GridLayout in the following way: mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));

    So, I just want to change that 2 for a 4 when the user rotates the phone/tablet. I've read about onConfigurationChanged and I tried to make it work for my case, but it isn't going in the right way. When I rotate my phone, the app crashes...

    Could you tell me how to solve this issue?

    Here is my approach to find the solution, which is not working correctly:

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

    Thanks in advance!

  • fapps
    fapps about 9 years
    I'll try it out and tell you about. Thanks!
  • ciccioska
    ciccioska almost 9 years
    Is this the correct behaviour to do this task? Thanks
  • TWiStErRob
    TWiStErRob over 8 years
    @ciccioska I think resource folders are a better practice than doing conditions on getConfiguration() or onConfigurationChanged. Also see my answer on this question.
  • Vladimir Salguero
    Vladimir Salguero almost 8 years
    Excellent implementation! rotate the screen to change the number of columns dynamically and maintains the position of scroll
  • Stoycho Andreev
    Stoycho Andreev over 6 years
    This is probably the most perfect solution, but not if your designer decide something different. Sometimes the design just make us to the implementation by the hard way