如何自定义适配ViewPager的Tablayout indicator样式
自定义TabLayout搭配ViewPager实现自定义样式方案
前置准备
确保项目引入官方Material组件库,添加依赖到模块级build.gradle:
implementation 'com.google.android.material:material:1.9.0'
实现步骤
方式1:自定义Tab布局(推荐,兼容性强,可实现任意样式)
- 编写自定义Tab项布局
tab_item_layout.xml,可根据需要加入标题、自定义指示器、图标等元素:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/tv_tab_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:textColor="@color/tab_text_selector"/> <!-- 自定义指示器,替换默认indicator --> <View android:id="@+id/v_indicator" android:layout_width="20dp" android:layout_height="2dp" android:layout_marginTop="4dp" android:background="@color/colorPrimary" android:visibility="gone"/> </LinearLayout>
- 关联ViewPager后给每个Tab设置自定义布局
// 初始化ViewPager适配器 val titles = listOf("标签1", "标签2", "标签3") viewPager.adapter = object : FragmentStatePagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getCount() = titles.size override fun getItem(position: Int) = MyFragment(position) override fun getPageTitle(position: Int) = titles[position] } // TabLayout绑定ViewPager tabLayout.setupWithViewPager(viewPager) // 遍历替换Tab自定义布局 for (i in 0 until tabLayout.tabCount) { tabLayout.getTabAt(i)?.customView = getCustomTabView(i) }
- 监听Tab选中状态,更新自定义布局样式
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { viewPager.currentItem = tab.position updateTabState(tab, true) } override fun onTabUnselected(tab: TabLayout.Tab) { updateTabState(tab, false) } override fun onTabReselected(tab: TabLayout.Tab) {} }) private fun getCustomTabView(position: Int): View { val view = LayoutInflater.from(this).inflate(R.layout.tab_item_layout, null) view.findViewById<TextView>(R.id.tv_tab_title).text = titles[position] updateTabState(tabLayout.getTabAt(position)!!, tabLayout.selectedTabPosition == position) return view } private fun updateTabState(tab: TabLayout.Tab, isSelected: Boolean) { val customView = tab.customView ?: return customView.findViewById<TextView>(R.id.tv_tab_title).isSelected = isSelected customView.findViewById<View>(R.id.v_indicator).visibility = if (isSelected) View.VISIBLE else View.GONE }
方式2:仅修改默认指示器样式(适用于只需要调整默认indicator的场景)
如果不需要自定义复杂布局,仅需要调整指示器长度、颜色等,可直接在布局中添加属性:
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="48dp" app:tabIndicatorColor="@color/colorPrimary" app:tabIndicatorHeight="2dp" app:tabIndicatorFullWidth="false" <!-- 设为false后指示器和文字宽度一致 --> app:tabSelectedTextColor="@color/colorPrimary" app:tabTextColor="@color/gray"/>
设置完成后直接调用tabLayout.setupWithViewPager(viewPager)即可生效。
注意事项
- 必须在
setupWithViewPager调用完成后再设置自定义Tab布局,否则自定义布局会被默认Tab覆盖 - 自定义布局中的尺寸统一使用dp单位,文字大小使用sp单位,适配不同分辨率设备
- Tab之间的间距可通过
app:tabPaddingStart、app:tabPaddingEnd属性调整
内容的提问来源于stack exchange,提问作者Thành Tâm Cao
相关产品推荐
相关产品推荐

