Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView tap not working first time after constraints change

IMPORTANT: My problem is not that I'm implementing didDeelectRowAt instead of didSelectRowAt. Already checked that :)

I have a UITableView that is shown on part of the screen in a modally presented view controller. When the user is dragging it resizes to full screen and back to some defined min height. I'm doing this by implementing the following methods from the UIScrollViewDelegate:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard !scrollView.isDecelerating else { return }

    let contentOffset = scrollView.contentOffset.y
    if tableViewHeightConstraint.constant < view.frame.height && contentOffset > 0.0 {
        tableViewHeightConstraint.constant = min(contentOffset + tableViewHeightConstraint.constant, view.frame.height)
        scrollView.contentOffset.y = 0.0
        return
    }

    if tableViewHeightConstraint.constant > minViewHeight && contentOffset < 0.0 {
        tableViewHeightConstraint.constant = max(tableViewHeightConstraint.constant + contentOffset, minViewHeight)
        scrollView.contentOffset.y = 0.0
    }
}

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    // Here I have some calculations if depending the dragging end position and the velocity the end size should be full screen or `minViewHeight`
    // After calculating what the end size should be I'm animating the size change
    heightConstraint.constant = newConstraintHeight
    UIView.animate(withDuration: TimeInterval(calculatedAnimationDuration), delay: 0.0, options: .curveEaseOut, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)
}

Everything about the resizing and the scrolling works fine, but there is a problem that I cannot figure out why it's happening. It's the following:

  • When the view controller with the table view is shown for the first time with the min height and I tap on a cell it works fine.
  • If I drag to expand the table view to full screen height and tap on a cell, again it works fine.
  • If I drag to expand the table view to full screen height and then drag again to return it to the min height and then tap on a cell, nothing is happening, no UIScrollViewDelegate or UITableViewDelegate method is called at all. If I tap once more on a cell everything works fine.

One thing that I noticed is that after dragging the table view back to the min height the scroll indicator does not hide. On the first tap it hides, and on the second tap the didSelectRowAt is called.

UPDATE:

Here is a test repo for the problem: https://github.com/nikmin/DragTest

Please don't mind if the dragging doesn't work perfectly, I just put something so anyone can try it out, but I think the problem is easily reproducible.

Also one more thing... If you drag from full size all the way to the bottom so the table view reaches min height and you continue dragging so the content offset is < 0 and the you release, the problem is not happening.

like image 586
nikmin Avatar asked Nov 02 '17 19:11

nikmin


1 Answers

Drag TableView to return it to the min height and then tap on a cell, nothing is happening because:

  • When you drag to expand the table view to full screen, scrollView.isDecelerating is true. So the code inside scrollViewDidScroll method will run.

  • But when you drag TableView to return it to the min height, scrollViewDidScroll is false. So the code inside scrollViewDidScroll method won't run. It's make the first tap do nothing.

Simply remove guard !scrollView.isDecelerating else { return } from scrollViewDidScroll. You will tap cell normally after drag TableView down.

But you need change logic a little, animation will go wrong after remove above line.

Hope it can help you ;)

like image 117
trungduc Avatar answered Nov 15 '22 05:11

trungduc