自定義 UITabBar 主要有兩條路徑:繼承 UITabBar 或繼承 UIView 完全自繪。本文聚焦繼承 UITabBar 方案,解決「如何精準調整系統按鈕佈局、插入自定義按鈕」的核心難點。
subviews 遠不止按鈕直接遍歷 self.subviews 會發現三類視圖:
UITabBarButton(私有類):真正的標籤按鈕UITabBarBackgroundView:背景視圖UIImageView:分隔線/陰影等裝飾視圖直接對所有 subviews 設 frame 會導致背景、分隔線錯位,必須過濾出按鈕。
UITabBarButton 是私有類,無法直接 #import,需用 NSClassFromString 動態獲取:
- (void)layoutSubviews {
[super layoutSubviews];
Class btnClass = NSClassFromString(@"UITabBarButton");
for (UIView *child in self.subviews) {
if ([child isKindOfClass:btnClass]) {
// 這裡安全調整按鈕 frame、插入自定義按鈕等
// 例:child.frame = CGRectMake(...);
}
}
}
UIButton,並調整左右原生按鈕間距self.bounds.width / 按鈕數 重新分佈UIControlEventTouchUpInside 切換 selectedImage/title 顏色init 佈局:此時 subviews 尚未建立,需在 layoutSubviews 或 setItems: 之後layoutSubviews 會多次調用,佈局邏輯需冪等UITabBarAppearance,背景圖/陰影建議改用 Appearance API,而非直接改 subviewssafeAreaInsets.bottom,避免按鈕被 Home Indicator 遮擋| 方案 | 優點 | 缺點 |
|---|---|---|
| 繼承 UITabBar | 保留系統動畫、無障礙、外觀代理 | 依賴私有類結構,版本升級風險 |
| 繼承 UIView + 隱藏原生 TabBar | 完全可控、無私有 API 風險 | 需手動實現選中動畫、無障礙、旋轉適配 |
| 第三方庫(如 CYLTabBarController) | 功能豐富、維護良好 | 引入依賴、體積增大 |
對於「微調按鈕佈局、加個中間按鈕」等輕度需求,繼承 UITabBar + Runtime 過濾是性價比最高的方案;重度定製建議轉向完全自繪或成熟第三方庫。