In my iOS app, I have an UITableView which contains a PKCanvaView in one of its cells (5th, for testing purposes).
The problem is that when the user 'drags' vertically (up or down), the tableView catches these touches, scrolls the table, and prevents the PKCanvasView from working correctly. I would like to stop the table from scrolling as long as the user is touching that particular subview.
If I use an Apple Pencil it works fine but it scrolls the table when I use my fingers. It works a bit better if I drag slowly. It would let me draw but if I try to draw a bit faster the tableview scrolls.
NOTE: This question is similar to this post Prevent UITableView from scrolling when custom subview is handling touches although the proposed solution doesn't seem to be working anymore or is not too clear into how to implement it.
import UIKit
import PencilKit
class ViewController: UITableViewController {
private let inkCanvasView: PKCanvasView = {
let canvasView = PKCanvasView(frame: .zero)
canvasView.translatesAutoresizingMaskIntoConstraints = false
canvasView.tool = PKInkingTool(.pen, color: .blue, width: 10)
canvasView.drawing = PKDrawing()
canvasView.backgroundColor = .red
canvasView.drawingPolicy = .anyInput
canvasView.contentMode = .scaleAspectFit
canvasView.becomeFirstResponder()
return canvasView
}()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delaysContentTouches = true
tableView.canCancelContentTouches = false
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {
preconditionFailure("Invalid cell")
}
if indexPath.row == 5 {
cell.contentView.addSubview(inkCanvasView)
inkCanvasView.topAnchor.constraint(equalTo: cell.contentView.topAnchor).isActive = true
inkCanvasView.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor).isActive = true
inkCanvasView.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor).isActive = true
inkCanvasView.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor).isActive = true
}
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 5 {
return 500
}
return 80
}
}