【问题标题】:Swift : Pull down to dismiss `UITableViewController`Swift:下拉以关闭`UITableViewController`
【发布时间】:2016-02-22 07:43:48
【问题描述】:

我想下拉关闭UITableViewController,所以我使用了scrollViewDidScroll 方法,但它不起作用!

    class CommentViewController: PFQueryTableViewController {

        private let tableHeaderHeight: CGFloat = 350.0



extension CommentViewController
{
    override func scrollViewDidScroll(scrollView: UIScrollView)
    {



            // Pull down to dismiss TVC 
            let offsetY = scrollView.contentOffset.y
            let adjustment: CGFloat = 130.0

            // for later use
            if (-offsetY) > (tableHeaderHeight+adjustment) {
                self.dismissViewControllerAnimated(true, completion: nil)
                }
 }
    }

【问题讨论】:

  • 请检查您是否已将委托设置为您的表格视图。
  • tableview 已经有UIScrollViewDelegate 对吧?如果我添加它,它将导致错误冗余一致性 ... to protocol UIScrollViewDelegate
  • 我的意思是 tableView.delegate 设置为 self?
  • 我做了但还是不行

标签: ios xcode swift uitableview uiscrollview


【解决方案1】:

您必须实现额外的平移手势识别器,它将与 scrollView 的平移手势识别器同时识别。然后您可以确定当表格视图已经滚动到顶部时用户是否正在用手指进行平移。 例如

var isTrackingPanLocation = false
var panGestureRecognizer: UIPanGestureRecognizer!

public override func viewDidLoad() {
    super.viewDidLoad()
    tableView.bounces = false
    panGestureRecognizer = UIPanGestureRecognizer(target: self, 
                                                  action: #selector(panRecognized(gestureRecognizer:)))
    panGestureRecognizer.delegate = self
    tableView.addGestureRecognizer(panGestureRecognizer)
}

public func panRecognized(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .began && tableView.contentOffset.y == 0 {
        recognizer.setTranslation(CGPoint.zero, inView : tableView)

        isTrackingPanLocation = true
    } else if recognizer.state != .ended && 
              recognizer.state != .cancelled && 
              recognizer.state != .failed && 
              isTrackingPanLocation {
        let panOffset = recognizer.translationInView(tableView)

        // determine offset of the pan from the start here. 
        // When offset is far enough from table view top edge - 
        // dismiss your view controller. Additionally you can 
        // determine if pan goes in the wrong direction and 
        // then reset flag isTrackingPanLocation to false

        let eligiblePanOffset = panOffset.y > 200
        if eligiblePanOffset {
            recognizer.enabled = false
            recognizer.enabled = true
            dismissViewControllerAnimated(true, completion: nil)
        }

        if panOffset.y < 0 {
            isTrackingPanLocation = false
        }
    } else {
        isTrackingPanLocation = false
    }
}

public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWithGestureRecognizer 
                    otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

【讨论】:

  • 什么是合格的PanOffset?
  • 这是一个标志,当用户拉到顶部时为真。您必须根据 panOffset 和 0 - 表视图边界点来计算它。例如。让符合条件的PanOffset = (panOffset.y
  • 不知道你怎么举个例子
  • 滚动后崩溃panRecognized:]: unrecognized selector sent to instance 0x7fa29b02a770
  • 可能是因为它是私有的。设为公开。让我们开始聊天。
【解决方案2】:

斯威夫特 4

var panGestureRecognizer : UIPanGestureRecognizer!

override func viewDidLoad() {
    mainTableView.bounces = true
    panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panRecognized))
    panGestureRecognizer.delegate = self
    mainTableView.addGestureRecognizer(panGestureRecognizer)
}


@objc func panRecognized(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .began && mainTableView.contentOffset.y == 0 {

    } else if recognizer.state != .ended && recognizer.state != .cancelled && recognizer.state != .failed {
        let panOffset = recognizer.translation(in: mainTableView)
        let eligiblePanOffset = panOffset.y > 300
        if eligiblePanOffset {
            recognizer.isEnabled = false
            recognizer.isEnabled = true
            self.dismiss(animated: true, completion: nil)
        }
    }
}


func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

【讨论】:

  • 与 UIScrollView 几乎可以互换。这个解决方案比我见过的其他解决方案简单得多。
  • 是的,可以和 UIScrollView 同时使用 :) 谢谢
  • 最干净的解决方案在这里。开箱即用。
【解决方案3】:

为什么不将 print(offsetY) 放在 scrollViewDidScroll 中。我怀疑(-offsetY) &gt; (tableHeaderHeight+adjustment) 永远不会满足,因为橡皮筋会导致tableview 在关闭视图控制器之前反弹

【讨论】:

  • 所以我应该删除它?你有什么建议?
  • 将 print(-offsetY) 放在 if 语句之前的 scrollViewDidScroll 中。构建并运行您的应用程序,下拉您的 tableview,查看控制台中的值。它们是否曾经超过 480.0?
  • 346.666666666667 这是结果
  • 所以你需要重新考虑(-offsetY) > (tableHeaderHeight+adjustment) try (-offsetY)> 340.0
【解决方案4】:

对于 2019 年关注此问题的人们——更现代的方法是使用 UIGestureRecognizerDelegate 方法,而不是在视图控制器中保留额外的状态。例如:

private weak var panFromTop: UIPanGestureRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()

    // Add pan gesture recognizer
    let panFromTop = UIPanGestureRecognizer(target: self, action: #selector(handlePanFromTop(_:)))
    panFromTop.delegate = self
    tableView.addGestureRecognizer(panFromTop)
    self.panFromTop = panFromTop
}

@objc func handlePanFromTop(_ recognizer: UIPanGestureRecognizer) {
    switch recognizer.state {
    case .began:
        // TODO: BEGIN YOUR ANIMATION HERE
    case .changed:
        // TODO: UPDATE YOUR ANIMATION HERE
    default:
        let translation = recognizer.translation(in: view)
        let velocity = recognizer.velocity(in: view)
        if ((translation.y + velocity.y) / view.bounds.height) > 0.5 {
            // TODO: FINISH YOUR ANIMATION HERE
        } else {
            // TODO: CANCEL YOUR ANIMATION HERE
        }
    }
}

仅在表格视图顶部禁用反弹:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.y < 0 {
        scrollView.setContentOffset(.zero, animated: false)
    }
}

然后实现手势识别器委托方法:

func gestureRecognizer(
    _ gestureRecognizer: UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
    return true
}

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    guard let recognizer = gestureRecognizer as? UIPanGestureRecognizer,
        recognizer === panFromTop else {
        // Only require special conditions for the panFromTop gesture recognizer
        return true
    }

    // Require the scroll view to be at the top,
    // and require the pan to start by dragging downward
    return (
        tableView.contentOffset.y <= 0 &&
        recognizer.velocity(in: view).y > 0
    )
}

【讨论】:

  • 如果要向上滚动,需要先向下拖动一点再向上拖动。
  • 很好的答案,谢谢!为了改进它,不要实现scrollViewDidScroll,而是在handlePanFromTop中添加scrollView.isScrollEnabled = falsecase .begantruedefault
猜你喜欢
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 2015-11-12
  • 2013-07-11
  • 1970-01-01
  • 2020-10-08
  • 1970-01-01
  • 2014-09-10
相关资源
最近更新 更多