21

I'm trying to center all my items horizontally for each row in RecyclerView

I tried many things: RelativeLayout as a parent, then use layout_centerInParent, use the basic android:layout_gravity="center", try to add some space element,using weights and .... in item_row.xml
but I didn't succeed :(

What i have

a busy cat

What i want

a busy cat

In activity

recyclerView.setLayoutManager(new GridLayoutManager(this, 3));

item_row.xml

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true">

<!--   Recycler View Item Row   -->
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">


    <ImageView
        android:id="@+id/imgThumbnail"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:background="@android:color/black" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">


        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="item name"
            android:id="@+id/txtName"
            android:layout_margin="5dp"
            android:singleLine="false"
            android:lines="2"
            android:gravity="center" />

        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:id="@+id/txtCategory"
                android:textStyle="italic"
                android:textColor="#496fa9"
                android:text="subtitle"
                android:layout_weight="1"
                android:gravity="center_vertical"
                android:paddingLeft="10dp"
                android:layout_gravity="center" />

            <ImageButton
                android:id="@+id/imageButton"
                android:layout_width="48dp"
                android:layout_height="wrap_content"
                android:background="@android:color/black"
                android:adjustViewBounds="true"
                android:scaleType="fitCenter"
                android:padding="8dp"/>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

</android.support.v7.widget.CardView>

i googled a lot and found this answer but actually i don't know how to create a LinearLayout for each row of items!

  • is that the best solution?

  • any other idea?

Community
  • 1
  • 1
Ali Sherafat
  • 3,506
  • 2
  • 38
  • 51

4 Answers4

4

you can use a SpanSizeLookup to make views/items with different widths for your grid view. So with that you can do some cleverness with empty views to adjust accordingly. Might be more complicate or simpler depending on how variable your layout actually is.

reference: https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.SpanSizeLookup.html

for this specific case you show on your drawing you would do something like:

GridLayoutManager lm = new GridLayoutManager(context, 6);
lm.setSpanSizeLookup(new MySizeLookup());

public static class MySizeLookup extends SpanSizeLookup {

   public int getSpanSize(int position) {
      if(position >= 0 && position <= 2) {
          return 2;
      } else if (position == 3 || position == 6) {
          return 1;
      } else {
          return 2;
      }
   }
}

and with that you'll have to make on your adapter, the position 3 and 6 to be an empty/invisible element. Something like new View(context); just to occupy that extra space

Budius
  • 39,391
  • 16
  • 102
  • 144
  • 1
    i did a lot of tests and tried your code but didn't succeed and i think i should check the rows that have less than 3 item and put the item of that row in a `LinearLayout` with `android:layout_gravity="center"` attribute **BUT** i don't know how to do that – Ali Sherafat May 29 '16 at 09:59
  • @RahulKhurana answer works for 3 rows, this one does not. – lostintranslation Sep 01 '17 at 13:48
  • 1
    i have same issue,i can't set row in center With grid layout manager,i have tried this but not working with 4 or 5 items for each row.can any one have idea? – civani mahida Oct 17 '19 at 09:02
  • 1
    @civanimahida have you find any solution to center row for 5 items – Fazal Hussain May 16 '20 at 10:10
3

Use the gridLayoutManager = new GridLayoutManager(context,6) and override setSpanSizeLookup.

Example:

int totalSize=list.size();
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        int span;
                        span = totalSize % 3;
                        if (totalSize < 3) {
                            return 6;
                        } else if (span == 0 || (position <= ((totalSize - 1) - span))) {
                            return 2;
                        } else if (span == 1) {
                            return 6;
                        } else {
                            return 3;
                        }
                    }
                });

This will work if you want to display 3 items in a row and remaining in the center of the grid.

Change the grid layout manager span counts accordingly your requirement.

Rahul Devanavar
  • 3,917
  • 4
  • 32
  • 61
0
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 6);
final int totalSize = customList.size();

layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        int extra;
        extra = totalSize % 3;

        if(extra == 0)
            return 2;

        if (totalSize - (position + 1) < extra) {
            return (int) 6 / extra;
        }

        return 2;
    }
});

recycler.setLayoutManager(layoutManager);
  • Code only answers are discouraged. Please add some explanation as to how this solves the problem, or how this differs from the existing answers. [From Review](https://stackoverflow.com/review/late-answers/25188517) – Nick Jan 26 '20 at 05:06
  • I can explain this since I came up with a similar solution, you have to be familiar with span size first, then, notice the number 6, this is, for 3 columns we are going to use 6 span areas, in this example, 3 items (3 columns) each column will occupy a 2-span area by default. Variable extra is the remainder items, the 2 at the bottom, the 2 last ones, the one's to be aligned, this is why {if extra==0, return 2} The middle IF states: Is the current position one of the last-to-be-centered items? then assign the total area (6) between remainder items {return (int) 6 / extra} Saludos – einschneidend Jul 17 '20 at 15:59
0
    GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 6);
    final int totalSize = customList.size();

    layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            int rows = Math.round((totalSize / 3f) + 0.4f);
            int itemInRow = Math.round(((position + 1) / 3f) + 0.4f);
            if (rows == 1 || rows == itemInRow) {
                int span = totalSize % 3;
                if (span == 0) {
                    return 2;
                }
                return 6 / span;
            }
            return 2;
        }
    });