Android TabLayout图标与标题行内对齐实现及状态颜色问题咨询
解决TabLayout图标与文本行内显示并保留原生状态样式
嘿,这个问题我之前在项目里也踩过坑!新版Material Design Library确实把Tab的默认布局改成了图标在上、文字在下,要回到行内显示同时保留原生的状态(比如禁用时的颜色变化),咱们可以通过自定义Tab布局+状态选择器的方式完美解决,而且能和原生Tab的表现完全一致:
第一步:创建自定义Tab布局
先写一个横向排列的布局文件(比如res/layout/custom_tab.xml),把图标和文本放在同一行,同时给View绑定原生的样式属性,这样就能继承TabLayout的状态样式:
<?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="wrap_content" android:gravity="center" android:orientation="horizontal" android:paddingHorizontal="16dp" android:paddingVertical="8dp"> <ImageView android:id="@+id/tab_icon" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginEnd="8dp" android:drawableTint="?attr/tabIconTint" /> <TextView android:id="@+id/tab_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?attr/textAppearanceTab" /> </LinearLayout>
这里的关键是:
drawableTint绑定?attr/tabIconTint,让图标颜色跟随TabLayout的配置textAppearance绑定?attr/textAppearanceTab,让文本样式继承TabLayout的设置
第二步:配置TabLayout的状态颜色选择器
接下来要定义Tab在选中、未选中、禁用三种状态下的颜色,这样自定义布局才能响应状态变化:
1. 文本颜色选择器(res/color/tab_text_selector.xml)
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/tab_disabled" android:state_enabled="false" /> <item android:color="@color/tab_selected" android:state_selected="true" /> <item android:color="@color/tab_unselected" /> </selector>
2. 图标颜色选择器(res/color/tab_icon_selector.xml)
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/tab_disabled" android:state_enabled="false" /> <item android:color="@color/tab_selected" android:state_selected="true" /> <item android:color="@color/tab_unselected" /> </selector>
3. 在样式中关联选择器(res/values/styles.xml)
<style name="CustomTabLayoutStyle" parent="Widget.MaterialComponents.TabLayout"> <item name="tabTextColor">@color/tab_text_selector</item> <item name="tabSelectedTextColor">@color/tab_selected</item> <item name="tabIconTint">@color/tab_icon_selector</item> <item name="textAppearanceTab">@style/TabTextAppearance</item> </style> <style name="TabTextAppearance" parent="TextAppearance.MaterialComponents.Tab"> <item name="android:textColor">@color/tab_text_selector</item> </style>
别忘了在布局文件里给TabLayout应用这个样式:
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/CustomTabLayoutStyle" />
第三步:代码中设置Tab
最后在代码里给每个Tab设置自定义布局,同时绑定图标和文本,设置启用/禁用状态:
Kotlin 示例
val tabLayout = findViewById<TabLayout>(R.id.tabLayout) // 创建并添加第一个Tab(测试禁用状态) val disabledTab = tabLayout.newTab().apply { val tabView = LayoutInflater.from(context).inflate(R.layout.custom_tab, tabLayout, false) tabView.findViewById<ImageView>(R.id.tab_icon).setImageResource(R.drawable.ic_home) tabView.findViewById<TextView>(R.id.tab_title).text = "首页" customView = tabView isEnabled = false // 禁用这个Tab,颜色会自动切换为禁用色 } tabLayout.addTab(disabledTab) // 创建并添加第二个Tab val normalTab = tabLayout.newTab().apply { val tabView = LayoutInflater.from(context).inflate(R.layout.custom_tab, tabLayout, false) tabView.findViewById<ImageView>(R.id.tab_icon).setImageResource(R.drawable.ic_profile) tabView.findViewById<TextView>(R.id.tab_title).text = "我的" customView = tabView } tabLayout.addTab(normalTab)
Java 示例
TabLayout tabLayout = findViewById(R.id.tabLayout); // 禁用Tab TabLayout.Tab disabledTab = tabLayout.newTab(); View tabView1 = LayoutInflater.from(this).inflate(R.layout.custom_tab, tabLayout, false); ImageView icon1 = tabView1.findViewById(R.id.tab_icon); TextView title1 = tabView1.findViewById(R.id.tab_title); icon1.setImageResource(R.drawable.ic_home); title1.setText("首页"); disabledTab.setCustomView(tabView1); disabledTab.setEnabled(false); tabLayout.addTab(disabledTab); // 正常Tab TabLayout.Tab normalTab = tabLayout.newTab(); View tabView2 = LayoutInflater.from(this).inflate(R.layout.custom_tab, tabLayout, false); ImageView icon2 = tabView2.findViewById(R.id.tab_icon); TextView title2 = tabView2.findViewById(R.id.tab_title); icon2.setImageResource(R.drawable.ic_profile); title2.setText("我的"); normalTab.setCustomView(tabView2); tabLayout.addTab(normalTab);
这样设置后,自定义Tab不仅能实现图标和文本行内显示,还能完美响应选中、未选中、禁用的状态变化,颜色表现和原生Tab完全一致,再也不用头疼自定义布局不跟随原生样式的问题啦!
内容的提问来源于stack exchange,提问作者S K
相关产品推荐
相关产品推荐

