iosobjective-cgestureswipe-gesture

Swipe Gesture on UITableview Cell Like Whtsapp does for "Reply a Message"


How can we implement swipe gesture on tableview cell and move the tableview cell as the finger moves from left to right?

I am able to add the swipe gesture but moving the cell is something I want to implement.

Whatsapp has the same feature implemented while replying to a message and want to attain the same animation effect.

Any help will be appreciated.

Thanks


Solution

  • I have created a demo for this. You can use https://github.com/Dharmesh-shah2412/demoWhatsappSwipeToReply

    Objective C :

    I have added PanGesture to 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()
                }
            }
        }
    }