
ViewPager2 实现高效的顶部导航(通常结合
TabLayout)是一种常见的需求。以下是优化后的实现方案,确保代码高效、简洁且易于维护。FragmentStateAdapter 的特性,避免不必要的 Fragment 实例化。TabLayout 和 ViewPager2。确保在 build.gradle 中添加 ViewPager2 和 Material Design 依赖:
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'com.google.android.material:material:1.4.0'
}
使用 sealed class 或 data class 定义页面信息,包括标题、图标和对应的 Fragment。
// Page.kt
sealed class Page(val title: String, val icon: Int) {
object Home : Page("Home", R.drawable.ic_home)
object Dashboard : Page("Dashboard", R.drawable.ic_dashboard)
object Notifications : Page("Notifications", R.drawable.ic_notifications)
companion object {
val pages = listOf(Home, Dashboard, Notifications)
}
}
为每个页面创建对应的 Fragment。
// Fragment1.kt
class Fragment1 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
}
// Fragment2.kt
class Fragment2 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_2, container, false)
}
}
// Fragment3.kt
class Fragment3 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_3, container, false)
}
}
使用 FragmentStateAdapter 动态加载 Fragment。
class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int = Page.pages.size
override fun createFragment(position: Int): Fragment {
return when (Page.pages[position]) {
is Page.Home -> Fragment1()
is Page.Dashboard -> Fragment2()
is Page.Notifications -> Fragment3()
}
}
}
在 MainActivity 中设置 ViewPager2 和 TabLayout 的联动。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewPager = findViewById(R.id.viewPager)
val tabLayout = findViewById(R.id.tabLayout)
// 设置 ViewPager2 适配器
viewPager.adapter = ViewPagerAdapter(this)
// 将 TabLayout 与 ViewPager2 联动
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = Page.pages[position].title
tab.icon = ContextCompat.getDrawable(this, Page.pages[position].icon)
}.attach()
}
}
在 activity_main.xml 中定义布局,包含 TabLayout 和 ViewPager2。
如果需要频繁配置 TabLayout,可以将其封装为扩展函数。
// TabLayoutExtensions.kt
fun TabLayout.setupWithViewPager(viewPager: ViewPager2, pages: List) {
TabLayoutMediator(this, viewPager) { tab, position ->
tab.text = pages[position].title
tab.icon = ContextCompat.getDrawable(context, pages[position].icon)
}.attach()
}
在 MainActivity 中使用:
tabLayout.setupWithViewPager(viewPager, Page.pages)
FragmentStateAdapter 确保 Fragment 实例的高效管理。Page.pages 动态配置页面,避免硬编码。Page 中添加一个新对象,无需修改核心逻辑。如果需要添加一个新页面,只需在 Page 中添加一个新对象:
object Profile : Page("Profile", R.drawable.ic_profile)
然后在 ViewPagerAdapter 中处理新页面:
override fun createFragment(position: Int): Fragment {
return when (Page.pages[position]) {
is Page.Home -> Fragment1()
is Page.Dashboard -> Fragment2()
is Page.Notifications -> Fragment3()
is Page.Profile -> Fragment4() // 新增页面
}
}
其他代码无需修改,系统会自动同步 TabLayout。
通过以上优化,ViewPager2 实现顶部导航的代码变得更加高效、简洁和易于维护。sealed class
和扩展函数的使用使代码更具可读性和可扩展性,同时避免了硬编码和重复逻辑。运行优化后的代码,你将获得一个高效的顶部导航实现。
