iOS - UITableViewCell 中的 UIGestureRecognizer 类似于 Snapchat

Posted

技术标签:

【中文标题】iOS - UITableViewCell 中的 UIGestureRecognizer 类似于 Snapchat【英文标题】:iOS - UIGestureRecognizer In UITableViewCell Similar To Snapchat 【发布时间】:2015-04-02 06:06:50 【问题描述】:

我正在尝试在我的练习应用中实现与 Snapchat 非常相似的功能,在其中您将 UITableViewCell 拖动到右侧或左侧,并且当您拖动时,视图后面的图像会慢慢出现,直到它达到了某个点,然后,它开始一个 segue 或 PageViewController 类型 segue 到另一个视图控制器,您可以使用它与您的朋友聊天。

起初,我尝试使用屏幕边缘平移手势识别器,但只有从屏幕边缘开始滑动时才有效。我需要能够从UITableViewCell 中的任何位置滑动。

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

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

了解这一点确实会增加我在流畅用户体验方面的体验。任何建议或方法将不胜感激,谢谢。

编辑:请在 Objective C 中留下答案。我不认识斯威夫特。

【问题讨论】:

【参考方案1】:

您可以为此创建一个自定义 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 = "\u2713"      // 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,只需使用委托即可。

【讨论】:

谢谢,但我不知道 Swift。有没有办法在Objective-C中得到这个?如果没有,我将尝试阅读此代码并通过将其转换为 Objective C 来进行尝试。我会尽快回复您。再次感谢。 另外,如果您希望它看起来平滑,您可以使用 UIView(或标签)的 alpha 值,并根据滑动使其从 0 -> 1 变为。抱歉,我对 Objective-C 了解不多。我所知道的是,它使用方括号 [] 代替 Swift 中的点表示法。 我让平移手势工作了一点......但这还没有成功。有没有办法制作一个 Swift 文件,把这段代码放在那里,并让它与我的其他 Objective-C 文件共存? 我将此问题标记为正确,因为它确实给了我想要的东西。但我无法使其与我的目标 C 代码兼容。非常感谢您,很抱歉花了这么长时间才将其标记为正确。 np,与您的 obj-c 代码混合有什么问题?您也可以使用自动布局来做到这一点,也许这样会更容易?

以上是关于iOS - UITableViewCell 中的 UIGestureRecognizer 类似于 Snapchat的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 无法访问 UITableViewCell 类中的 UITextView 委托

UITableViewCell 中的 ios 滑块操作

iOS - 圆圈中的图像(UITableViewCell)

iOS 8 中的 UITableViewCell 约束在 iOS7 中不起作用

iOS - UITableViewCell 中的 UIGestureRecognizer 类似于 Snapchat

iOS + Swift 2:UITableViewCell 中的动态高度不适用于空视图