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