輸入多行文字 UITextView

UITextView 與 UITextField 有點類似,時常用在輸入或顯示多行文字,很常見的應用就是通訊軟體的文字輸入框,你可以輸入多行文字一次送出。本節的目標如下:

uitextview01

建立一個 UITextView

首先在 Xcode 裡,新建一個 Single View Application 類型的專案,取名為 ExUITextView 。

這節建立 UITextView 時,我們會為ViewController建立一個UITextView屬性,以因應後續的使用,如下:

class ViewController: UIViewController {
    // 建立一個 UITextView 的屬性
    var myTextView: UITextView!

    override func viewDidLoad() {
        // 省略
    }
}

接著便在viewDidLoad()中建立 UITextView ,可以看到這邊是使用屬性myTextView來生成,如下:

// 使用 UITextView(frame:) 建立一個 UITextView
myTextView = UITextView(
  frame: CGRect(x: 0, y: 0, width: 250, height: 200))

與 UITextField 類似,有許多一樣的屬性可以設定,如下:

// 背景顏色
myTextView.backgroundColor = UIColor.darkGray

// 文字顏色
myTextView.textColor = UIColor.white

// 文字字型及大小
myTextView.font = UIFont(name: "Helvetica-Light", size: 20)

// 文字向左對齊
myTextView.textAlignment = .left

// 預設文字內容
myTextView.text = "Swift 起步走"

// 適用的鍵盤樣式 這邊選擇預設的
myTextView.keyboardType = .default

// 鍵盤上的 return 鍵樣式 這邊選擇預設的
myTextView.returnKeyType = .default

另外常用的屬性還有如下:

// 文字是否可以被編輯
myTextView.isEditable = true

// 文字是否可以被選取
myTextView.isSelectable = true

最後就是將元件加入畫面中:

// 設置於畫面的中間偏上位置
myTextView.center = CGPoint(
  x: fullScreenSize.width * 0.5,
  y: fullScreenSize.height * 0.3)

// 加入畫面
self.view.addSubview(myTextView)

自訂選取內容後的選項

當顯示一段文字時,可以在選取文字後,對這段文字進行操作,像是全選、複製、貼上等等。除此之外,我們還可以自己增加需要的功能選項,如下:

// 建立兩個新的選項
let mail = UIMenuItem(
  title: "寄送", 
  action: #selector(ViewController.sendMail))
let facebook = UIMenuItem(
  title: "FB",
  action: #selector(ViewController.sendFB))

// 建立選單
let menu = UIMenuController.shared

// 將新的選項加入選單
menu.menuItems = [mail,facebook]

上述程式中,建立選項時可以看到UIMenuItem()的其中一個參數為action,這代表按下這個選項後要執行的動作,而這個動作會寫在#selector(ViewController.sendMail),也就是ViewControllersendMail方法中,所以我們還需要為這兩個新的選項加上新的ViewController的方法,用來處理按下後的動作,如下:

@objc func sendMail() {
    print("sendMail")
}

@objc func sendFB() {
    print("sendFB")
}

選項建立好後,就可以看到下面這樣的結果,有額外的選項可供選擇:

uitextview02

Hint
  • 如果要為不同輸入框元件設置不同的選取內容後的選單,可以將上述建立選單的程式,改放到元件取得焦點時的方法。以UITextView來說,就可以寫在textViewDidBeginEditing(textView: UITextView)這個委任函式中(這節範例沒有設置UITextViewDelegate委任模式,必須再自己加上)。而有不同元件(像是UITextField)同時存在時,就是在各自取得焦點(也就是becomefirstresponder)時設置不同選單。

按空白處隱藏鍵盤

介紹前一節的 UITextField 時,是使用鍵盤上的return鍵來隱藏鍵盤,而使用 UITextView 時,有時候會需要換行就沒辦法使用return鍵來結束編輯,這時就需要使用別的方式來替換。這邊介紹一個常用的方式,以按輸入框之外其他空白處的方式來隱藏鍵盤。

// 增加一個觸控事件
let tap = UITapGestureRecognizer(
  target: self,
  action: #selector(ViewController.hideKeyboard(tapG:)))

tap.cancelsTouchesInView = false

// 加在最基底的 self.view 上
self.view.addGestureRecognizer(tap)

上述程式可以看到同樣需要一個action來處理這個觸控事件,所以需要為ViewController加上一個新的方法hideKeyboard(tapG:),如下:

@objc func hideKeyboard(tapG:UITapGestureRecognizer){
    // 除了使用 self.view.endEditing(true)
    // 也可以用 resignFirstResponder()
    // 來針對一個元件隱藏鍵盤
    self.myTextView.resignFirstResponder()
}

要隱藏鍵盤,除了前一節介紹的self.view.endEditing(true)之外,也可以對元件使用resignFirstResponder()方法。

First Responder 代表的是目前畫面中,處於焦點狀態的元件,而當輸入文字時,這個輸入框就是 First Responder ,所以如果要隱藏鍵盤,當然就是將 First Responder 取消,也就是使用resignFirstResponder()方法。

Hint
  • 實際上,觸控事件是由 UIControl 所負責的動作。 UIControl 是繼承自 UIView 的子類別,而這些需要觸控事件的元件則是再繼承自 UIControl ,像是往後會學習到的 UIButton、UISwitch、UISlider 都是。

與 Objective-C 混合使用

Objective-C 是在 Swift 尚未推出前,主要用來撰寫 iOS 應用程式的語言。雖然我們現在改以 Swift 為主,但還是有一些工作必須經由 Objective-C 來實作完成,而需要的地方必須顯式地在前面加上 @objc 標示出來。

前面提到的三個按下動作事件後的 action ,應該可以發現方法的 func 關鍵字前加上了 @objc ,這就表示這個方法是需要交給 Objective-C 來處理的(函式、類別或擴展也都有可能需要標示)。

你可能會擔心什麼地方該加 @objc ,什麼地方不加。其實不用太糾結與此, Xcode 在大部分情況下都會提醒你是否漏寫了 @objc

範例

本節範例程式碼放在 uikit/uitextview

results matching ""

    No results matching ""