UIKit是蘋果官方的framework, 其中包含了各種UI元件, window和view, 事件處理, 互動, 動畫, 資源管理等基礎設施支援.
按照前面的介紹, 用UIKit寫UI可以用storyboard(Interface Builder)和程式碼兩種方式.
大體的思路都是新增元件後, 設定屬性, 設定尺寸位置約束, 處理響應事件.
這裡主要介紹用程式碼寫的情形.
希望這篇文章, 可以幫你快速上手UIKit, 熟悉常用的元件, 完成一些簡單的UI介面相關任務.
在程式碼中寫UI的步驟大致是:
比如:
class ViewController: UIViewController {
var myLabel: UILabel!
override func loadView() {
view = UIView()
view.backgroundColor = .white
// 建立範例
myLabel = UILabel()
myLabel.translatesAutoresizingMaskIntoConstraints = false
myLabel.text = "Hello"
// 新增到view中
view.addSubview(myLabel)
// 設定約束
NSLayoutConstraint.activate([
myLabel.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
myLabel.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
])
}
}
這裡有幾點說明:
var** myLabel: UILabel!
元件欄位這樣宣告有lateinit的作用, 如果不帶!會報錯, 說controller沒有init方法.translatesAutoresizingMaskIntoConstraints = **false**
. 如果元件的位置是通過frame來設定的, 則不用設定這個屬性.設定文字等屬性:
myLabel = UILabel()
myLabel.translatesAutoresizingMaskIntoConstraints = false
myLabel.font = UIFont.systemFont(ofSize: 24)
myLabel.text = "Hello"
myLabel.numberOfLines = 0
myLabel.textAlignment = .right
給UILabel設定點選事件:
myLabel.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(userDidTapLabel(tapGestureRecognizer:)))
myLabel.addGestureRecognizer(tapGesture)
點選事件處理方法:
@objc func userDidTapLabel(tapGestureRecognizer _: UITapGestureRecognizer) {
print("label clicked!")
}
這裡有#selector
, 對應的userDidTapLabel方法要加上@objc
. 便於OC的程式碼呼叫能找到swift的方法.
給UILabel設定點選事件和UIButton不同, 這點我們後面說繼承關係的時候解釋一下.
設定文字:
submitButton = UIButton(type: .system)
submitButton.translatesAutoresizingMaskIntoConstraints = false
submitButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
submitButton.setTitle("SUBMIT", for: .normal)
submitButton.setTitleColor(.black, for: .normal)
設定點選事件:
submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)
@objc func submitTapped(_ sender: UIButton) {
}
這裡使用@objc
的理由同上.
基本上我們在iOS程式碼中用到#
的時候, 對應的方法都要加上@objc
.
myTextField = UITextField()
myTextField.translatesAutoresizingMaskIntoConstraints = false
myTextField.placeholder = "What's your name?"
myTextField.textAlignment = .center
myTextField.font = UIFont.systemFont(ofSize: 44)
想要禁用輸入框可以這樣:
myTextField.isUserInteractionEnabled = false
在app裡簡單的互動我們經常需要彈出一個對話方塊:
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alert, animated: true)
其中preferredStyle有.alert
和.actionSheet
兩種.
.alert
是中心的對話方塊, 一般用於資訊提示或者確認操作; .actionSheet
是底部的bottom sheet, 一般用來在幾個選項中做選擇.
isHidden
, 控制view是否需要隱藏.layer
屬性.本文僅列出幾個常用元件, 更多的請看官方範例.
NSObject
是所有Cocoa Touch class的基礎類別. 所有UIKit中的類都是它的子類.
這裡有一個類關係的圖:
我們這裡不展開講述所有了, 只解答一下前面提出的關於UILabel點選事件的問題.
這裡可以看到UILabel
和UIButton
雖然都繼承了UIView
, 但是UIButton
的繼承層次更深一些, 它還繼承了了UIControl
.
可以看到和UIButton平級的還有好幾個子類.
Controls使用的是target-action機制, 所有的action都通過方法: addTarget(_:action:for:)
新增.
當在程式碼中設定約束時, 有三種選擇:
NSLayoutConstraint
類.上面我們提到過的就是其中Layout Anchors的寫法:
初級單個寫法:
buttonsView.topAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
buttonsView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
buttonsView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
buttonsView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
放進陣列裡批次啟用寫法:
NSLayoutConstraint.activate([
buttonsView.topAnchor.constraint(equalTo: view.centerYAnchor),
buttonsView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
buttonsView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
buttonsView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])
感覺是對新手比較直觀的一種寫法.
其他寫法文末有參考檔案.
PS: 專案中更流行用 SnapKit.
safeAreaLayoutGuide
: 去掉圓角和劉海.layoutMarginsGuide
: safe area的內部再加上一些額外的margin.Cmd + Shift + 0
.