Android 入门到实战(三):ViewPager及ViewPager2多页面布局

一. 引言

在 Android 应用开发中,实现多页面的左右滑动切换,是非常常见且实用的交互方式。ViewPager 组件正是为此而生,帮助我们轻松管理和切换多个页面内容。

不过,随着 Android Jetpack 的发展,Google 推出了 ViewPager 的升级版本 ------ ViewPager2,它在功能和性能上都有显著提升,成为了新的官方推荐组件。

本篇文章将带你快速了解旧版 ViewPager 的基本情况及它的两种常用适配器(FragmentPagerAdapter 和 FragmentStatePagerAdapter)之间的区别,随后重点介绍 ViewPager2 的使用方法,并演示如何配合 TabLayout 实现漂亮的滑动标签页效果。通过一个简单的 Activity + 3 个 Fragment 示例,帮助你快速掌握多页面滑动切换的核心技巧。

无论你是刚接触 ViewPager 相关组件,还是想了解 ViewPager2 的实战用法,这篇内容都会为你提供清晰且实用的指导。

二. 旧版 ViewPager 简介及适配器区别

2.1 什么是 ViewPager?

ViewPager 是 Android Support Library(现为 AndroidX)中提供的一个经典组件,用于在多个页面之间实现左右滑动切换。它内部管理多个页面视图,支持手势滑动、页面切换动画以及预加载等功能,使得多页面导航体验更加流畅自然。

2.2 FragmentPagerAdapter 和 FragmentStatePagerAdapter 的区别

在使用 ViewPager 管理 Fragment 页面时,通常会用到两种适配器:

FragmentPagerAdapter

  • 适用于页面数量较少且固定的情况。
  • 它会保留所有 Fragment 的实例,页面切换时仅隐藏或显示。
  • 因为会一直持有所有 Fragment,占用更多内存,适合 Tab 页数较少的场景。

FragmentStatePagerAdapter

  • 适用于页面较多或者动态变化的情况。
  • 它会在 Fragment 不可见时销毁其视图和状态,仅保存必要的状态信息。
  • 能有效节省内存,适合需要管理大量页面的情况。

2.3 代码示例(简要)

Kotlin 复制代码
class MyPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
    override fun getCount() = 3
    override fun getItem(position: Int): Fragment {
        return when(position) {
            0 -> FragmentA()
            1 -> FragmentB()
            else -> FragmentC()
        }
    }
}

如果用 FragmentStatePagerAdapter,写法类似,只是继承不同。

2.4 为什么推荐使用 ViewPager2?

尽管旧版 ViewPager 仍在一些项目中使用,但它存在一些设计和性能上的限制,比如:

  • 只能水平方向滑动(ViewPager2 支持垂直滑动)
  • 不支持 RecyclerView 的所有优势(ViewPager2 基于 RecyclerView 实现)
  • 适配现代架构组件支持较弱

因此,Google 推荐在新项目中使用功能更强、灵活性更高的 ViewPager2。

三. ViewPager2 介绍

3.1 ViewPager2 是什么?

ViewPager2 是 Google 推出的 ViewPager 升级版,基于 RecyclerView 实现,拥有更强的功能和更好的性能,同时完美支持 AndroidX 和 Jetpack 架构组件。它的 API 设计更灵活,兼容性更好,是当前新项目的首选。

3.2 相比旧版的主要改进

特性 ViewPager ViewPager2
滑动方向 仅支持水平方向 支持水平 & 垂直
底层实现 自定义 Layout 基于 RecyclerView
数据更新 需调用 notifyDataSetChanged(),机制复杂 直接使用 RecyclerView Adapter 更新机制
生命周期 与 Fragment 生命周期适配不够好 完全兼容 Fragment Lifecycle & LiveData
反向布局 不支持 支持(RTL,倒序显示等)

3.3 基本使用方式

ViewPager2 继承自 ViewGroup,与 RecyclerView 的 Adapter 配合使用,官方推荐配合 FragmentStateAdapter 来管理 Fragment 页面。它的使用步骤通常为:

  1. 在布局文件中添加 ViewPager2
  2. 创建一个继承自 FragmentStateAdapter 的适配器
  3. 在 Activity/Fragment 中将适配器绑定到 ViewPager2
  4. (可选)与 TabLayout 结合,使用 TabLayoutMediator 进行绑定

