83

I need to center elements in each row so they will be like in this mockup. I've been searching if there is any layout that works that way without look. items are centered in their rows.

mockup

This is how it looks now in my code.enter image description here

Chris Gomez
  • 6,644
  • 4
  • 18
  • 39

11 Answers11

84

Make recyclerview width to wrap_content and its container's layout_gravity to center_horizontal

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

      <android.support.v7.widget.RecyclerView
           android:id="@+id/recycrer_view"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center_horizontal"
           android:paddingLeft="16dp"
           android:paddingRight="16dp" />
 </LinearLayout>
Johnny Five
  • 987
  • 1
  • 14
  • 29
Ravi Yadav
  • 2,296
  • 3
  • 25
  • 32
41

Take LinearLayout in your RecyclerView's item row layout then give android:layout_gravity="center" to LinearLayout.

For each row of images you have to take different LinearLayout.

Here is example code:

 <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:orientation="horizontal">

            <ImageView
                android:id="@+id/image1"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:layout_marginRight="10dp"
                android:layout_weight="1"
                android:src="@drawable/image1" />

            <ImageView
                android:id="@+id/image2"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_weight="1"
                android:src="@drawable/image2" />

           <ImageView
                android:id="@+id/image3"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_weight="1"
                android:src="@drawable/image3" />

  </LinearLayout>
Rajesh Jadav
  • 12,801
  • 5
  • 53
  • 78
  • 2
    I had to modify the RecyclerView layout_width="wrap_content" rather than match_parent as well – jernkuan Oct 26 '16 at 21:00
  • 1
    @jemkuan That will disable scrolling when the user swipes on the edge or outer region of the parent, as the width of the RecyclerView will be less than the width of the parent. – Elliott Beach Jun 01 '17 at 18:10
  • The problem with this approach is that the recycler view will register a click event when user will touch outside of the image views. – Izak Feb 17 '19 at 22:21
37

Achieved with:

recyclerView.adapter = MyAdapter()
val layoutManager = FlexboxLayoutManager(context).apply {
    justifyContent = JustifyContent.CENTER
    alignItems = AlignItems.CENTER
    flexDirection = FlexDirection.ROW 
    flexWrap = FlexWrap.WRAP
}
recyclerView.layoutManager = layoutManager

You need to add FlexboxLayout to your gradle:

implementation 'com.google.android.flexbox:flexbox:3.0.0'

enter image description here

Amir Hossein Ghasemi
  • 20,623
  • 10
  • 57
  • 53
AskQ
  • 4,215
  • 7
  • 34
  • 61
8

I am assuming that you are using a LinearLayoutManager with a RecyclerView for a ListView-style effect. In that case, use a horizontal LinearLayout for each row, with android:gravity="center" to center its contents.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
6

Use FlexboxLayout from com.google.android:flexbox library. Note the flexwrap and justifyContent property values. Then, set layout_wrapBefore = true on the view that you want to wrap the line of items before.

    <com.google.android.flexbox.FlexboxLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flexWrap="wrap"
        app:justifyContent="center">

        <View ... />

        <View app:layout_wrapBefore="true" ... />

        <View ... />

    </com.google.android.flexbox.FlexboxLayout>
ersin-ertan
  • 2,283
  • 2
  • 18
  • 27
  • 4
    I would like to add this is a very clean way to do this. Specially you can use the library as a `layoutManager` for `recyclerview`. All you have to do is set up the layout manager with direction and alignment requirements. No need to make a two dimensional recyclerview as mentioned by third top answer. – Juan Mendez Jun 07 '19 at 18:20
4

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.

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
Rahul Devanavar
  • 3,917
  • 4
  • 32
  • 61
4

you can use the new layoutManager from google FlexLayoutManager it will gives you a lot of control and flexibility over the recyclerView items

Omar Abdan
  • 1,901
  • 17
  • 29
3

you can add some layouts dynamically, for example:

  • adapter object can be a horizontal LinearLayout

1- create a LinearLayout in java code and customize it (gravity,...)

2- add some icons to linearLayout

3- add linearLayout to your adapter

4- repeat 1,2,3


    // : declare new horizontal linearLayout
    ImageView myIcons[nomOfIcons];
    // : add all icons to myIcons
    for(int i=1; i<=nomOfIcons; i++){
        linearLayout.addView(myIcons[i - 1]);
        if(i%numOfIconsInOneHorizontalLinearLayout==0) {
            results.add(linearLayout); // add linearLayout to adapter dataSet
            // : declare new horizontal linearLayout
        }
    }
    if(n%numOfIconsInOneHorizontalLinearLayout!=0) // add last linearLayout if not added in the loop
        results.add(linearLayout);
    mAdapter.notifyDataSetChanged(); // update adapter

Misagh
  • 3,403
  • 1
  • 20
  • 17
2

Trust me, this gonna work. In your main xml file where you've put the recycler view, copy my code.

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/_50sdp"
        android:gravity="center">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="wrap_content"
            android:layout_height="@dimen/_50sdp"/>

    </LinearLayout>
AI Shakil
  • 1,015
  • 10
  • 20
1

Currently, I think we need to write our own custom view for it because Android has not supported this feature as we expected yet.

It is the Sample I made in case someone needs it: https://github.com/mttdat/utils

(Try the CenterGridActivity.kt by adjusting Manifest file to start this activity as default)

Nguyen Tan Dat
  • 3,780
  • 1
  • 23
  • 24
0

In case you need the Java Version of AskQ's reply:

    // Set layout manager to position the items
    FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(this);
    layoutManager.setJustifyContent(JustifyContent.CENTER);
    layoutManager.setAlignItems(AlignItems.CENTER);
    layoutManager.setFlexDirection(FlexDirection.ROW);
    layoutManager.setFlexWrap(FlexWrap.WRAP);
    adapter.setLayoutManager(layoutManager);
Brett Ezra
  • 121
  • 1
  • 11