Меня очень интересует этот вопрос, и я надеюсь, что, предоставив, как я его реализовал, он не подавит ответ, который может показать, как правильно обойти респондента.Уловка, которую я думаю, что я помещаю в комментарии, отслеживает прикосновения.Я забыл о том, как scrollview поглощает их, но вы можете использовать UIPanGesture.Посмотрите, близко ли это к тому, что вы ищете.Единственный случай, с которым я столкнулся, может потребовать больше размышлений - использовать свиток, чтобы отклонить вид снизу.Большая часть этого кода настроена для получения рабочего вида прокрутки в представлении.Я думаю, что лучше всего использовать анимацию свойств, чтобы сделать ее прерываемой, или даже мою любимую анимацию в Facebook Pop.Для простоты я использовал анимацию UIView.Дайте мне знать, если это решит то, что вы ищете. Код ниже и вот результат .Вид прокрутки остается прокручиваемым и активным.Я анимирую кадры, но ограничения на обновление также могут работать.
import UIKit
class ViewController: UIViewController{
//setup
var items : [Int] = []
lazy var tableView : UITableView = {
let tv = UITableView(frame: CGRect(x: 0, y: topViewHeight, width: self.view.frame.width, height: self.view.frame.height))
tv.autoresizingMask = [.flexibleWidth,.flexibleHeight]
tv.delegate = self
tv.dataSource = self
tv.layer.cornerRadius = 4
return tv
}()
lazy var topView : UIView = {
let v = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: topViewHeight))
v.backgroundColor = .green
v.autoresizingMask = [.flexibleWidth,.flexibleHeight]
return v
}()
let cellIdentifier = "ourCell"
//for animation
var isAnimating = false
var lastOffset : CGPoint = .zero
var startingTouch : CGPoint?
let topViewHeight : CGFloat = 500
var isShowing : Bool = false
let maxCollapse : CGFloat = 50
override func viewDidLoad() {
super.viewDidLoad()
for x in 0...100{
items.append(x)
}
// Do any additional setup after loading the view, typically from a nib.
self.view.addSubview(topView)
self.view.addSubview(tableView)
self.tableView.reloadData()
let pan = UIPanGestureRecognizer(target: self, action: #selector(moveFunction(pan:)))
pan.delegate = self
self.view.addGestureRecognizer(pan)
}
@objc func moveFunction(pan:UIPanGestureRecognizer) {
let point:CGPoint = pan.location(in: self.view)
switch pan.state {
case .began:
startingTouch = point
break
case .changed:
processMove(touchPoint:point.y)
break
default:
processEnding(currentPointY: point.y)
break
}
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell : UITableViewCell!
cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)
}
cell.textLabel?.text = "\(items[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 30
}
}
extension ViewController : UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if isAnimating == true{
scrollView.contentOffset = lastOffset
return
}
lastOffset = scrollView.contentOffset
}
}
extension ViewController : UIGestureRecognizerDelegate{
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
extension ViewController{
func processMove(touchPoint:CGFloat){
if let start = startingTouch{
if touchPoint <= topViewHeight && start.y > topViewHeight{
isAnimating = true
tableView.frame = CGRect(x: 0, y:touchPoint, width: self.view.frame.width, height: self.view.frame.height)
return
}else if touchPoint >= self.maxCollapse && isShowing == true && start.y < self.maxCollapse{
isAnimating = true
tableView.frame = CGRect(x: 0, y:touchPoint, width: self.view.frame.width, height: self.view.frame.height)
return
}else if isShowing == true && self.tableView.contentOffset.y <= 0{
//this is the only one i am slightly unsure about
isAnimating = true
tableView.frame = CGRect(x: 0, y:touchPoint, width: self.view.frame.width, height: self.view.frame.height)
return
}
}
self.isAnimating = false
}
func processEnding(currentPointY:CGFloat){
startingTouch = nil
if isAnimating{
if currentPointY < topViewHeight/2{
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: .curveEaseInOut, animations: {
self.tableView.frame = CGRect(x: 0, y:self.maxCollapse, width: self.view.frame.width, height: self.view.frame.height)
}) { (finished) in
self.isShowing = true
}
}else{
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: .curveEaseInOut, animations: {
self.tableView.frame = CGRect(x: 0, y:self.topViewHeight, width: self.view.frame.width, height: self.view.frame.height)
}) { (finished) in
self.isShowing = false
}
}
}
self.isAnimating = false
}
}