導(dǎo)航欄設(shè)置
課程目標(biāo)
- 便利構(gòu)造函數(shù)的使用
- 自定義顯示到 XIB 控制面板的屬性
- 自定義導(dǎo)航控制器思路
發(fā)現(xiàn)頁面搜索框
課程目標(biāo)
- 明確 Xib 創(chuàng)建視圖的流程
- IBInspectable&IBDesignable使用
代碼實現(xiàn)
- 新建
HMDiscoverSearchView
繼承于UIView
class HMDiscoverSearchView: UIView,UITextFieldDelegate {
}
- 新建 Xib 文件
HMDiscoverSearchView.xib
- 拖入
UITextField
作輸入框
- 拖入
UIButton
作取消按鈕 - 添加相關(guān)約束
- 指定 class 為
HMDiscoverSearchView
- 連線
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var cancelButton: UIButton!
- 在
HMDiscoverSearchView
提供類方法通過 xib 創(chuàng)建 view
class func searchView() -> HMDiscoverSearchView {
let view = NSBundle.mainBundle().loadNibNamed("HMDiscoverSearchView", owner: nil, options: nil).last! as! HMDiscoverSearchView
return view;
}
- 在
HMDiscoverTableViewController
添加方法,測試此View的顯示
private func setupUI(){
let searchView = HMDiscoverSearchView.searchView()
searchView.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.size.width, 35)
navigationItem.titleView = searchView
}
- 設(shè)置
textfield
的左邊放大鏡視圖
private lazy var leftImage: UIImageView = {
return UIImageView(image: UIImage(named: "searchbar_textfield_search_icon")!)
}()
...
override func awakeFromNib() {
// 設(shè)置 textField 的左邊視圖
leftImage.frame = CGRectMake(0, 0, frame.height, frame.height)
leftImage.contentMode = .Center
textField.leftView = leftImage
// 設(shè)置顯示模型
textField.leftViewMode = UITextFieldViewMode.Always
}
- 設(shè)置 textField 的代理掰担,實現(xiàn)代理方法
class HMDiscoverSearchView: UIView,UITextFieldDelegate {
...
func textFieldDidBeginEditing(textField: UITextField) {
}
}
- 拖入
textfield
右邊的約束到 view 中,在開始編輯的時候執(zhí)行動畫
@IBOutlet weak var textFieldRightCons: NSLayoutConstraint!
- 執(zhí)行約束動畫需要調(diào)用 view 的 layoutIfNeed
func textFieldDidBeginEditing(textField: UITextField) {
textFieldRightCons.constant = cancelButton.frame.width
// 執(zhí)行動畫
UIView.animateWithDuration(0.25) { () -> Void in
self.textField.layoutIfNeeded()
}
}
- 拖入取消按鈕的點擊事件,點擊的時候取消第一響應(yīng)者并執(zhí)行動畫
@IBAction func cancelButtonClick(sender: UIButton) {
textField.resignFirstResponder()
textFieldRightCons.constant = 0
// 執(zhí)行動畫
UIView.animateWithDuration(0.25) { () -> Void in
self.textField.layoutIfNeeded()
}
}
IBInspectable & IBDesignable
IBInspectable
- 其修飾的屬性可以在 XIB/SB 右邊控制面板顯示
- 可以重寫該屬性的 get/set 方法做自己的操作
IBDesignable
- 其修飾自定義 View
- 可以在更改
IBInspectable
修飾的屬性的時候動態(tài)在 XIB/SB 里面渲染
圖片填充模式
UIBarButtonItem抽取
- 快速構(gòu)造一個
UIBarButtonItem
// item 上的文字顏色,高亮顏色带迟,字體大小
// 導(dǎo)航欄上左右的文字一般都會統(tǒng)一演熟,所以可以定義成常量
private let ItemNormalColor = UIColor(red: 80/255, green: 80/255, blue: 80/255, alpha: 1)
private let ItemHighlightedColor = UIColor.orangeColor()
private let ItemFontSize: CGFloat = 14
extension UIBarButtonItem {
/// 快速構(gòu)造一個 UIBarButtonItem
///
/// - parameter imgName: 圖片名字
/// - parameter title: 標(biāo)題文字
/// - parameter target:
/// - parameter action:
///
/// - returns: UIBarButtonItem
convenience init(imgName: String? = nil,title: String? = nil, target: AnyObject?, action: Selector){
self.init()
let button = UIButton()
button.addTarget(target, action: action, forControlEvents: .TouchUpInside)
// 如果有圖片,設(shè)置圖片
if let img = imgName {
button.setImage(UIImage(named: img), forState: UIControlState.Normal)
button.setImage(UIImage(named: "\(img)_highlighted"), forState: UIControlState.Highlighted)
}
// 如果有文字项郊,設(shè)置文字
if let t = title {
button.setTitle(t, forState: UIControlState.Normal)
button.titleLabel?.font = UIFont.systemFontOfSize(ItemFontSize)
button.setTitleColor(UIColor(red: 80/255, green: 80/255, blue: 80/255, alpha: 1), forState: .Normal)
button.setTitleColor(UIColor.orangeColor(), forState: .Highlighted)
}
button.sizeToFit()
customView = button
}
}
自定義導(dǎo)航控制器
課程目標(biāo)
自定義 UINavigationController
,實現(xiàn)新浪微博左上角返回按鈕邏輯
- 如果是從一級頁面進入到二級頁面斟赚,第二級頁面左上角返回按鈕顯示
一級頁面的title
- 如果是從二級頁面進入到三級頁面(或者層次更深)着降,進入頁面的左上角返回按鈕顯示
返回
分析
- 如果要在每一個控制器里面分別設(shè)置的話,代碼煩瑣而且擴展性不強拗军,所以寫一個自己的
UINavigationController
- 新push進入的控制器都會經(jīng)過
UINavigationController
的pushViewController(viewController: UIViewController, animated: Bool)
方法 - 可以在這個方法里面判斷當(dāng)前是 push 進入的是第幾級控制器任洞,并設(shè)置不同的返回按鈕title
代碼
import UIKit
class HMNavigationController: UINavigationController {
/**
重寫此方法,在里面統(tǒng)一返回按鈕邏輯
- parameter viewController: 將要push進來的控制器
- parameter animated: 是否需要動畫
*/
override func pushViewController(viewController: UIViewController, animated: Bool) {
// 如果當(dāng)前里面有控制器发侵,才執(zhí)行下面的邏輯
if childViewControllers.count > 0 {
var title = "返回"
if childViewControllers.count == 1 {
//正要往里面添加第二個控制器
title = childViewControllers.first?.title ?? "返回"
}
// push第二個或者以后控制器隱藏底部tabBar
viewController.hidesBottomBarWhenPushed = true
// 設(shè)置左邊item
viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(imgName: "navigationbar_back_withtext", title: title, target: self, action: "back")
}
super.pushViewController(viewController, animated: animated)
}
@objc private func back(){
popViewControllerAnimated(true)
}
}
在 HMMainViewController 添加子控制器的地方交掏,使用自己定義的導(dǎo)航控制器
- 默認push控制器的時候,頂部右邊會出現(xiàn)部分陰影:
解決方法:
// 給tabBar(或者navigationBar)設(shè)置一張背景圖片
// HMMainViewController->ViewDidLoad()方法里面
let tab = HMTabBar()
// 設(shè)置撰寫按鈕點擊的事件響應(yīng)
tab.composeButtonClickBlock = {
print("撰寫按鈕點擊")
}
// 設(shè)置背景圖片器紧,去掉頂部陰影的效果
tab.backgroundImage = UIImage(named: "tabbar_background")
setValue(tab, forKey: "tabBar")