以下是关于 ​ViewPager2​ 的详细使用指南,包含核心功能、代码示例及最佳实践:


一、ViewPager2 基础用法

1. 添加依赖

build.gradle中添加:

dependencies {
    implementation 'androidx.viewpager2:viewpager2:1.1.0'
}
2. 布局文件中添加 ViewPager2
<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

二、创建适配器

​(1) 继承 FragmentStateAdapter(推荐用于 Fragment)​
class MyPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
    private val items = listOf("Page 1", "Page 2", "Page 3")

    override fun getItemCount(): Int = items.size

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> PageFragment.newInstance(items[0])
            1 -> PageFragment.newInstance(items[1])
            else -> PageFragment.newInstance(items[2])
        }
    }
}
​(2) 继承 RecyclerView.Adapter(自定义 View)​
class MyViewPagerAdapter(private val items: List<String>) : RecyclerView.Adapter<MyViewPagerAdapter.ViewHolder>() {
    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val textView: TextView = itemView.findViewById(R.id.item_text)
        fun bind(item: String) {
            textView.text = item
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(items[position])
    }

    override fun getItemCount(): Int = items.size
}

三、绑定适配器与设置监听

在 Activity/Fragment 中
class MainActivity : AppCompatActivity() {
    private lateinit var viewPager: ViewPager2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewPager = findViewById(R.id.viewPager)
        
        // 使用 Fragment 适配器
        val adapter = MyPagerAdapter(this)
        viewPager.adapter = adapter

        // 或使用自定义 View 适配器
        // val adapter = MyViewPagerAdapter(listOf("A", "B", "C"))
        // viewPager.adapter = adapter

        // 监听页面切换
        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                Toast.makeText(this@MainActivity, "当前页:$position", Toast.LENGTH_SHORT).show()
            }
        })
    }
}

四、高级功能

1. 设置页面间距
// 在 Activity/Fragment 中
val pageMarginPx = resources.getDimensionPixelOffset(R.dimen.page_margin)
val offsetPx = resources.getDimensionPixelOffset(R.dimen.page_offset)
viewPager.setPageTransformer { page, position ->
    val offset = position * -(2 * offsetPx + pageMarginPx)
    page.translationX = offset.toFloat()
}
2. 与 TabLayout 结合
// 在 Activity/Fragment 中
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
    tab.text = "Tab ${position + 1}"
}.attach()
3. 动态添加/删除页面
// 更新数据源
adapter.items.add("New Page")
adapter.notifyDataSetChanged()

// 删除页面
adapter.items.removeAt(0)
adapter.notifyItemRemoved(0)

五、常见问题解决

1. 页面闪烁或复用问题
  • 原因​:默认启用视图复用,可能导致动画异常。

  • 解决​:关闭视图复用:

    viewPager.offscreenPageLimit = items.size // 保留所有页面
2. Fragment 状态丢失
  • 原因​:配置变更(如屏幕旋转)导致 Fragment 重建。

  • 解决​:在 Fragment 中使用 setRetainInstance(true)或通过 ViewModel 保存状态。

3. 与 RecyclerView 冲突
  • 原因​:同时使用 ViewPager2 和 RecyclerView 时滚动冲突。

  • 解决​:为 RecyclerView 添加嵌套滚动监听:

    recyclerView.isNestedScrollingEnabled = false

六、完整示例代码

Activity
class ViewPager2DemoActivity : AppCompatActivity() {
    private lateinit var viewPager: ViewPager2
    private lateinit var adapter: MyPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view_pager2_demo)

        viewPager = findViewById(R.id.viewPager)
        adapter = MyPagerAdapter(this)
        viewPager.adapter = adapter

        // 设置页面间距
        val pageMargin = resources.getDimensionPixelSize(R.dimen.page_margin)
        val offset = resources.getDimensionPixelSize(R.dimen.page_offset)
        viewPager.setPageTransformer { page, position ->
            val offsetPx = position * -(2 * offset + pageMargin)
            page.translationX = offsetPx.toFloat()
        }

        // 绑定 TabLayout
        val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = "Section $position"
        }.attach()
    }
}
适配器
class MyPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return ContentFragment.newInstance(position + 1)
    }
}
Fragment
class ContentFragment : Fragment() {
    companion object {
        private const val ARG_PAGE = "ARG_PAGE"

        fun newInstance(page: Int): ContentFragment {
            return ContentFragment().apply {
                arguments = Bundle().apply { putInt(ARG_PAGE, page) }
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = FragmentContentBinding.inflate(inflater, container, false)
        val page = arguments?.getInt(ARG_PAGE) ?: 1
        binding.textView.text = "Page $page"
        return binding.root
    }
}

七、总结

ViewPager2 的核心优势:

  1. 兼容性​:基于 RecyclerView 实现,支持横向滑动和垂直滑动。

  2. 生命周期管理​:自动处理 Fragment 的创建与销毁。

  3. 灵活性​:支持自定义页面间距、动画和与 TabLayout 的无缝集成。

通过合理使用适配器和页面变换,可以轻松实现复杂的滑动交互场景(如引导页、轮播图、多屏切换)。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