xcode Swift:下拉以关闭`UITableViewController`

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33816200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 08:14:02  来源:igfitidea点击:

Swift : Pull down to dismiss `UITableViewController`

iosxcodeswiftuitableviewuiscrollview

提问by marrioa

I want to pull down to dismiss UITableViewControllerso I used scrollViewDidScrollmethod but it didn't works!

我想下拉解散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)
                }
 }
    }

回答by Eugene Dudnyk

You have to implement additional pan gesture recognizer which will recognize simultaneously with scrollView's pan gesture recognizer. Then you can determine whether user is panning by his finger when table view is already scrolled to the top. e.g.

您必须实现额外的平移手势识别器,它将与 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
}

回答by Varun

Swift 4

斯威夫特 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
}

回答by beyowulf

Why don't you place print(offsetY) in scrollViewDidScroll. I suspect that (-offsetY) > (tableHeaderHeight+adjustment)will never be satisfied because of the rubber banding will cause the tableview to rebound before it can dismiss the view controller

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

回答by Chris Chute

For people looking at this in 2019 -- A more modern approach would use the UIGestureRecognizerDelegatemethods, instead of keeping extra state in your view controller. For example:

对于在 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
        }
    }
}

Disable bounce at the top of the table view only:

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

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

Then implement the gesture recognizer delegate methods:

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

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
    )
}