类似WhatsApp的“回复消息”功能,如何在UITableview单元格上实现滑动手势?

3

如何在表格视图单元格上实现滑动手势,并随着手指从左到右的移动移动表格视图单元格?

我已经能够添加滑动手势,但是移动单元格是我想要实现的内容。

Whatsapp 在回复消息时实现了相同的功能,希望获得相同的动画效果。

任何帮助都将不胜感激。

谢谢

2个回答

3

我已经为此创建了一个演示。您可以使用https://github.com/Dharmesh-shah2412/demoWhatsappSwipeToReply

Objective C:

我已将PanGesture添加到Tableviewcell中:

- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"Cell"];
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureCellAction:)];
    pan.delegate = self;
    [cell.contentView addGestureRecognizer:pan];
    return cell;
}

- (IBAction)panGestureCellAction:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    if (recognizer.view.frame.origin.x < 0) { return; }
    recognizer.view.center = CGPointMake(recognizer.view.center.x+ translation.x,
                                         recognizer.view.center.y );
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    if(recognizer.view.frame.origin.x > [UIScreen mainScreen].bounds.size.width * 0.9)
    {
        [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            [recognizer.view setFrame: CGRectMake(0, recognizer.view.frame.origin.y, recognizer.view.frame.size.width, recognizer.view.frame.size.height)];
        } completion:nil];
    }
    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        int x = recognizer.view.frame.origin.x;
        [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            [recognizer.view setFrame: CGRectMake(0, recognizer.view.frame.origin.y, recognizer.view.frame.size.width, recognizer.view.frame.size.height)];
        } completion:^(BOOL finished) {
            if (x > recognizer.view.frame.size.width / 2) {
                [_txtField becomeFirstResponder];
            }
        }];
    }
}
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
    CGPoint velocity = [panGestureRecognizer velocityInView:_tblView];
    if (velocity.x < 0) {
        return false;
    }
    return fabs(velocity.x) > fabs(velocity.y);
}

Swift:

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGestureCellAction))
    cell.contentView.addGestureRecognizer(panGestureRecognizer)
    return cell
}

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    let velocity : CGPoint = gestureRecognizer.location(in: tblView)
    if velocity.x < 0 {
        return false
    }
    return abs(Float(velocity.x)) > abs(Float(velocity.y))
}

@objc func panGestureCellAction(recognizer: UIPanGestureRecognizer)  {
    let translation = recognizer.translation(in: tblView)
    if recognizer.view?.frame.origin.x ?? 0 < 0 {
        return
    }
    recognizer.view?.center = CGPoint(
        x: (recognizer.view?.center.x ?? 0) + translation.x,
        y: (recognizer.view?.center.y ?? 0))
    recognizer.setTranslation(CGPoint(x: 0, y: 0), in: view)
    if (recognizer.view?.frame.origin.x ?? 0) > UIScreen.main.bounds.size.width * 0.9 {
        UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut, animations: {
            recognizer.view?.frame = CGRect(x: 0, y: recognizer.view?.frame.origin.y ?? 0, width: recognizer.view?.frame.size.width ?? 0, height: recognizer.view?.frame.size.height ?? 0)
        })
    }
    if recognizer.state == .ended {
        let x = recognizer.view?.frame.origin.x ?? 0
        UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut) {
            recognizer.view?.frame = CGRect(x: 0, y: recognizer.view?.frame.origin.y ?? 0, width: recognizer.view?.frame.size.width ?? 0, height: recognizer.view?.frame.size.height ?? 0)
        } completion: { (finished) in
            if x > ((recognizer.view?.frame.size.width ?? 0) / 2) {
                self.txtChat.becomeFirstResponder()
            }
        }
    }
}

1
@famfamfam 我已经添加了 Swift 代码,请验证。 - Dharmesh shah
1
这是一个有趣的解决方案。我只希望能在消息左侧添加回复图片。 - ekashking
@ekashking,你在消息左侧添加了回复图片吗? - Arjun
不,我没有继续实现这个功能。 - ekashking
问题在于,当他们回复一条消息时,他们希望访问消息数据,你如何处理这个问题? - Saeed Rahmatolahi
显示剩余2条评论

0

我使用Swift 5在Xcode 14.2上创建了滑动手势。

以下是我在UITableViewCell中执行滑动的代码...

//declare the `UISwipeGestureRecognizer` 
let swipeGesture = UISwipeGestureRecognizer()

//a call back to notify the swipe in `cellForRowAt` as follow.
var replyCallBack : ( () -> Void)?

//this view perform swiping in cell
@IBOutlet weak var containerView: UIView! 

 override func awakeFromNib() {
            super.awakeFromNib()
           
            //set up your UI 

            setSwipeGesture() //register gesture 
  }


func setSwipeGesture(){
        // Add the swipe gesture and set the direction to the right or left according to your needs 
        swipeGesture.direction = .right
        contentView.addGestureRecognizer(swipeGesture)
        
        // Add a target to the swipe gesture to handle the swipe
        swipeGesture.addTarget(self, action: #selector(handleSwipe(_:)))
 }


@objc func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
            // Animate the action view onto the screen when the user swipes right
            if gesture.direction == .right {
                UIView.animate(withDuration: 0.15) {
                    self.messageContainerView.transform = CGAffineTransform(translationX: self.contentView.frame.width / 2.5, y: 0)

                    // Schedule a timer to restore the cell after 0.2 seconds or change it according to your needs
                    Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { (_) in
                        UIView.animate(withDuration: 0.1) {
                            self.messageContainerView.transform = .identity

                            //callback to notify in cellForRowAt 
                            self.replyCallBack!()

                            //your code when 
                        }
                    }
                }
            } else {
                // Animate the action view off the screen when the user swipes left

            UIView.animate(withDuration: 0.3) {
                self.messageContainerView.transform = .identity
            }
        }
    }

你可以根据自己的需求更改动画时长,或者将 .right 动画更改为 .left 动画... 在这种情况下,我只进行了向右滑动操作...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接