0

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
    }
    
}
rudymatos
  • 301
  • 1
  • 3
  • 9

0 Answers0