需求
實現(xiàn)以下UI效果,指示符寬度為10dp,高度為4dp,圓角為2dp
效果圖.png
通常的做法如下:
-
定義指示符tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:width="10dp" android:height="4dp" android:gravity="center"> <shape> <corners android:radius="2dp" /> </shape> </item> </layer-list>
定義TabLayout,設(shè)置 app:tabIndicator="@drawable/tab_indicator"
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="center"
app:tabIndicator="@drawable/tab_indicator"
app:tabIndicatorColor="#3F51B5"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="4dp"
app:tabMode="scrollable"
app:tabRippleColor="@android:color/transparent"
app:tabSelectedTextColor="#333333"
app:tabTextColor="#999999" />
在Android 6.0及以上系統(tǒng)的展示效果如下:
Android 8.0效果圖.png
在Android 5.1的機器上展示效果如下:
Android 5.1效果圖.png
在Android 5.1的機器上指示符的寬度和文本的寬度一樣長,而不是我們想要的10dp
問題排查
檢查了一下代碼,發(fā)現(xiàn)xml文件中l(wèi)ayer-list節(jié)點下android:width/height屬性在Android 6.0以下系統(tǒng)無效,當(dāng)我們把光標放在tab_indicator.xml布局文件里會有這樣的提示: Attribute width is only used in API level 23 and higher (current min is 21)
image.png
解決方案
在代碼中動態(tài)設(shè)置指示符寬度,添加一個TabLayout的擴展方法,如下:
/**
* 設(shè)置指示符固定寬度
*/
fun TabLayout.setSelectedTabIndicatorFixWidth(width: Float) {
setSelectedTabIndicator(object : DrawableWrapper(tabSelectedIndicator) {
override fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
var realLeft = left
var realRight = right
if ((right - left).toFloat() != width) {
val center = left + (right - left).toFloat() / 2
realLeft = (center - width / 2).toInt()
realRight = (center + width / 2).toInt()
}
super.setBounds(realLeft, top, realRight, bottom)
}
})
}
使用
tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
</shape>
布局文件
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="center"
app:tabIndicator="@drawable/tab_indicator"
app:tabIndicatorColor="#3F51B5"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="4dp"
app:tabMode="scrollable"
app:tabRippleColor="@android:color/transparent"
app:tabSelectedTextColor="#333333"
app:tabTextColor="#999999" />
tabLayout.setSelectedTabIndicatorFixWidth(dp2px(10f))
最終效果
- Android 5.0 & 5.1
- Android 6.0+