上次客製化TabbarController,這次輪到UINavigationController
一言以蔽之,就是用iOS13後出的UINavigationBarAppearance
調整
四種場景UI可設定
- standardAppearance:用於設置導航欄在標準狀態下的外觀。這通常是默認的外觀配置。
- scrollEdgeAppearance:用於設置導航欄在用戶滾動到內容邊緣時的外觀。當用戶滾動到內容的頂部或底部時,這個外觀配置會生效。
- compactAppearance:用於設置導航欄在緊湊狀態下的外觀,通常在設備處於橫向模式時生效。
- compactScrollEdgeAppearance:用於設置導航欄在緊湊狀態下並且用戶滾動到內容邊緣時的外觀。
這邊我覺得很容易想錯,standardAppearance是指滾動的時候,scrollEdgeAppearance反而才是一開始會看到的(因為預設是頂端)。
原生樣式

原生樣式
- NavigationBar未滑動時背景是透明的
- 返回鍵會自動帶入上一頁標題且為藍色
- 標題黑色且字體大小固定
改變返回鍵&背景顏色&標題顏色大小

改變樣式!!!
class MyNVC: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
let appearance = UINavigationBarAppearance()
// 設定標題文字與大小
appearance.titleTextAttributes = [.foregroundColor: UIColor.white, .font: UIFont.systemFont(ofSize: 20.0, weight: .semibold)]
// 設定背景顏色
appearance.backgroundColor = .systemBlue
// 設定返回鍵normal狀態
let a = UIBarButtonItemAppearance()
let buttonItemAppearance = UIBarButtonItemAppearance()
let normal = buttonItemAppearance.normal
// 不顯示上一頁title(設成透明)
normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
// 設定使用自己的圖片
normal.backgroundImage = UIImage(named: "back")
appearance.backButtonAppearance = buttonItemAppearance
navigationBar.standardAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance
}
}
我的做法是先subclass一個NVC,並在viewdidload時去設定他的appearance。
底部陰影
NG作法
// 會變一條實心的線
appearance.shadowColor = .gray

實心線
有效做法
// 用圖的方式放上去
appearance.shadowImage = UIImage(named: "shadow")

陰影
StackOverFlow上也有人是用程式動態渲染出陰影圖片再放,或在navigationBar的layer上加,可是都比較麻煩,最好就是請設計單獨出一張陰影線的圖片XD
用UINavigationBarAppearance的優點
- 可以客製化的地方很多: 太多了反而覺得有點頭昏😵💫 裡面還有很多我沒用到的。
- 客製化返回鍵UI又保留返回手勢
以前我們專案有另一種做法是去subclass VC,在viewdidLoad時把最左按鈕改成自定義的,缺點是會喪失掉原生的返回手勢,變成只能點擊按鈕返回,對使用者比較難用。
NG作法(不好用!)
class MyVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let goBackBtn = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(goBack))
self.navigationItem.leftBarButtonItem = goBackBtn
}
@objc func goBack() {
self.navigationController?.popViewController(animated: true)
}
}