使用 TabHost 時常遇到「只有文字、圖標不顯示」或「圖文重疊」問題。本文深度剖析 TabHost 圖標顯示機制,提供從 XML 佈局到代碼實現的完整解決方案。
您的代碼中關鍵問題:
spec 變數被重複賦值,第一個標籤配置丟失setContent 僅設定 View ID,未關聯實際 Activity/內容android.R.drawable.xxx 在不同 API 級別可能不存在或樣式不一<TabHost xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 標籤 1 內容 -->
<LinearLayout
android:id="@+id/tab1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Tab 1 內容"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- 標籤 2 內容 -->
<LinearLayout
android:id="@+id/tab2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Tab 2 內容"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
public class MainActivity extends TabActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabHost = getTabHost();
Resources res = getResources();
// 標籤 1:使用 Intent 關聯內容(推薦)
Intent intent1 = new Intent(this, Tab1Activity.class);
TabHost.TabSpec spec1 = tabHost.newTabSpec("tab1")
.setIndicator("標籤一", res.getDrawable(R.drawable.ic_tab_home)) // 使用專案自有圖標
.setContent(intent1);
tabHost.addTab(spec1);
// 標籤 2:使用 View ID 關聯內容(簡單場景)
TabHost.TabSpec spec2 = tabHost.newTabSpec("tab2")
.setIndicator("標籤二", res.getDrawable(R.drawable.ic_tab_profile))
.setContent(R.id.tab2); // 對應 XML 中的 android:id="@+id/tab2"
tabHost.addTab(spec2);
tabHost.setCurrentTab(0);
}
}
| 場景 | 圖標來源 | 建議尺寸 | 注意事項 |
|---|---|---|---|
| API 21+ (Material) | 專案 res/drawable-xxx/ | 24x24 dp (mdpi 基準) | 提供 mdpi/hdpi/xhdpi/xxhdpi/xxxhdpi 完整套圖 |
| API < 21 | 專案自有圖標 | 32x32 px (舊版 TabWidget) | 系統圖標 android.R.drawable.* 不保證跨版本一致 |
| 向量圖標 | VectorDrawable (API 21+) | 任意(矢量縮放) | 需 vectorDrawables.useSupportLibrary = true |
原因:TabWidget 預設高度不足容納圖文垂直排列。
解決:自訂 Tab 標籤佈局:
// 代碼中使用
View tabView = LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
((ImageView) tabView.findViewById(R.id.tab_icon)).setImageResource(R.drawable.ic_tab_home);
((TextView) tabView.findViewById(R.id.tab_text)).setText("首頁");
spec1.setIndicator(tabView);
現代替代方案:
遷移範例:
// MainActivity.java
ViewPager2 viewPager = findViewById(R.id.viewPager);
TabLayout tabLayout = findViewById(R.id.tabLayout);
viewPager.setAdapter(new FragmentStateAdapter(this) { ... });
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
tab.setText(titles[position]).setIcon(icons[position]);
}).attach();
TabHost 圖標不顯示的核心原因通常是 TabSpec 變數覆蓋 與 內容關聯缺失。使用獨立變數建立每個 TabSpec、正確設定 setContent(Intent/ViewID)、使用專案自有圖標資源即可解決。但強烈建議新專案採用 ViewPager2 + TabLayout,獲得更好的使用者體驗、開發效率與長期維護性。