KDTabLayout
Introduction: 参考自 MagicIndicator 撸的自用版本,Kotlin 编写,适配 ViewPager2。
Tags:
一直感觉MagicIndicator这个库相当牛逼,在自己的工作过程中也帮我解决了很多问题,无奈作者志向高远,已经转行不写代码了,所以我参考了一下该库,自己撸了一个 TabLayout。
本 TabLayout 直接继承自 ViewGroup,默认实现了一些简单的效果,也留出了接口供用户自定义单个 Tab,Indicator,Badge 等控件,可以和 ViewPager2 和 ViewPager 搭配使用。
效果图:

将 JitPack 存储库添加到构建文件(项目根目录下 build.gradle 文件)
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
添加依赖项
// 版本号参看 Release
implementation 'com.github.XuQK:KDTabLayout:versionCode'
// 如果要使用 ViewPager2,请添加 ViewPager2 库
implementation 'androidx.viewpager2:viewpager2:versionCode'
使用说明
简单使用
将 KDTabLayout 添加到你的布局文件中
为 KDTabLayout 配置 Adapter
// KDTabLayout 本身主要有 tabMode 和 scrollBiasX 两个属性可设置,具体见类 field 注释,默认是 TAB_MODE_FLEXIBLE
tab2.tabMode = KDTabLayout.TAB_MODE_SCROLLABLE
tabLayout.contentAdapter = object : KDTabAdapter() {
override fun createTab(position: Int): KDTab? {
// 如果该方法返回 null,则 TabLayout 只会绘制 Indicator
// 这是一个 Tab 中文字颜色和大小会随滚动进度变化的 Tab
return KDColorMorphingTextTab(context, data[position]).apply {
horizontalPadding = 16f
selectedTextColor = Color.parseColor("#ff5722")
normalTextColor = Color.parseColor("#9e9e9e")
setOnClickListener {
viewPager2.currentItem = position
}
}
}
override fun createIndicator(): KDTabIndicator? {
// 如果该方法返回 null,则 TabLayout 不会绘制 Indicator
// 这是一个普通的矩形 Indicator
return KDRecIndicator(tab2).apply {
indicatorHeight = 6f
color = 0xffff5722.toInt()
cornerRadius = 3f
mode = KDRecIndicator.MODE_EXACT
indicatorWidth = 16f
startInterpolator = AccelerateInterpolator()
endInterpolator = DecelerateInterpolator(2f)
}
}
override fun getTabCount(): Int {
return ZH.size
}
}
// 与 ViewPager2 联动
tabLayout.setViewPager2(viewPager2)
// 与 ViewPager 联动
tabLayout.setViewPager(viewPager)
以上配置后,即可顺利使用。
自定义 Tab
只需继承KDTab,然后根据需要重写其中方法即可
class XTab(context: Context) : KDTab(context) {
/**
* @param selectedFraction 该 Tab 被选中的比例,即滚动完成度
* @param selectedInLeft 该 Tab 是否是从左边滚动到右边
*/
override fun onScrolling(selectedFraction: Float, selectedInLeft: Boolean) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
* 重置为初始状态
*/
override fun reset() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
* 设置为选中状态
*/
override fun selectTab() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
* 计算内容尺寸
*/
override fun computeContentBounds() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
自定义 Indicator
只需继承KDTabIndicator,根据需要重写其中方法即可
class XIndicator(tabLayout: KDTabLayout) : KDTabIndicator(tabLayout) {
/**
* 初始化方法,在 TabLayout 布局尺寸改变,或 adapter 重新设置后会调用
*/
override fun init() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
* 此方法参数都是以滚动方向为参照
*/
override fun onTabScrolled(startItem: Int, endItem: Int, scrolledFraction: Float) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun draw(canvas: Canvas) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
* 获取 Indicator 占用的宽度
* 此方法在且仅在 Indicator 单独使用时需要实现
*/
override fun getWidth(): Int {
return 0
}
/**
* 获取 Indicator 占用的高度
* 此方法在且仅在 Indicator 单独使用时需要实现
*/
override fun getHeight(): Int {
return 0
}
}
