Fork me on GitHub

开始用Swift开发iOS 10 - 12 丰富Detail View和定制化Navigation Bar

上一篇开始用Swift开发iOS 10 - 11 面向对象编程介绍对代码做了一点修改,这一篇来丰富一下详情页和定制化Navigation Bar。

重新设计详细页面

  • 选中Main.storyboard,删除Image View和三个Label。

  • 添加Table View,修改其大小为整个View,并且添加一些约束。设置prototype cells为1;table view cell的identifierCellrow height为36。
    向Detail View Controller中添加一个Table View

  • 在table view的头部添加一个image view,给变其高度为300,宽度为View的宽度。

  • 连接image view和RestaurantDetailViewController中的restaurantImageView接口。

  • 修改Image View的content modeAspect Fit,并勾选Clip to Bounds

定制 Prototype Cell

  • 增加两个label,分别命名为FieldValue ,字体修改成自己想要的。把它们组成一个Stack View。
  • 为Stack View添加一些约束。
    在cell中垂直居中;Trailing Space 和 Leading Space都为零。

Ctrl-dragFieldLabel到ValueLabel,选择Equal Widths,生成一个FieldLabel与ValueLabel宽度相同的约束。修改Multiplier值为0.5,就是FieldLabel的宽度是ValueLabel的一半。

  • 新建RestaurantDetailTableViewCell类文件,继承至UITableViewCell。添加两个接口,并关联上面的两个Label。
    1
    2
    @IBOutlet var fieldLabel:UILabel!
    @IBOutlet var valueLabel:UILabel!

更新 RestaurantDetailViewController

  • 实现UITableViewDataSourceUITableViewDelegate:

    class RestaurantDetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
  • 实现UITableViewDataSource的相关方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 4
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! RestaurantDetailTableViewCell
    // Configure the cell...
    switch indexPath.row {
    case 0:
    cell.fieldLabel.text = "Name"
    cell.valueLabel.text = restaurant.name
    case 1:
    cell.fieldLabel.text = "Type"
    cell.valueLabel.text = restaurant.type
    case 2:
    cell.fieldLabel.text = "Location"
    cell.valueLabel.text = restaurant.location
    case 3:
    cell.fieldLabel.text = "Been here"
    cell.valueLabel.text = (restaurant.isVisited) ? "Yes, I've been herebefore" : "No"
    default:
    cell.fieldLabel.text = ""
    cell.valueLabel.text = ""
    }

    cell.backgroundColor = UIColor.clear

    return cell
    }
  • 把table view的delegatedataSource接口设置成Restaurant Detail View Controller

定制table view 的样式

  • RestaurantDetailViewController中添加一个接口变量,并关联storyboard中的table view。
    @IBOutlet var tableView:UITableView!

  • 设置table view的背景颜色,在viewDidLoad中添加:
    tableView.backgroundColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.2)
    新加的颜色是亮灰色(和白色相近,可以设置成其他深颜色做对比),运行后不是整个table view都变色。

    这是因为,每一个cell都是重新添加的,cell的背景颜色还是默认的白色,覆盖了table view的背景颜色,要在tableView(_:cellForRowAt:)return之前添加:
    cell.backgroundColor = UIColor.clear

  • 移除table view中空cell的分割线,在viewDidLoad中添加:

    tableView.tableFooterView = UIView(frame: CGRect.zero)
    
  • 改变分割线的颜色, 在viewDidLoad中添加:
    tableView.separatorColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.8)
    

定制Navigation Bar的样式

通过UINavigationBar.appearance()修改Navigation Bar的样式。

Navigation Bar的样式修改是整体修改的,所以修改Navigation Bar的样式代码要写在application(_:didFinishLaunchingWithOptions:)方法中。

  • 修改navigation bar的背景颜色:
    UINavigationBar.appearance().barTintColor = UIColor(red: 216.0/255.0, green: 74.0/255.0, blue: 32.0/255.0, alpha: 1.0)
    
  • 修改title样式:
    1
    2
    3
    if let barFont = UIFont(name: "Avenir-Light", size: 24.0) {
    UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white, NSFontAttributeName:barFont]
    }

Avenir-Light是字体名称,详细的iOS字体可查 http://iosfonts.com

  • tintColor控制Navigation items和bar button items的颜色
    UINavigationBar.appearance().tintColor = UIColor.white

目前,Navigation bar的返回按钮是一个<Food Pin,想删除Food Pin,需要修改RestaurantTableViewControllerbackBarButtonItem属性。
RestaurantTableViewControllerviewDidLoad中添加:
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

为 detail view 的 Navigation bar 添加title,在 RestaurantDetailViewControllerviewDidLoad中添加:
title = restaurant.name

隐藏Navigation Bar

  • 自从iOS 8后,Navigation Bar可以在不同情况下隐藏,在storyboard中选择Navigation Controller修改。(On Swipe是向上滑)

  • 但这种设置整个app的Navigation Bar都会隐藏。如果只想在restaurant table view controller中隐藏,在detail view中不隐藏,就需要在两个控制器的viewDidLoad分别设置:navigationController?.hidesBarsOnSwipe = truenavigationController?.hidesBarsOnSwipe = false

  • 运行反复测试后发现两个问题:

    1. 当从detail view返回后,restaurant table view controllerNavigation Bar不能隐藏。
    2. restaurant table view controllerNavigation Bar隐藏后进入detail view后, Navigation Bar消失不能再显示。

首先明确两个控制器中的navigationController属性指的是同一个Navigation Controller ,viewDidLoad方法是view第一次加载时调用,之后就不再调用了。 也就是说当从detail view返回,hidesBarsOnSwipe已经被设置为false,而到restaurant table view controllerviewDidLoad不再调用,所以Navigation Bar不能再隐藏。

解决办法是使用viewWillAppear,这个方法是在视图每一次显示时调用。
RestaurantTableViewController中添加:

1
2
3
4
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnSwipe = true
}

RestaurantDetailViewController中添加:

1
2
3
4
5
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnSwipe = false
navigationController?.setNavigationBarHidden(false, animated: true)
}

修改Status Bar样式

app中Status Bar的默认样式是黑色。

Info.plist中添加一个key为View controller-based status bar appearance,值为NO。然后application(_:didFinishLaunchingWithOptions:)中添加:UIApplication.shared.statusBarStyle = .lightContent

代码

Beginning-iOS-Programming-with-Swift

说明

此文是学习appcode网站出的一本书 《Beginning iOS 10 Programming with Swift》 的一篇记录

坚持原创技术分享,您的支持将鼓励我继续创作!
  • 本文标题: 开始用Swift开发iOS 10 - 12 丰富Detail View和定制化Navigation Bar
  • 本文作者: AndyRon
  • 发布时间: 2017年07月19日 - 00:00
  • 最后更新: 2017年09月09日 - 12:58
  • 本文链接: http://andyron.com/2017/beginning-ios-swift-12.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!