客製化長相的UITabBarController

更新於 發佈於 閱讀時間約 9 分鐘

雖然我之前文章大力讚美SwiftUI的tabView有多好用,無奈專案大部分都是UIKit啊~~~~要在既有專案用Tab架構只能用UITabBarController了

設計這次還出了一個超複雜的UI,陰影+圓角+客製化高度 大套餐

馬上開始吧。

圓角+陰影

圓角+陰影很簡單,高度很難🥹

圓角+陰影很簡單,高度很難🥹


重點就是subclass一個UITabController 並去更改tabBar UI

也有人會在viewWillLayoutSubviews()或viewDidLayoutSubviews()去進行。

class MyTabController: UITabBarController {
func viewDidLoad() {
super.viewDidLoad()
setupTabBarUI()
}   

func setupTabBarUI() {
self.tabBar.backgroundColor = .white
self.tabBar.tintColor = .grayself.tabBar.layer.cornerRadius = 10
self.tabBar.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
self.tabBar.clipsToBounds = true
self.tabBar.layer.masksToBounds = false
self.tabBar.layer.shadowColor = UIColor.black.cgColor
self.tabBar.layer.shadowOpacity = 0.2
// 陰影要這樣畫,不然會太耗效能
self.tabBar.layer.shadowPath = UIBezierPath(roundedRect: self.tabBar.bounds, cornerRadius: 10.0).cgPath
}
}

陰影NG作法

研究的時候,發現有些人的作法是在TabBar後面墊一塊UIView當陰影。這個方法如果TabBar永恆存在的話沒問題,但有些動線需要push後隱藏Tab的話,官方提供的hidesBottomBarWhenPushed只會幫你隱藏TabBar本身,多墊的那塊UIView就要另外再處理,我覺得很不方便,不推薦。

高度

那如何更改高度呢?在網路上有查到2017年的答案StackOverflow是在viewWillLayoutSubviews去更改高度,但我用已經無效了。

我的作法是建立一個CustomTabBar,改他的高度。

class CustomTabBar: UITabBar {    
override func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 98
return sizeThatFits
}

然而使用自定義的Tabbar意外的困難,override tabBar屬性也沒反應(NG作法)

class MyTabController: UITabBarController {
// 沒有變高
override var tabBar: UITabBar {
return customTabBar
}
}

後來查到要使用object_setClass在runtime時把tabBar改掉。apple真的很難搞耶🧐

