8、横向滚动列表:设置 LinearLayoutManager 为 HORIZONTAL
说实话,很多新手做列表时,脑子里默认就是上下滑。但实际项目中,横向滚动的需求太常见了——图片轮播、标签选择、商品推荐卡片……你想想看,几乎每个App里都有那么一两个横向滑动的区域。
这一章我们就专门聊聊,怎么把 RecyclerView 从「竖着滑」变成「横着滑」。其实改动非常小,但背后有些细节值得注意。
核心改动:一行代码的事
要让 RecyclerView 横向滚动,关键就在 LinearLayoutManager 的构造参数上。默认情况下,我们用的是:
val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
这样得到的是垂直滚动。改成横向只需要加一个参数:
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recyclerView.layoutManager = layoutManager
第二个参数传 HORIZONTAL,第三个参数是 reverseLayout,一般传 false 表示从左到右排列。如果你传 true,那就会从右向左滚动——嗯,某些阿拉伯语系的App可能会用到。
关键点:LinearLayoutManager 的构造方法有三个参数:
- context:上下文
- orientation:方向,VERTICAL 或 HORIZONTAL
- reverseLayout:是否反向布局
布局上的调整
方向变了,item 的布局也得跟着调整。我个人习惯把 item 的宽度设为 wrap_content 或者一个固定值,高度设为 match_parent。为什么呢?因为横向滚动时,每个 item 的高度通常由 RecyclerView 的高度决定,而宽度则需要我们显式控制。
举个例子,一个横向的图片列表:
<!-- item_image.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="4dp">
<ImageView
android:id="@+id/iv_thumb"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="12sp" />
</LinearLayout>
这里宽度设了 120dp,高度撑满父布局。如果你设成 match_parent,那每个 item 就会占满整个屏幕宽度——横向滚动就变成了一屏一屏翻页的效果,这可能是你想要的,也可能不是。
小技巧:如果你希望 item 宽度自适应内容,可以用 wrap_content。但要注意,RecyclerView 的父布局宽度要设成 match_parent,否则可能撑不开。
我在项目中踩过的坑
我曾经在一个电商项目里做横向推荐列表,遇到一个奇怪的问题:列表滑到最右边时,最后一个 item 只显示了一半。排查了半天,发现是 RecyclerView 的父布局用了 wrap_content,导致 RecyclerView 自身宽度不够。
解决方案很简单:把 RecyclerView 的宽度设为 match_parent,或者给父布局一个固定宽度。另外,如果你用 ConstraintLayout,记得给 RecyclerView 加上左右约束。
避坑指南:横向 RecyclerView 嵌套在 ScrollView 或 NestedScrollView 里时,会出现滑动冲突。我曾经被这个问题折磨了一下午——横向滑动总是被父布局拦截。解决方案是给 RecyclerView 重写 onInterceptTouchEvent,或者用 NestedScrollView 配合 setNestedScrollingEnabled(false)。
完整示例代码
下面是一个完整的横向列表实现,包含 Adapter 和 Activity 的代码:
// HorizontalAdapter.kt
class HorizontalAdapter(private val items: List<String>) :
RecyclerView.Adapter<HorizontalAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_horizontal, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount() = items.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val tvLabel: TextView = itemView.findViewById(R.id.tv_label)
fun bind(text: String) {
tvLabel.text = text
}
}
}
// MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recyclerView.layoutManager = layoutManager
val data = listOf("推荐1", "推荐2", "推荐3", "推荐4", "推荐5")
val adapter = HorizontalAdapter(data)
recyclerView.adapter = adapter
}
}
横向列表的常见应用场景
| 场景 | 说明 | Item 宽度建议 |
|---|---|---|
| 图片轮播 | 全屏宽度,左右滑动切换 | match_parent |
| 标签选择 | 横向排列的标签,可多选 | wrap_content |
| 商品推荐 | 一行显示多个商品卡片 | 固定值(如 150dp) |
| 分类导航 | 类似 Tab 的横向导航 | wrap_content 或固定值 |
SVG 结构图:横向列表的核心逻辑
总结
横向滚动列表,说白了就是改一个参数的事。但真正用好它,你需要关注三点:
- 方向参数:
LinearLayoutManager.HORIZONTAL - Item 宽度:根据场景选择固定值或
wrap_content - 父布局宽度:确保 RecyclerView 有足够的空间
嗯,这一章的内容其实不多,但横向列表在实际项目中出现的频率非常高。下一章我们会聊聊更进阶的话题——如何给列表添加分割线,让 UI 更精致。