[Android開發學iOS系列] 快速上手UIKit

2022-10-13 06:00:17

快速上手iOS UIKit

UIKit是蘋果官方的framework, 其中包含了各種UI元件, window和view, 事件處理, 互動, 動畫, 資源管理等基礎設施支援.

按照前面的介紹, 用UIKit寫UI可以用storyboard(Interface Builder)和程式碼兩種方式.

大體的思路都是新增元件後, 設定屬性, 設定尺寸位置約束, 處理響應事件.

這裡主要介紹用程式碼寫的情形.
希望這篇文章, 可以幫你快速上手UIKit, 熟悉常用的元件, 完成一些簡單的UI介面相關任務.

在程式碼中寫UI的基本步驟

在程式碼中寫UI的步驟大致是:

  • 初始化.
  • addSubview新增到當前view, 或hierarchy中的其他可達view.
  • 設定約束.

比如:

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方法.
  • 如果在程式碼中設定UI元件的constraints, 那麼這個屬性經常要設定為false: translatesAutoresizingMaskIntoConstraints = **false**. 如果元件的位置是通過frame來設定的, 則不用設定這個屬性.
  • 約束有多種寫法, 這裡只是其中一種, 用anchor的方式.

常用元件

文字: UILabel

設定文字等屬性:

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不同, 這點我們後面說繼承關係的時候解釋一下.

按鈕: 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.

輸入框: UITextField

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, 一般用來在幾個選項中做選擇.

其他

  • view中比較常用的屬性isHidden, 控制view是否需要隱藏.
  • 所有的UIView都有一個layer屬性.
    設定border的寬度和顏色就在layer上設定.
    CALayer在UIView之下. 所以不知道UIColor, 只知道CGColor.

本文僅列出幾個常用元件, 更多的請看官方範例.

這裡可以下載

繼承關係

NSObject是所有Cocoa Touch class的基礎類別. 所有UIKit中的類都是它的子類.

這裡有一個類關係的圖:

我們這裡不展開講述所有了, 只解答一下前面提出的關於UILabel點選事件的問題.

這裡可以看到UILabelUIButton雖然都繼承了UIView, 但是UIButton的繼承層次更深一些, 它還繼承了了UIControl.

可以看到和UIButton平級的還有好幾個子類.

Controls使用的是target-action機制, 所有的action都通過方法: addTarget(_:action:for:) 新增.

約束Constraints

當在程式碼中設定約束時, 有三種選擇:

  • 使用layout anchors.
  • 使用NSLayoutConstraint類.
  • 使用Visual Format Language.

上面我們提到過的就是其中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.

Bonus

  • 友情提示: 在xcode裡就可以看官方檔案, 快捷鍵是Cmd + Shift + 0.

References