iOS - UITestureRecognizer在UITableViewCell中类似于Snapchat

时间:2015-04-02 06:06:50

标签: ios uitableview uipangesturerecognizer tableviewcell

我正在尝试在我的练习应用程序中实现非常类似于Snapchat的功能,在那里你向右或向左拖动UITableViewCell,当你拖动时,视图后面的图像是慢慢的出现直到它到达某一点,并且在它之后,它会启动一个segue或PageViewController类型segue到另一个视图控制器,您可以用它与您的朋友聊天。

首先,我尝试使用屏幕边缘平移手势识别器,但这仅在您开始从屏幕边缘滑动时才有效。我需要能够在UITableViewCell内的任何地方滑动。

我所需要的功能的演示在Snapchat中,当你在朋友的一个表格单元格上慢慢地向右滑动时,你可以更清楚地看到它,它会慢慢显示一个消息图标的图像,并最终导致另一个视图,你可以聊天。

那么平移手势识别器就足够了吗?如果是这样,那么完成这项工作的最佳方法是什么?我已经看过关于平移手势识别器的教程,但是我看不到它在滑动一定距离后最终会如何导致另一个视图控制器。我想我可以放弃将消息图标放在显示的表格单元格内容后面,这些内容可以在向右滑动时显示,但我怎样才能实现这种流畅的功能呢?

学习这将真正增加我在流畅的用户体验方面的经验。任何建议或方法将不胜感激,谢谢。

编辑:请在目标C中留下答案。我不知道斯威夫特。

1 个答案:

答案 0 :(得分:2)

您可以为此创建自定义TableViewCell。下面的代码应该按照您的要求进行。只需将代理人添加到ViewController

即可
protocol TableViewCellDelegate {
    func something()
}

class TableViewCell: UITableViewCell {

    var startSegue = false
    var label: UILabel                      // Or UIView, whatever you want to show
    var delegate: TableViewCellDelegate?    // Delegate to your ViewController to perform the segue

    required init(coder aDecoder: NSCoder) {
        fatalError("NSCoding not supported")
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

        // Utility method for creating the label / view
        func createLabel() -> UILabel {
            let label = UILabel(frame: CGRect.nullRect)

            // Add label customization here

            return label
        }

        // Create "check" & "cross" labels for context cues
        label = createLabel()        // Create the label
        label.text = "\u{2713}"      // Add check symbol as text

        super.init(style: style, reuseIdentifier: reuseIdentifier)

        addSubview(label)

        // Add a pan recognizer
        var recognizer = UIPanGestureRecognizer(target: self, action: "handleSwipe:")
        recognizer.delegate = self
        addGestureRecognizer(recognizer)
    }

    let cueMargin: CGFloat = 10.0, cueWidth: CGFloat = 50.0

    override func layoutSubviews() {

        // The label starts out of view
        label.frame = CGRect(x: bounds.size.width + cueMargin, y: 0, width: cueWidth, height: bounds.size.height)
    }

    func handleSwipe(recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translationInView(self)

        if recognizer.state == .Changed {
            center = CGPointMake(center.x + translation.x, center.y)
            startSegue = frame.origin.x < -frame.size.width / 2.0                       // If swiped over 50%, return true
            label.textColor = startSegue ? UIColor.redColor() : UIColor.whiteColor()    // If swiped over 50%, become red
            recognizer.setTranslation(CGPointZero, inView: self)
        }
        if recognizer.state == .Ended {
            let originalFrame = CGRect(x: 0, y: frame.origin.y, width: bounds.size.width, height: bounds.size.height)
            if delegate != nil {
                startSegue ? delegate!.something() : UIView.animateWithDuration(0.2) { self.frame = originalFrame }
            }
        }
    }

    // Need this to handle the conflict between vertical swipes of tableviewgesture and pangesture
    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
        if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
            let velocity = panGestureRecognizer.velocityInView(superview!)
            if fabs(velocity.x) >= fabs(velocity.y) { return true }
            return false
        }
        return false
    }
}

我从这个tutorial

得到了这个

编辑: 在ViewController中,您必须使用以下命令“注册”此TableViewCell:

yourTableName.registerClass(TableViewCell.self, forCellReuseIdentifier: "cellIdentifier")

TableViewDataSource cellForRowAtIndexPath看起来像是:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier", forIndexPath: indexPath) as TableViewCell

        cell.delegate = self

        // Add stuff for your other labels like:
        // "cell.name = item.name" etc        

       return cell
    }

如果您想将数据传回ViewController,只需使用委托。