# view_pager2_tabs **Repository Path**: singcl/view_pager2_tabs ## Basic Information - **Project Name**: view_pager2_tabs - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-26 - **Last Updated**: 2026-03-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ViewPager2Demo 一个基于 Android ViewPager2 实现的 Tab 分页导航示例应用,演示了如何使用 ViewPager2 与 TabLayout 联动创建可滑动的分页界面,支持自定义 Tab 样式、图标和多种页面切换动画效果。 ## 项目简介 本项目展示了 Android JetPack ViewPager2 组件的基本用法,通过 FragmentStateAdapter 实现多个页面的滑动切换,并使用 Material Design 的 TabLayout 提供可视化标签导航。 **主要特性:** - 自定义 Tab 图标和颜色 - Tab 选中/取消选中动画效果 - 多种页面切换动画(深度、缩放、旋转、立方体、翻页) - Material Design 风格 UI 设计 ## 技术栈 - **语言**: Kotlin - **最低 SDK**: API 24 (Android 7.0) - **目标 SDK**: API 36 (Android 15) - **编译 SDK**: API 36 ### 核心依赖 | 依赖库 | 版本 | |--------|------| | ViewPager2 | 1.1.0 | | Material Components | 1.12.0 | | Fragment KTX | 1.8.0 | | Jetpack Compose | Latest BOM | | Activity Compose | Latest | | Lifecycle Runtime KTX | Latest | ## 项目结构 ``` app/ ├── src/main/ │ ├── java/com/example/viewpager2demo/ │ │ ├── MainActivity.kt # 主 Activity,承载 Fragment 容器 │ │ ├── MainHostFragment.kt # 主 Fragment,包含 ViewPager2 和 TabLayout │ │ ├── EnhancedMainHostFragment.kt # 增强版 Fragment,支持多种动画切换 │ │ ├── MainViewPagerAdapter.kt # ViewPager2 适配器,管理页面数据 │ │ ├── PageFragment.kt # 单个页面 Fragment │ │ ├── transformers/ # 页面切换动画变换器 │ │ │ ├── DepthPageTransformer.kt # 深度透视效果 │ │ │ ├── ZoomOutPageTransformer.kt # 缩放退出效果 │ │ │ ├── RotateDownPageTransformer.kt # 旋转向下效果 │ │ │ ├── CubeInTransformer.kt # 立方体进入效果 │ │ │ └── FlipHorizontalTransformer.kt # 水平翻页效果 │ │ └── ui/theme/ # Jetpack Compose 主题相关 │ │ ├── Color.kt │ │ ├── Theme.kt │ │ └── Type.kt │ ├── res/ │ │ ├── layout/ │ │ │ ├── activity_main.xml # Activity 布局(Fragment 容器) │ │ │ ├── fragment_main_host.xml # Fragment 布局(ViewPager2 + TabLayout) │ │ │ └── custom_tab_item.xml # 自定义 Tab 项布局 │ │ ├── drawable/ # 图标资源 │ │ │ ├── ic_tools.xml │ │ │ ├── ic_settings.xml │ │ │ ├── ic_history.xml │ │ │ └── ic_profile.xml │ │ ├── anim/ # 动画资源 │ │ │ ├── tab_slide_in_left.xml │ │ │ ├── tab_slide_in_right.xml │ │ │ ├── tab_slide_out_left.xml │ │ │ ├── tab_slide_out_right.xml │ │ │ ├── tab_zoom_in.xml │ │ │ └── tab_zoom_out.xml │ │ └── values/ │ │ ├── colors.xml # 颜色定义(含自定义 Tab 颜色) │ │ ├── strings.xml │ │ ├── themes.xml │ │ └── styles.xml # 自定义 TabLayout 样式 │ └── AndroidManifest.xml └── build.gradle.kts ``` ## 功能特性 ### 页面结构 应用包含 4 个可滑动的页面: 1. **Tools** - 工具页(紫色图标) 2. **Settings** - 设置页(青色图标) 3. **History** - 历史页(橙色图标) 4. **Profile** - 个人页(绿色图标) ### 自定义 Tab 样式 #### Tab 颜色配置 在 `colors.xml` 中定义了自定义颜色: ```xml #FF6200EE #FF03DAC5 #FFFF5722 #FF4CAF50 #FF6200EE #FF9E9E9E #FF03DAC5 ``` #### Tab 样式定义 在 `styles.xml` 中定义了三种样式: - `CustomTabLayout` - 基础自定义样式 - `AnimatedTabLayout` - 带动画效果的样式 - `MaterialTabLayout` - Material Design 风格样式 ```xml ``` ### Tab 动画效果 #### 1. 选中/取消选中动画 ```kotlin private fun animateTabSelection(tab: TabLayout.Tab, isSelected: Boolean) { val tabPage = (binding.tabLayout.getChildAt(0) as? ViewGroup) ?.getChildAt(tab.position) tabPage?.let { view -> if (isSelected) { // 选中动画:放大 + 弹性效果 ObjectAnimator.ofFloat(view, View.SCALE_X, 0.8f, 1.15f, 1.0f) .apply { duration = 350; start() } ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.8f, 1.15f, 1.0f) .apply { duration = 350; start() } } else { // 取消选中动画:缩小 ObjectAnimator.ofFloat(view, View.SCALE_X, 1.0f, 0.9f) .apply { duration = 200; start() } ObjectAnimator.ofFloat(view, View.SCALE_Y, 1.0f, 0.9f) .apply { duration = 200; start() } } } } ``` #### 2. 重新选中动画 点击已选中的 Tab 时触发 360 度旋转动画。 #### 3. 图标颜色动态变化 每个 Tab 选中时显示对应的主题色,未选中时显示灰色。 ### 页面切换动画 项目提供了 5 种页面切换动画效果,通过 `transformers` 包中的变换器实现: | 变换器 | 效果描述 | |--------|----------| | `DepthPageTransformer` | 深度透视效果,页面滑动时有远近变化 | | `ZoomOutPageTransformer` | 缩放退出效果,页面向后滑动时缩小淡出 | | `RotateDownPageTransformer` | 旋转向下效果,页面向后滑动时向下旋转 | | `CubeInTransformer` | 立方体进入效果,页面像立方体一样翻转 | | `FlipHorizontalTransformer` | 水平翻页效果,页面像书本一样翻转 | #### 使用示例 ```kotlin // 设置深度动画效果 viewPager2.setPageTransformer(DepthPageTransformer()) // 或使用增强版 Fragment 切换动画 enhancedFragment.setPageTransformer("zoom") // 缩放效果 enhancedFragment.cycleToNextTransformer() // 切换到下一个动画 ``` ### 核心实现 #### 1. MainActivity ```kotlin class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_main) if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.fragmentContainer, MainHostFragment()) .commit() } } } ``` - 启用 Edge-to-Edge 全屏显示 - 使用 Fragment 容器加载主 Fragment #### 2. MainHostFragment ```kotlin class MainHostFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val adapter = MainViewPagerAdapter(this) binding.viewPager2.adapter = adapter // 绑定 TabLayout 和 ViewPager2 TabLayoutMediator(binding.tabLayout, binding.viewPager2) { tab, position -> tab.text = adapter.getPageTitle(position) }.attach() } } ``` - 使用 ViewBinding 简化视图操作 - 通过 `TabLayoutMediator` 实现 TabLayout 与 ViewPager2 的双向绑定 - 自动同步滑动状态和标签选中状态 #### 3. MainViewPagerAdapter ```kotlin class MainViewPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { private val pageTitles = listOf("Tools", "Settings", "History", "Profile") override fun getItemCount(): Int = pageTitles.size override fun createFragment(position: Int): Fragment { return PageFragment.newInstance(pageTitles[position], position) } fun getPageTitle(position: Int): String = pageTitles[position] } ``` - 继承 `FragmentStateAdapter` 管理 Fragment 生命周期 - 动态创建页面 Fragment 并传递参数 #### 4. PageFragment ```kotlin class PageFragment : Fragment() { companion object { fun newInstance(title: String, index: Int): PageFragment { return PageFragment().apply { arguments = Bundle().apply { putString(ARG_TITLE, title) putInt(ARG_INDEX, index) } } } } override fun onCreateView(...): View { return TextView(requireContext()).apply { gravity = Gravity.CENTER textSize = 24f text = "${arguments?.getString(ARG_TITLE)}\nPage ${arguments?.getInt(ARG_INDEX)?.plus(1)}" } } } ``` - 使用静态工厂方法创建实例 - 通过 Bundle 传递页面标题和索引 ## 布局说明 ### fragment_main_host.xml ```xml ``` - ViewPager2 占据主要空间(`layout_weight="1"`) - TabLayout 固定在底部,带有阴影效果(`elevation="8dp"`) - 禁用了过度滚动效果(`overScrollMode="never"`) ## 构建与运行 ### 环境要求 - Android Studio Hedgehog 或更高版本 - JDK 11+ - Android SDK API 36 ### 构建命令 ```bash # Debug 构建 ./gradlew assembleDebug # Release 构建 ./gradlew assembleRelease # 运行测试 ./gradlew test ./gradlew connectedAndroidTest ``` ### 安装 ```bash # 安装到连接的设备 adb install app/build/outputs/apk/debug/app-debug.apk ``` ## 关键知识点 ### 1. TabLayoutMediator `TabLayoutMediator` 是 ViewPager2 与 TabLayout 联动的核心类: ```kotlin TabLayoutMediator(tabLayout, viewPager2) { tab, position -> tab.text = titles[position] // 可设置图标:tab.setIcon(...) }.attach() ``` ### 2. FragmentStateAdapter 相比传统的 `FragmentPagerAdapter`,`FragmentStateAdapter` 优势: - 更好的内存管理 - 支持更多页面数量 - 与 ViewPager2 完美配合 ### 3. ViewBinding 项目启用了 ViewBinding: ```kotlin private var _binding: FragmentMainHostBinding? = null private val binding get() = _binding!! override fun onDestroyView() { super.onDestroyView() _binding = null // 防止内存泄漏 } ``` ### 4. Edge-to-Edge ```kotlin enableEdgeToEdge() ``` 启用边缘到边缘的全屏显示模式。 ## 扩展建议 可以在此基础上添加以下功能: - [x] 自定义 Tab 样式和动画效果(已完成) - [x] 添加页面切换动画(已完成) - [ ] 支持水平/垂直滑动切换 - [ ] 集成 ViewModel 管理页面状态 - [ ] 添加下拉刷新功能 - [ ] 实现深色模式支持 ## 截图 (此处可添加应用运行截图) ## 许可证 本项目仅供学习参考使用。 ## 更新日志 ### v1.1.0 - 自定义样式和动画更新 - 添加自定义 Tab 图标(Tools/Settings/History/Profile) - 添加 Tab 选中/取消选中动画效果 - 添加 5 种页面切换动画(深度/缩放/旋转/立方体/翻页) - 添加自定义颜色和样式资源 - 添加 EnhancedMainHostFragment 支持动画切换 - 添加自定义 Tab 项布局 ### v1.0.0 - 初始版本 - 基础 ViewPager2 + TabLayout 实现 - 4 个可滑动页面 ## 参考资料 - [ViewPager2 官方文档](https://developer.android.com/training/animation/screen-slide-fragment) - [Material Design TabLayout](https://material.io/components/tabs-android) - [FragmentStateAdapter](https://developer.android.com/reference/androidx/viewpager2/adapter/FragmentStateAdapter)