约束更改后,UITableView点击不首次工作

时间:2017-11-02 19:31:55

标签: ios swift uitableview uiscrollview uiscrollviewdelegate

重要提示:我的问题不是我正在实施 didDeelectRowAt 而不是 didSelectRowAt 。已经检查过:)

我有一个UITableView,它显示在模块呈现的视图控制器的屏幕的一部分上。当用户拖动时,它会调整到全屏并返回到某个定义的最小高度。我是通过从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)
}

关于调整大小和滚动的一切都很好,但有一个问题,我无法弄清楚它为什么会发生。它是以下内容:

  • 当第一次以最小高度显示具有表格视图的视图控制器时,我点击一个单元格,它可以正常工作。
  • 如果我拖动将表格视图展开到全屏高度并点击一个单元格,那么它再次正常工作。
  • 如果我拖动以将表格视图展开到全屏高度,然后再次拖动以将其返回到最小高度,然后点按单元格,则不会发生任何事情,不会UIScrollViewDelegateUITableViewDelegate方法被召唤了。如果我再次点击一个单元格,一切正常。

我注意到的一件事是,在将表格视图拖回最小高度后,滚动指示器不会隐藏。在第一次点击时它会隐藏,在第二次点击时会调用didSelectRowAt

更新:

以下是问题的测试回购:https://github.com/nikmin/DragTest

请不要介意拖动操作是否完美,我只是放了一些东西,所以任何人都可以尝试一下,但我认为问题很容易重现。

还有一件事......如果你从完整尺寸一直拖到底部,那么桌面视图达到最小高度,你继续拖动,所以内容偏移量是&lt; 0,你释放,问题没有发生。

3 个答案:

答案 0 :(得分:3)

拖动TableView将其返回到最小高度,然后点按一个单元格,没有任何事情发生,因为:

  • 当您拖动以将表格视图展开为全屏时,scrollView.isDeceleratingtrue。因此scrollViewDidScroll方法中的代码将运行。

  • 但是,当您拖动TableView将其返回到最小高度时,scrollViewDidScrollfalse。因此scrollViewDidScroll方法中的代码将无法运行。这是第一次点击什么都没做。

只需从guard !scrollView.isDecelerating else { return }移除scrollViewDidScroll即可。拖动TableView后,您将正常点击单元格。

但是你需要稍微改变逻辑,移除上面的行后动画就会出错。

希望它可以帮到你;)

答案 1 :(得分:1)

在尝试找出没有结果的解决方案之后,我们(我和UX设计师)决定稍微改变行为。

因此,在应用程序的实际场景中我实现了这一点,表视图位于另一个视图中,该视图还具有标题标签和表视图上方的一些其他视图。我们决定在此根视图中添加一个平移手势识别器,并在视图具有最小尺寸时禁用滚动表视图。这样,无论何时用户尝试拖动视图内的任何位置(包括表视图),平移手势识别器都将接管,因此视图的扩展起作用。细胞中的水龙头仍然有效。

当视图具有最大高度时,表视图滚动被启用,因此用户可以滚动。这种方法的缺点是,当用户滚动到表视图的顶部并继续滚动视图时,不会减小大小。但他仍然可以通过拖动表格视图上方的任何视图来拖动它。以这种方式向下拖动时,只有表格视图的大小发生变化,而内容偏移量不是问题的根源(同时更改两者)。

答案 2 :(得分:0)

看起来错误设置了内容偏移量。第一次触摸取消错误的位置(取消滚动),这就是它未注册的原因。如果我们可以访问完整的代码来检查它可能会更好,因为我无法告诉您问题究竟在哪里,但我想这是在方法scrollViewDidScroll中。