Swift28/90Days - 基於手勢的TODO應用 2

Swift90Days - 基於手勢的 TODO 應用 2

接着上面的文章看看這個 TODO 應用的代碼,接下來看下 TableViewCell 類。git

TableViewCell

TableViewCellDelegate

在 Cell 裏首先是定義了一個委託,用來對 Cell 進行操做:github

protocol TableViewCellDelegate {
    func toDoItemDeleted(todoItem: ToDoItem)
    func cellDidBeginEditing(editingCell: TableViewCell)
    func cellDidEndEditing(editingCell: TableViewCell)
}

todoItem

Cell 的數據來源是這個 todoItem 對象。定義以下:swift

var toDoItem: ToDoItem? {
    didSet {
        label.text = toDoItem!.text
        label.strikeThrough = toDoItem!.completed
        itemCompleteLayer.hidden = !label.strikeThrough
    }
}

能夠看到這個屬性在 didSet 以後會刷新 UI。app

init

注意在 init 中有這麼幾個點:ide

內部方法

由於右側的打鉤按鈕和左側的打叉按鈕除了內容不一樣,基本的形式 (背景顏色、字體、文字顏色) 是同樣的,而除了當前方法又不會有其餘方法調用這個生產 UILabel 的方法,因此定義了一個內部方法生產 UILabel :字體

func createCueLabel() -> UILabel {
    let label = UILabel(frame: CGRect.nullRect)
    label.textColor = UIColor.whiteColor()
    label.font = UIFont.boldSystemFontOfSize(32.0)
    label.backgroundColor = UIColor.clearColor()
    return label
}

按鈕高亮

高亮效果並非用切圖實現的,而是經過代碼設置色值和色值所在的位置實現的。每一個 Cell 的高亮效果是這樣寫的:code

gradientLayer.frame = bounds
let color1 = UIColor(white: 1.0, alpha: 0.2).CGColor as CGColorRef
let color2 = UIColor(white: 1.0, alpha: 0.1).CGColor as CGColorRef
let color3 = UIColor.clearColor().CGColor as CGColorRef
let color4 = UIColor(white: 0.0, alpha: 0.1).CGColor as CGColorRef
gradientLayer.colors = [color1, color2, color3, color4]
gradientLayer.locations = [0.0, 0.01, 0.95, 1.0]
layer.insertSublayer(gradientLayer, atIndex: 0)

若是搞不懂這些代碼的做用,改爲這樣再運行就能夠理解了:對象

// gradient layer for cell
gradientLayer.frame = bounds
let color1 = UIColor(white: 1.0, alpha: 1.0).CGColor as CGColorRef
let color2 = UIColor(white: 1.0, alpha: 0.0).CGColor as CGColorRef
gradientLayer.colors = [color1, color2]
gradientLayer.locations = [0.0, 1.0]
layer.insertSublayer(gradientLayer, atIndex: 0)

完成效果

當一個 item 完成的時候,會把它的顏色設置爲綠色標記爲已經完成。這個綠色也是經過 CALayer 實現的,一開始初始化的時候設置爲隱藏:get

// add a layer that renders a green background when an item is complete
itemCompleteLayer = CALayer(layer: layer)
itemCompleteLayer.backgroundColor = UIColor(red: 0.0, green: 0.6, blue: 0.0, alpha: 1.0).CGColor
itemCompleteLayer.hidden = true
layer.insertSublayer(itemCompleteLayer, atIndex: 0)

手勢

手勢應該算是這個應用的一個亮點,在 init 裏面定義了手勢的識別:animation

var recognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
recognizer.delegate = self
addGestureRecognizer(recognizer)

首先先經過委託判斷是否應該識別這個手勢:

override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
        let translation = panGestureRecognizer.translationInView(superview!)
        if fabs(translation.x) > fabs(translation.y) {
            return true
        }
        return false
    }
    return false
}

能夠看到是 X 偏移量大於 Y 的偏移量便可繼續識別。

而後看下具體的識別過程:

//MARK: - 橫向手勢識別
func handlePan(recognizer: UIPanGestureRecognizer) {
    // 1
    if recognizer.state == .Began {
        // 剛開始的時候,記錄手勢的位置
        originalCenter = center
    }
    // 2
    if recognizer.state == .Changed {
        let translation = recognizer.translationInView(self)
        center = CGPointMake(originalCenter.x + translation.x, originalCenter.y)
        // 判斷是否達到屏幕的一半,從而選擇是否觸發
        deleteOnDragRelease = frame.origin.x < -frame.size.width / 2.0
        completeOnDragRelease = frame.origin.x > frame.size.width / 2.0
        // 隱藏左右標記
        let cueAlpha = fabs(frame.origin.x) / (frame.size.width / 2.0)
        tickLabel.alpha = cueAlpha
        crossLabel.alpha = cueAlpha
        // 根據判斷結果刷新界面
        tickLabel.textColor = completeOnDragRelease ? UIColor.greenColor() : UIColor.whiteColor()
        crossLabel.textColor = deleteOnDragRelease ? UIColor.redColor() : UIColor.whiteColor()
    }
    // 3
    if recognizer.state == .Ended {
        let originalFrame = CGRect(x: 0, y: frame.origin.y,
            width: bounds.size.width, height: bounds.size.height)
        if deleteOnDragRelease {
            if delegate != nil && toDoItem != nil {
                // 通知委託刪除
                delegate!.toDoItemDeleted(toDoItem!)
            }
        } else if completeOnDragRelease {
            if toDoItem != nil {
                toDoItem!.completed = true
            }
            label.strikeThrough = true
            itemCompleteLayer.hidden = false
            UIView.animateWithDuration(0.2, animations: {self.frame = originalFrame})
        } else {
            UIView.animateWithDuration(0.2, animations: {self.frame = originalFrame})
        }
    }
}

References

相關文章
相關標籤/搜索