class MyTabController: UITabBarController {
init() {
super.init(nibName: nil, bundle: nil)
object_setClass(self.tabBar, CustomTabBar.self)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

成品

raw-image

同場加映:小紅點

原生提供的小紅點是有數字的

vc1.tabbarItem.badgeValue = "1"
raw-image


如果設計想要純小紅點怎麼辦??

有一種邪魔歪道(?的作法是,用同上方法,但不放數字

vc1.tabbarItem.badgeValue = ""
raw-image


雖然可以出現紅點,但整個大的不可思議,而且因為客製化高度,位置也跑掉。

增加客製化的小紅點

先做一個列出所有Tab的enum

enum V2TabBarItem {
case tab1
case tab2
case tab3

// badge tag要不同,新增移除時不會互相干擾
var badgeTag: Int {
switch self {
case .tab1:
return 6543
case .tab2:
return 6542
case .tab3:
return 6541
}
}

}

增加小紅點

private func addRedDotAtTabBarItem(tab: V2TabBarItem) {
guard let index = tabs.firstIndex(of: tab) else { return }
removeRedDotAtTabBarItem(tab: tab)
let radius: CGFloat = 5
let diameter = radius * 2
let topMargin:CGFloat = 17
let tabBarItemCount = CGFloat(tabBar.items?.count ?? 0)
let screenSize = UIScreen.main.bounds
let halfItemWidth = (screenSize.width) / (tabBarItemCount * 2)
let xOffset = halfItemWidth * CGFloat(index * 2 + 1)
let imageHalfWidth: CGFloat = ((tabBar.items?[index])?.selectedImage?.size.width ?? 0) / 2
// 離tab icon距離可自行調整
let redDot = UIView(frame: CGRect(x: xOffset + imageHalfWidth/2 + 3, y: topMargin, width: diameter, height: diameter))
redDot.tag = tab.badgeTag
redDot.backgroundColor = UIColor.red
redDot.layer.cornerRadius = radius
tabBar.addSubview(redDot)
}

移除小紅點

private func removeRedDotAtTabBarItem(tab: V2TabBarItem) {
for subview in tabBar.subviews {
if subview.tag == tab.badgeTag {
subview.removeFromSuperview()
break
}
}
}

加!!!!!

加在viewDidLoad裡會沒反應,我覺得應該是太快了tabBar UI還沒ready,我是選擇加在ViewDidAppear裡

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addRedDotAtTabBarItem(tab: .tab1)
}
VC生命週期

VC生命週期

成品

raw-image







avatar-img
7會員
35內容數
紀錄iOS開發上遇到的問題或是一些流程筆記。主要都是Swift。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Michelle Chen的沙龍 的其他內容
Sandbox 架構 /Documents:主要用於儲存用戶生成的數據或者不能重新創建的數據。這些可能包括由你的應用程式創建的文件、從服務器下載的文件、用戶在應用程式中創建或修改的數據等。 這些數據在應用程式的生命週期中是持久保存的,即使應用程式被終止或者系統重啟,這些數據也會保留。此外
SwiftUI的TabView實在太好用啦!我要大大的推廣他ლ(╹◡╹ლ) 換頁+小圓點滑動 無限自動輪播 底部Tabbar
這個浮誇標題是ChatGPT幫我想的😊 圖也是DALL幫我產的, AI萬歲! GCD也是面試必問題啊!我答超爛的,只會用背景呼叫API+切Main Thread更新畫面,今天就來認真了解。 GCD是什麼? 先來問ChatGPT什麼是GCD? GCD,全名 Grand Central Dis
字數算法 = string.count? 在swift算一個string的字數時候,很直覺的會想到用.count來算 let s = "這是幾個字呢".count print(s.count) // 6 毫無疑問的安心信賴6個字 表情符號的場合 let emoji = "😂" print
Xcode15的 @escaping closure裡解包後的[weak self]不必再寫 self了!! 用一個範例class Test來實驗,裡面只有一個變數a跟一個testClosure回"test",再用callTestClosure把變數a改成"test" 編譯正常!變數a成功被改成
一樣先來看官方文件 A view controller that provides access to documents or destinations outside your app’s sandbox. 其實就是讓你去讀取檔案App的東西 有兩種模式,Don’t copy the do
Sandbox 架構 /Documents:主要用於儲存用戶生成的數據或者不能重新創建的數據。這些可能包括由你的應用程式創建的文件、從服務器下載的文件、用戶在應用程式中創建或修改的數據等。 這些數據在應用程式的生命週期中是持久保存的,即使應用程式被終止或者系統重啟,這些數據也會保留。此外
SwiftUI的TabView實在太好用啦!我要大大的推廣他ლ(╹◡╹ლ) 換頁+小圓點滑動 無限自動輪播 底部Tabbar
這個浮誇標題是ChatGPT幫我想的😊 圖也是DALL幫我產的, AI萬歲! GCD也是面試必問題啊!我答超爛的,只會用背景呼叫API+切Main Thread更新畫面,今天就來認真了解。 GCD是什麼? 先來問ChatGPT什麼是GCD? GCD,全名 Grand Central Dis
字數算法 = string.count? 在swift算一個string的字數時候,很直覺的會想到用.count來算 let s = "這是幾個字呢".count print(s.count) // 6 毫無疑問的安心信賴6個字 表情符號的場合 let emoji = "😂" print
Xcode15的 @escaping closure裡解包後的[weak self]不必再寫 self了!! 用一個範例class Test來實驗,裡面只有一個變數a跟一個testClosure回"test",再用callTestClosure把變數a改成"test" 編譯正常!變數a成功被改成
一樣先來看官方文件 A view controller that provides access to documents or destinations outside your app’s sandbox. 其實就是讓你去讀取檔案App的東西 有兩種模式,Don’t copy the do
你可能也想看
Google News 追蹤
Thumbnail
在創作的路上真的很多人問我說 到底要怎麼做出符合自己期待 但又可以表現得很有美感的作品?🥹 這個問題真的應該是每個創作者都一直在學習的課題吧!
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
早在今年上半年有解析過「信邦」去年獲利表現,當時股價也確實從284元一路成長至345元,漲幅達2成以上,主要是今年上半年預期為營運谷底期,反應今年下半年有望重回成長趨勢。
接近學校的段考,已經連續兩個周末都待在家裡了。愛趴趴走的媽媽,其實有點耐不住~ 上次買的馬鈴薯要趕快煮以免發芽;還有冷凍庫裡的吻仔魚也待料理,好吧來煮頓晚餐。小孩都在房間念書,媽媽很閒,於是邊上網查作法邊洗菜,晚餐滷了一鍋肉,吻仔魚炒蛋,還有皮蛋地瓜葉。 結論是,媽媽我的手藝有點平淡,就可以吃但
Thumbnail
當公司準備要架設網站或改版網站的時候,會需要專業網頁設計公司服務,這邊推薦企業可以參考台中的網頁設計公司廠商,無論是RWD網頁設計、Wordpress網頁設計或者是需要完全客製化的網頁、台中的網頁設計公司都能選到適合的,評價也都非常好。 今天作者要來為大家推薦台中網頁設計公司介紹與評價,都是有很多
我自己是希望可以製作iOS app來更好存放我的文章, 更進階一點,可以變成直接錄音後, 照我設定的方式轉換成文檔,讓iPhone變成我更強的助手。 感覺有很多可以探索,用時間慢慢累積經驗。
Thumbnail
需求情境: 一般的看盤軟體,雖然都能針對一籃子自選股票,列出其即時行情和當天漲幅,但若要看「五日漲幅」呢?那就少見了,但這對我很重要。因為小部位的波段性價差交易是個好策略,這時候若能排序好一整排看下來,可以節省大量點來點去的成本,很有價值,所以就來自己刻。 解決方案: 從大處著眼,UI 最外層
Thumbnail
iPhone 最新作業系統 iOS 18 控制中心大更新,預設有常用功能、音樂播放器、連線控制三個頁面,並允許使用者自訂頁面,可以直接在控制中心管理所需的功能、調整位置和選擇尺寸。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
本文介紹如何使用UINavigationBarAppearance調整四種場景下的UI外觀,並探討客製化返回鍵UI又保留返回手勢的做法,可以有效地客製化NavigationBar的外觀,並避免一些NG作法。
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
雖然我之前文章大力讚美SwiftUI的tabView有多好用,無奈專案大部分都是UIKit啊~~~~要在既有專案用Tab架構只能用UITabBarController了 設計這次還出了一個超複雜的UI,陰影+圓角+客製化高度 大套餐 馬上開始吧。 圓角+陰影 重點就是subclass一個
Thumbnail
在創作的路上真的很多人問我說 到底要怎麼做出符合自己期待 但又可以表現得很有美感的作品?🥹 這個問題真的應該是每個創作者都一直在學習的課題吧!
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
早在今年上半年有解析過「信邦」去年獲利表現,當時股價也確實從284元一路成長至345元,漲幅達2成以上,主要是今年上半年預期為營運谷底期,反應今年下半年有望重回成長趨勢。
接近學校的段考,已經連續兩個周末都待在家裡了。愛趴趴走的媽媽,其實有點耐不住~ 上次買的馬鈴薯要趕快煮以免發芽;還有冷凍庫裡的吻仔魚也待料理,好吧來煮頓晚餐。小孩都在房間念書,媽媽很閒,於是邊上網查作法邊洗菜,晚餐滷了一鍋肉,吻仔魚炒蛋,還有皮蛋地瓜葉。 結論是,媽媽我的手藝有點平淡,就可以吃但
Thumbnail
當公司準備要架設網站或改版網站的時候,會需要專業網頁設計公司服務,這邊推薦企業可以參考台中的網頁設計公司廠商,無論是RWD網頁設計、Wordpress網頁設計或者是需要完全客製化的網頁、台中的網頁設計公司都能選到適合的,評價也都非常好。 今天作者要來為大家推薦台中網頁設計公司介紹與評價,都是有很多
我自己是希望可以製作iOS app來更好存放我的文章, 更進階一點,可以變成直接錄音後, 照我設定的方式轉換成文檔,讓iPhone變成我更強的助手。 感覺有很多可以探索,用時間慢慢累積經驗。
Thumbnail
需求情境: 一般的看盤軟體,雖然都能針對一籃子自選股票,列出其即時行情和當天漲幅,但若要看「五日漲幅」呢?那就少見了,但這對我很重要。因為小部位的波段性價差交易是個好策略,這時候若能排序好一整排看下來,可以節省大量點來點去的成本,很有價值,所以就來自己刻。 解決方案: 從大處著眼,UI 最外層
Thumbnail
iPhone 最新作業系統 iOS 18 控制中心大更新,預設有常用功能、音樂播放器、連線控制三個頁面,並允許使用者自訂頁面,可以直接在控制中心管理所需的功能、調整位置和選擇尺寸。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
本文介紹如何使用UINavigationBarAppearance調整四種場景下的UI外觀,並探討客製化返回鍵UI又保留返回手勢的做法,可以有效地客製化NavigationBar的外觀,並避免一些NG作法。
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
雖然我之前文章大力讚美SwiftUI的tabView有多好用,無奈專案大部分都是UIKit啊~~~~要在既有專案用Tab架構只能用UITabBarController了 設計這次還出了一個超複雜的UI,陰影+圓角+客製化高度 大套餐 馬上開始吧。 圓角+陰影 重點就是subclass一個