需求:在 UIView 中處理使用者觸控操作,實現按下高亮、滑動追蹤、抬起確認、取消重置等效果。核心是覆寫 UIResponder 的四大觸控事件方法。
四大核心方法
| 方法 | 觸發時機 | 典型用途 |
touchesBegan(_:with:) | 手指**剛接觸**螢幕 | 高亮按鈕、記錄起始座標、啟動計時器 |
touchesMoved(_:with:) | 手指**在螢幕上滑動**(高頻率重複呼叫) | 拖曳視圖、繪圖、滑動選單追蹤 |
touchesEnded(_:with:) | 手指**離開螢幕**(正常結束) | 確認點擊、提交表單、結束拖曳、觸發動作 |
touchesCancelled(_:with:) | 系統**中斷觸控**(來電、推播、多工切換、超出視圖範圍) | 重置高亮、取消進行中操作、清理暫態狀態 |
完整實作範例:自訂按鈕高亮效果
class CustomButton: UIView {
private var isHighlighted = false
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
isHighlighted = true
UIView.animate(withDuration: 0.1) {
self.alpha = 0.6 // 按下變暗
self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) // 微縮
}
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
// 判斷手指是否移出按鈕範圍
if let touch = touches.first {
let location = touch.location(in: self)
if !bounds.contains(location) {
// 移出範圍 → 取消高亮
resetHighlight()
}
}
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if isHighlighted {
// 觸發點擊動作
sendActions(for: .touchUpInside)
}
resetHighlight()
}
override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
resetHighlight()
}
private func resetHighlight() {
isHighlighted = false
UIView.animate(withDuration: 0.1) {
self.alpha = 1.0
self.transform = .identity
}
}
}
關鍵細節
- 多點觸控:
touches 是 Set,單點操作用 touches.first。
- 座標轉換:
touch.location(in: view) 取得相對於指定視圖的座標。
- 事件傳遞鏈:View → Superview → ... → Window → Application。若不處理,呼叫
super 向上傳遞。
- touchesCancelled 必須處理:否則高亮狀態殘留、操作邏輯未重置,造成使用者困惑。
現代替代:UIControl / UIGestureRecognizer