03-导航栏设置

导航栏设置

课程目标

  • 便利构造函数的使用
  • 自定义显示到 XIB 控制面板的属性
  • 自定义导航控制器思路

发现页面搜索框

课程目标

  • 明确 Xib 创建视图的流程
  • IBInspectable&IBDesignable使用

代码实现

  • 新建 HMDiscoverSearchView 继承于 UIView
class HMDiscoverSearchView: UIView,UITextFieldDelegate {

}
  • 新建 Xib 文件 HMDiscoverSearchView.xib
  1. 拖入 UITextField 作输入框
  • 拖入 UIButton 作取消按钮
  • 添加相关约束
  • 指定 class 为 HMDiscoverSearchView
  • 连线
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var cancelButton: UIButton!
  • HMDiscoverSearchView 提供类方法通过 xib 创建 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
}
  • 设置 textfield 的左边放大镜视图
private lazy var leftImage: UIImageView = {
    return UIImageView(image: UIImage(named: "searchbar_textfield_search_icon")!)
}()

...
override func awakeFromNib() {
    // 设置 textField 的左边视图
    leftImage.frame = CGRectMake(0, 0, frame.height, frame.height)
    leftImage.contentMode = .Center
    textField.leftView = leftImage
    // 设置显示模型
    textField.leftViewMode = UITextFieldViewMode.Always
}
  • 设置 textField 的代理,实现代理方法
class HMDiscoverSearchView: UIView,UITextFieldDelegate {
    ...

    func textFieldDidBeginEditing(textField: UITextField) {

    }
}

  • 拖入 textfield 右边的约束到 view 中,在开始编辑的时候执行动画
@IBOutlet weak var textFieldRightCons: NSLayoutConstraint!
  • 执行约束动画需要调用 view 的 layoutIfNeed
func textFieldDidBeginEditing(textField: UITextField) {
    textFieldRightCons.constant = cancelButton.frame.width
    // 执行动画
    UIView.animateWithDuration(0.25) { () -> Void in
        self.textField.layoutIfNeeded()
    }
}
  • 拖入取消按钮的点击事件,点击的时候取消第一响应者并执行动画
@IBAction func cancelButtonClick(sender: UIButton) {
    textField.resignFirstResponder()
    textFieldRightCons.constant = 0

    // 执行动画
    UIView.animateWithDuration(0.25) { () -> Void in
        self.textField.layoutIfNeeded()
    }
}

IBInspectable & IBDesignable

IBInspectable

  • 其修饰的属性可以在 XIB/SB 右边控制面板显示
  • 可以重写该属性的 get/set 方法做自己的操作

IBDesignable

  • 其修饰自定义 View
  • 可以在更改 IBInspectable 修饰的属性的时候动态在 XIB/SB 里面渲染

图片填充模式

图片填充模式.png

UIBarButtonItem抽取

  • 快速构造一个 UIBarButtonItem
// item 上的文字颜色,高亮颜色,字体大小
// 导航栏上左右的文字一般都会统一,所以可以定义成常量
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 {

    /// 快速构造一个 UIBarButtonItem
    ///
    /// - parameter imgName: 图片名字
    /// - parameter title:   标题文字
    /// - 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)

        // 如果有图片,设置图片
        if let img = imgName {
            button.setImage(UIImage(named: img), forState: UIControlState.Normal)
            button.setImage(UIImage(named: "\(img)_highlighted"), forState: UIControlState.Highlighted)
        }

        // 如果有文字,设置文字
        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

    }
}

自定义导航控制器

课程目标

自定义 UINavigationController,实现新浪微博左上角返回按钮逻辑

  • 如果是从一级页面进入到二级页面,第二级页面左上角返回按钮显示一级页面的title
  • 如果是从二级页面进入到三级页面(或者层次更深),进入页面的左上角返回按钮显示返回

分析

  • 如果要在每一个控制器里面分别设置的话,代码烦琐而且扩展性不强,所以写一个自己的 UINavigationController
  • 新push进入的控制器都会经过 UINavigationControllerpushViewController(viewController: UIViewController, animated: Bool) 方法
  • 可以在这个方法里面判断当前是 push 进入的是第几级控制器,并设置不同的返回按钮title

代码

import UIKit

class HMNavigationController: UINavigationController {

    /**
    重写此方法,在里面统一返回按钮逻辑

    - parameter viewController: 将要push进来的控制器
    - parameter animated:       是否需要动画
    */
    override func pushViewController(viewController: UIViewController, animated: Bool) {

        // 如果当前里面有控制器,才执行下面的逻辑
        if childViewControllers.count > 0 {

            var title = "返回"

            if childViewControllers.count == 1 {
                //正要往里面添加第二个控制器
                title = childViewControllers.first?.title ?? "返回"
            }
            // push第二个或者以后控制器隐藏底部tabBar
            viewController.hidesBottomBarWhenPushed = true
            // 设置左边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 添加子控制器的地方,使用自己定义的导航控制器

  • 默认push控制器的时候,顶部右边会出现部分阴影:
navigationBar-bug.png

解决方法:

// 给tabBar(或者navigationBar)设置一张背景图片
// HMMainViewController->ViewDidLoad()方法里面
let tab = HMTabBar()
// 设置撰写按钮点击的事件响应
tab.composeButtonClickBlock = {
    print("撰写按钮点击")
}
// 设置背景图片,去掉顶部阴影的效果
tab.backgroundImage = UIImage(named: "tabbar_background")
setValue(tab, forKey: "tabBar")

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容