如何将RecyclerView中的项目居中显示?

84

我需要将每一行的元素居中,使其看起来像这个模型。 我一直在搜索是否有任何布局可以实现这种效果,而不会改变原有的外观。 元素在它们所在的行中居中。

模型

这是现在在我的代码中的样子。输入图像描述


这听起来与https://dev59.com/qFsX5IYBdhLWcg3wHsdv非常相似。 - Konstantin Loginov
这个问题已经解决了吗? - Hoa Le
你可能需要创建一个自定义的LayoutManager,因为GridLayoutManager无法解决这个问题。我已经发布了一个答案,但我不确定它是否完全符合你的要求。 - Mo1989
如何制作此布局? - Parth Anjaria
11个回答

86

将recyclerview的width设置为wrap_content,并将其容器的layout_gravity设置为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>

11
这将防止在RecyclerView两侧滚动。 - frankish

41

在您的RecyclerView项行布局中使用LinearLayout,然后将android:layout_gravity="center"指定给LinearLayout

对于每一行图像,您都需要采用不同的LinearLayout

以下是示例代码:

 <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>

2
我不得不修改RecyclerView的layout_width属性为"wrap_content"而不是"match_parent"。 - jernkuan
1
@jemkuan 这将禁用用户在父视图的边缘或外部区域滑动,因为RecyclerView的宽度将小于父视图的宽度。 - Elliott Beach
这种方法的问题在于,当用户触摸图像视图之外的区域时,回收视图将注册一个点击事件。 - Izak

37

使用的技术:

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

你需要将FlexboxLayout添加到你的gradle中:

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

enter image description here


8

假设你正在使用LinearLayoutManagerRecyclerView来实现ListView的效果。在这种情况下,为每一行使用一个horizontalLinearLayout,并将android:gravity="center"用于居中内容。


1
实际上我正在使用gridlayout,但让我试试这个。 - Chris Gomez
3
我认为可以通过 GridLayoutManager 或自定义的 RecyclerView.LayoutManager 实现,但是仅就我快速浏览来看,我不知道如何使用 GridLayoutManager 实现这一点。 - CommonsWare
你解决了这个问题吗? - Cristian Holdunu
对于我使用网格布局的 Recycler View 项目,使用重力属性使项目居中是有效的。 - MikeL
1
这并没有帮助到 :( - Quick learner

6

使用来自com.google.android:flexbox库的FlexboxLayout,注意flexwrapjustifyContent属性值。然后,在要在其前面换行的视图上设置layout_wrapBefore = true

    <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>

4
我想补充说明这是一种非常干净的方法来实现这个目标。特别是你可以将该库用作recyclerviewlayoutManager,只需设置方向和对齐要求即可。无需像第三个最佳答案所提到的那样创建一个二维recyclerview - Juan Mendez

4
你可以使用来自Google的新layoutManager FlexLayoutManager,它将使你对recyclerView中的项具有更多的控制和灵活性。

4

使用 gridLayoutManager = new GridLayoutManager(context,6) 并覆盖 setSpanSizeLookup

示例:

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

这将适用于在网格中显示3个项目并保持其余项目居中的情况。
根据您的需求更改网格布局管理器跨度计数。

3

您可以动态地添加一些布局,例如:

  • 适配器对象可以是一个水平的LinearLayout

1- 在Java代码中创建一个LinearLayout并自定义它(gravity,...)

2- 向LinearLayout添加一些图标

3- 将LinearLayout添加到您的适配器中

4- 重复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


2

相信我,这会起作用的。 在您放置了RecyclerView的主XML文件中,复制我的代码。

    <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>

1

目前,我认为我们需要为此编写自定义视图,因为Android尚未如我们所期望地支持此功能。

这是我制作的示例,以防有人需要: https://github.com/mttdat/utils

(通过调整清单文件以将此活动作为默认活动启动,尝试使用CenterGridActivity.kt)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接