0

Is it possible to use a specified width (100dp) to equally space out items in a Grid (as many as possible) for a RecyclerView rather than using an exact number of columns? int numberOfColumns = 3;, int numberOfColumns = 4;, etc. will not do the job as this will lead to plenty of empty space being present on larger screens.

portrait orientation

enter image description here

landscape orientation

enter image description here

RecyclerView-related code in Fragment

                static final String[] frenchVowels = new String[]{
                    "a", "e", "i", "o", "u", "y"
                };

                RecyclerViewAdapter rvAdapterGL;
                final RecyclerView rvGL = viewHolder.itemView.findViewById(R.id.rv);
                int numberOfColumns = 2;
                rvGL.setLayoutManager(new GridLayoutManager(getActivity(), numberOfColumns));
                rvAdapterGL = new RecyclerViewAdapter(getActivity(), frenchVowels);
                rvGL.setAdapter(rvAdapterGL);

RecyclerView adapter class

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private String[] mData;
    private LayoutInflater mInflater;

    // data is passed into the constructor
    public RecyclerViewAdapter(Context context, String[] data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // inflates the cell layout from xml when needed
    @Override
    @NonNull
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.gridview_item, parent, false);
        return new RecyclerViewAdapter.ViewHolder(view);
    }

    // binds the data to the TextView in each cell
    @Override
    public void onBindViewHolder(@NonNull RecyclerViewAdapter.ViewHolder holder, int position) {
        holder.myTextView.setText(mData[position]);
    }

    // total number of cells
    @Override
    public int getItemCount() {
        return mData.length;
    }


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.item_gridview);
        }
    }
}

XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:id="@+id/cv_gv"
    android:layout_marginBottom="20dp"
    >

    <LinearLayout
        android:id="@+id/cardview_gv_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp"
        android:animateLayoutChanges="true">

        <LinearLayout
            android:id="@+id/cardview_gv_titlerow"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="2dp"
            android:weightSum="100">

            <TextView
                android:id="@+id/tv_gv_A"
                android:layout_weight="90"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Medium" />

            <TextView
                android:id="@+id/tv_gv_expandcollapse"
                android:importantForAccessibility="no"
                android:clickable="true"
                android:focusable="true"
                android:layout_weight="10"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Large" />
        </LinearLayout>

        <RelativeLayout
            android:id="@+id/relativelayout_gv"
            android:animateLayoutChanges="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <GridView
                android:id="@+id/gv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:columnWidth="100dp"
                android:numColumns="auto_fit"
                android:layout_marginBottom="20dp"
                android:stretchMode="columnWidth" />
        </RelativeLayout>

    </LinearLayout>
</android.support.v7.widget.CardView>
wbk727
  • 8,017
  • 12
  • 61
  • 125

3 Answers3

1

If you use GridView layout, this question is answered here.

Or, if you want to use GridLayoutManager, do it like this

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
}
else{
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
}
Adnan Ismajli
  • 121
  • 1
  • 7
0

There are a few different ways to handle this. One thing you could do is get the screen width and divide it by your desired cell width to get the number of columns.

You could also use the Resources framework to set different column counts for different screen sizes. For example, you could have a res/values/integers.xml that sets the column count to 3, and also a res/values-sw400dp/integers.xml that sets the column count to 5, and so on.

res/values/integers.xml

<resources>
    <integer name=“column_count”>3</integer>
</resources>

res/values-sw400dp/integers.xml

<resources>
    <integer name=“column_count”>5</integer>
</resources>

Now you can replace

int numberOfColumns = 2;

with

int numberOfColumns = getResources().getInteger(R.integer.column_count);

And you can use any number of values-swXXXdp/integers.xml files with lots of different values for XXX to have lots of different column counts for lots of different screen sizes.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • How would your first suggestion work (this sounds more efficient)? (screen width / desired cell width (100dp)) – wbk727 Sep 16 '18 at 23:12
  • If anything it would be less efficient, since it would require actual computations as opposed to loading a resource (which the framework has optimized like crazy). I’ll try to update with more info later tonight, though. – Ben P. Sep 17 '18 at 02:05
  • Okay cool. What about just simply using a GridView? I've added my XML layout file. – wbk727 Sep 17 '18 at 10:04
  • https://stackoverflow.com/a/1016941/8298909 has info on getting screen width in pixels. You can then multiply your desired width (in dp) by the screen density `getResources().getDisplayMetrics().density` to get your column width in pixels. Then divide the one by the other to get your desired column count. Still, though, personally I'd go with the `` resource strategy (well, really I'd go with using a RecyclerView + FlexboxLayoutManager but you said you didn't want any other libraries). – Ben P. Sep 18 '18 at 17:31
0

You should use flexbox-layout library. It's open source library design by Google, Which will auto set column count based on the Row Width, You don't need to specify the column count.

And Its usage is also simple:

RecyclerView recyclerView = (RecyclerView) context.findViewById(R.id.recyclerview);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);

Gradle:

dependencies {
    implementation 'com.google.android:flexbox:1.0.0'
}
Dhaval Patel
  • 10,119
  • 5
  • 43
  • 46
  • Trying to avoid external libraries as they become bulky to the app. What about using a GridView? I've added my XML layout file. – wbk727 Sep 17 '18 at 10:04