iOS界面开发—开篇

当前篇:iOS界面开发—开篇
下一篇:iOS界面开发—导航控制器和标签控制器

前言

本系列文章用来总结我自己做iOS开发的一些UI方面的经验,我从零开始跌跌撞撞做了三年iOS开发,能力有限,经验有限,如果有读者读到我的文章,有发现不对的地方,或者有更好的解决方法的地方,还望提出来一起讨论。

本系列文章不对开发语言进行讲解,代码用Swift4进行展示,同时不对UIKit框架的组件进行详细讲解。

我习惯用纯代码进行UI开发,因此文章里基本不会出现storyboard和xib,所以可能一些地方不适用于可视化界面开发,同时我很少用autolayout,我觉得手机屏幕尺寸固定有限,用代码布局妥妥的够了,也方便贴代码。

创建工程

首先创建一个UIStudy的工程,开发者账号及证书用你自己的就行,如果没有可以用虚拟机做测试,更改项目配置如下:

iOS界面开发—开篇_第1张图片
屏幕快照 2018-02-06 上午10.36.04.png

我们把Main Interface清空,表示不使用storyboard构建界面,现在编译应用可能会看到报错,提示safeArea在iOS 9.0之后才支持,可以把配置文件中的Deployment Target升到9.0,也可以在storyboard文件中把User Safe Area Layout Guides关掉

iOS界面开发—开篇_第2张图片
278DBDD7-DA03-4314-B635-2F9DF15C15E2.png

LaunchScreen.storyboard文件也一样,由于我们项目中没有用Main.storyboard来构建应用,所以可以选择删掉,但是LaunchScreen.storyboard文件暂时不能删掉,因为我们还需要用它来确保应用的窗口大小。

注意项目配置截图中Launch Images Source和Launch Screen File两个选项,它们是用来设置应用启动界面的,如果两个选项都没设置,那么应用可能不是全屏的,我们也可以用图片作为启动界面,需要给出每一种屏幕尺寸对应的图片,否则应用界面可能也不是全屏的,我们这里就不用图片了,就用LaunchScreen.storyboard文件作为启动界面就行了。

现在运行应用,我们看到的是一个黑框,如果需要显示图形界面,就需要手动创建了,这就是为什么我不用Main.storyboard的原因,因为不写代码可能不会知道应用的界面是怎么显示出来的。

手动显示界面

如果我们要让应用正常显示图形界面,就需要自己动手创建,核心就在于UIWindow。想要显示一个图形界面就需要创建一个 UIWindow ,设置rootViewController,然后让其成为主窗口:

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow.init(frame: UIScreen.main.bounds)
    window!.backgroundColor = UIColor.white
    window!.rootViewController = ViewController()
    window!.makeKeyAndVisible()
    return true
}

打开AppDelegate.swift编写以上代码,运行应用,我们就能看见一个白色的界面了,这个界面的内容就是ViewController中定义的内容,现在还是空的界面,稍候我们会在上面显示一些内容。

创建UIWindow时一定要指定frame,否则在iOS 8及以上系统中应用无法响应事件,同时最好设置一下背景色,否则可能会在某些极其特殊的情况下屏幕中间会出现黑块。

简单布局扩展

import UIKit

//MARK: 简单布局扩展
extension UIView {
    
    //MARK: iPhone X适配属性
    
    /** 高度减去iPhone X底部不安全高度*/
    var safeAreaBottom: CGFloat {
        if #available(iOS 11.0, *) {
            return height - safeAreaInsets.bottom
        } else {
            return height
        }
    }
    
    /** iPhone X顶部不安全高度*/
    var safeAreaTop: CGFloat {
        if #available(iOS 11.0, *) {
            return safeAreaInsets.top
        } else {
            return 0
        }
    }
    
    /** iPhone X安全区域高度*/
    var safeAreaHeight: CGFloat {
        if #available(iOS 11.0, *) {
            return height - safeAreaInsets.bottom - safeAreaInsets.top
        } else {
            return height
        }
    }
    
    var height: CGFloat {
        get {
            return self.frame.size.height
        }
        set {
            self.frame.size.height = newValue
        }
    }
    
    var width: CGFloat {
        get {
            return self.frame.size.width
        }
        set {
            self.frame.size.width = newValue
        }
    }
    
    var size: CGSize {
        get {
            return self.frame.size
        }
        set {
            self.frame.size = newValue
        }
    }
    
    var top: CGFloat {
        get {
            return self.frame.origin.y
        }
        set {
            self.frame.origin.y = newValue
        }
    }
    
    var bottom: CGFloat {
        get {
            return self.top + self.height
        }
        set {
            self.frame.origin.y = newValue - self.height
        }
    }
    
    var left: CGFloat {
        get {
            return self.frame.origin.x
        }
        set {
            self.frame.origin.x = newValue
        }
    }
    
    var right: CGFloat {
        get {
            return self.left + self.width
        }
        set {
            self.frame.origin.x = newValue - self.width
        }
    }
    
    var origin: CGPoint {
        get {
            return self.frame.origin
        }
        set {
            self.frame.origin = newValue
        }
    }
    
    var centerX: CGFloat {
        get {
            return self.center.x
        }
        set {
            self.center.x = newValue
        }
    }
    
    var centerY: CGFloat {
        get {
            return self.center.y
        }
        set {
            self.center.y = newValue
        }
    }
    
    //MARK: 适应性布局设置
    //例如:当改变left位置的时候,自适应宽度好保持视图right位置不变
    
    func autoLeft(_ new: CGFloat) {
        let widthChanged = left - new
        left = new
        width += widthChanged
    }
    
    func autoRight(_ new: CGFloat) {
        let widthChanged = right - new
        width -= widthChanged
    }
    
    func autoTop(_ new: CGFloat) {
        let heightChanged = top - new
        top = new
        height += heightChanged
    }
    
    func autoBottom(_ new: CGFloat) {
        let heightChanged = bottom - new
        height -= heightChanged
    }
    
}

请将上面代码写进项目中,方便我们在设置frame时更好的理解布局的意图,可以像我这样组织代码文件:

iOS界面开发—开篇_第3张图片
屏幕快照 2018-02-06 上午11.48.48.png

Hello World

下面我们在界面中显示一串Hello World,打开ViewController.swift文件编写代码:

import UIKit

class ViewController: UIViewController {
    
    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(label)
        label.text = "Hello World"
        label.sizeToFit()
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        label.centerX = view.width / 2
        label.centerY = view.height / 2
    }

}

手动布局的套路就是,在viewDidLoad方法中添加子视图,在viewWillLayoutSubviews方法中设置子视图位置,在viewDidLoad方法中获取view.frame是不准确的。使用viewWillLayoutSubviews或者layoutSubviews方法需要注意的就是在UIScrollView中,滑动事件也会触发布局方法,在滑动的时候不要去设置子视图位置。

运行应用,界面中央出现了一串大大的Hello World字样。

以上就是创建一个应用,显示一个图形界面,以及自定义图形界面内容的全过程,后面的UI开发都是基于此,无非就是把ViewController换成UITabBarController,UINavigationController而已。

当前篇:iOS界面开发—开篇
下一篇:iOS界面开发—导航控制器和标签控制器

你可能感兴趣的:(iOS界面开发—开篇)