5

I am in the process of enabling Catalyst support for a freelancing project — one of the things that I noticed right away is the differing behaviour of scrolling views on MacOS vs iOS. I expected to be able to click and drag UIScrollViews or UITableViews as I would normally in the iOS Simulator, but I am only able to scroll these views using the mouse's scroll wheel (or two finger gesture on a trackpad).

Is there any way I can mimic the UIPanGestureRecognizer behaviour on iOS for a UIScrollView or UITableView using a Click + Drag gesture on MacOS?

Thank you :)

chmod
  • 1,173
  • 1
  • 9
  • 17
  • relevant: https://stackoverflow.com/questions/72355895/how-to-set-setsupportspointerdragscrolling-on-a-tableview-in-swift – Fattie May 24 '22 at 08:55

4 Answers4

3

If Private API is acceptable, there is a new one in Mac Catalyst 14.0 does exactly this:

- [UIScrollView _setSupportsPointerDragScrolling:]
naituw
  • 1,087
  • 10
  • 14
1

I noted the same for UICollectionViews. I decided to use scroll buttons and have them set the selection, and offsets. You can do the same with UIGestureRecognizers in each cell and then set the offsets, etc of the parent UITableView or UICollectionView. I've not thought about simple UIScrollViews.

polymerchm
  • 188
  • 1
  • 7
1

The following will do the trick:

First a convenience extension:

public extension CGPoint {
    static func - (a: CGPoint, b: CGPoint) -> CGPoint {
        return CGPoint(x: a.x-b.x, y: a.y-b.y)
    }
}

Add a pan gesture to the scroll view:

scrollView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))))

And finally the selector:

private var s0: CGPoint = .zero
@objc func onPan(_ gesture: UIPanGestureRecognizer) {
    let ds: CGPoint = gesture.translation(in: scrollView)
    switch gesture.state {
        case .began:
            s0 = scrollView.contentOffset
        case .changed:
            scrollView.contentOffset = CGPoint(x: 0, y: max(0, min(scrollView.contentSize.height-scrollView.height, (s0-ds).y)))
        default: break
    }
}

(Full set of CGPoint convenience methods included here: https://github.com/aepryus/Acheron)

aepryus
  • 4,715
  • 5
  • 28
  • 41
  • Note that unfortunately if you add a simple pan it doesn't really work - you can move the table to any unrealistic position above/below the usual maximums, and there's no throw anyway. – Fattie May 24 '22 at 09:05
  • @Fattie I could have sworn my own app worked ok, which it did, but when looking at the code I noticed I had added constraints manually. I've added the constraints above. But, you are right, there is no inertial component using this method. – aepryus May 24 '22 at 11:08
0

It's worth noting that, as of Monterey, if you use two finger gesture on trackpad, then, it does work exactly as if scrolling on a device - including the bounce.

Fattie
  • 27,874
  • 70
  • 431
  • 719