四. ViewPager2 + TabLayout 实现滑动 Tab 布局

下面我们用一个简单的 Activity + 3 个 Fragment,演示如何用 ViewPager2 配合 TabLayout 实现滑动标签页效果。

4.1 activity布局文件

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/main">

    <!-- TabLayout -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@android:color/holo_blue_dark"
        app:tabSelectedTextColor="@android:color/holo_blue_dark"
        app:tabTextColor="@android:color/darker_gray" />

    <!-- ViewPager2 -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

4.2 Fragment 布局

以fragment_home.xml为例:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:gravity="center"
    tools:context=".page.MineFragment">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="首页"
        android:layout_gravity="center"
        android:textSize="24sp" />

</FrameLayout>

4.3 Fragment 类

事实上这都是工具为我们自动创建的以HomeFragment.kt为例:

Kotlin 复制代码
class HomeFragment : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment HomeFragment.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            HomeFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }
}

4.4 适配器

MainPagerAdapter.kt

Kotlin 复制代码
package com.example.viewpagerexample.main

import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.viewpagerexample.page.DiscoverFragment
import com.example.viewpagerexample.page.HomeFragment
import com.example.viewpagerexample.page.MineFragment

class MainPagerAdapter(activity: FragmentActivity): FragmentStateAdapter(activity) {
    private val fragments = listOf(
        HomeFragment(),
        DiscoverFragment(),
        MineFragment()
    )

    override fun getItemCount() = fragments.size
    override fun createFragment(position: Int) = fragments[position]
}

4.5 Activity 绑定逻辑

MainActivity.kt

Kotlin 复制代码
    /// 配置tab
    private fun setupTabLayout() {
        val viewPager = findViewById<androidx.viewpager2.widget.ViewPager2>(R.id.viewPager2)
        val tabLayout = findViewById<com.google.android.material.tabs.TabLayout>(R.id.tabLayout)

        // 设置ViewPager2的适配器
        viewPager.adapter = MainPagerAdapter(this)

        // 使用 TabLayoutMediator 来绑定
        val titles = listOf("首页", "发现", "我的")
        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = titles[position]
        }.attach()

    }

效果如下:

五. 结语

在 Android 界面开发中,ViewPager2 搭配 TabLayout 是一种高效、直观的多页面切换方案。通过 FragmentStateAdapter,我们可以方便地将多个 Fragment 绑定到滑动视图中,而 TabLayoutMediator 则免去了手动同步标签与页面状态的繁琐逻辑,让交互更加顺畅自然。

相比旧版 ViewPager,ViewPager2 在性能、可扩展性、布局灵活性等方面都有显著提升,支持垂直滑动、RTL 布局、RecyclerView 优化等特性。对于新项目而言,已经没有理由再去使用旧的 ViewPager 与 FragmentPagerAdapter。

至此,我们通过一个 单 Activity + 多 Fragment + TabLayout + ViewPager2 的实战案例,完成了从基本使用到交互优化的全过程。掌握了这一套模式,你就可以轻松实现首页导航、功能分类、内容切换等多种常见 UI 场景,为应用提供更优的用户体验。

相关推荐
zzywxc7871 小时前
AI 行业应用:金融、医疗、教育、制造业领域的落地案例与技术实现
android·前端·人工智能·chrome·金融·rxjava
sTone873751 小时前
android studio之外使用NDK编译生成android指定架构的动态库
android·c++
风往哪边走4 小时前
Media3在线本地视频播放器
android
激昂网络4 小时前
android kernel代码 common-android13-5.15 下载 编译
android·大数据·elasticsearch
Monkey-旭4 小时前
Android 人脸识别技术全解析
android·android 人脸识别·ml kit 实战·活体检测技术·人脸识别性能优化·人脸考勤系统·移动端人脸特征提取
vivo互联网技术5 小时前
桌面挂件不能承受之重——GIF
android·gif加载·桌面挂件
JulyYu6 小时前
Android系统保存重名文件后引发的异常解决
android·操作系统·源码
叽哥6 小时前
Kotlin学习第 2 课:Kotlin 基础语法:掌握变量、数据类型与运算符
android·kotlin·app