https://github.com/dmytro-anokhin/advanced-scrollview
Build advanced interactions with UIScrollView and NSScrollView in SwiftUI
https://github.com/dmytro-anokhin/advanced-scrollview
appkit swift swiftui uikit
Last synced: about 2 months ago
JSON representation
Build advanced interactions with UIScrollView and NSScrollView in SwiftUI
- Host: GitHub
- URL: https://github.com/dmytro-anokhin/advanced-scrollview
- Owner: dmytro-anokhin
- License: mit
- Created: 2021-06-23T16:53:36.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2021-08-02T22:22:29.000Z (almost 4 years ago)
- Last Synced: 2025-03-26T21:45:54.544Z (2 months ago)
- Topics: appkit, swift, swiftui, uikit
- Language: Swift
- Homepage:
- Size: 105 KB
- Stars: 69
- Watchers: 2
- Forks: 9
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Advanced ScrollView
Advanced ScrollView creates a bridge between `UIScrollView` and `NSScrollView` and SwiftUI views.
What makes this scroll view "advanced"? You have full access to `UIScrollView` and `NSScrollView` APIs. It is harder to use, but you can build all kinds of interactions, like pinch to zoom at precise point, scroll with a given offset, infinite canvas, etc.
```swift
import SwiftUI
import AdvancedScrollViewstruct ScrollableImage: View {
let image: Image
var body: some View {
AdvancedScrollView { _ in
image
}
}
}
```See the showcase app for some ideas: [ShapeEdit](https://github.com/dmytro-anokhin/ShapeEdit).
## Magnification
You can configure magnification behaviour using `Magnification` struct.
```swift
let magnification = Magnification(range: 1.0...4.0, initialValue: 1.0, isRelative: true)AdvancedScrollView(magnification: magnification) { _ in
image
}
````range` and `initialValue` allows to configure magnification range and initial magnification respectfully. `isRelative` defines if magnification must be calculated relative to the view's frame. I.e. content magnified to fit in the view.
## Proxy
Similarly to `ScrollView` and `ScrollViewReader` combination, `AdvancedScrollView` takes `ViewBuilder` closure with a single `AdvancedScrollViewProxy` argument that provides access to common properties and methods of the underlying scroll view.
The names are self-explanatory and while this documentation is in development please refer to `UIScrollView`/`NSScrollView` APIs.
```
func scrollTo(_ rect: CGRect, animated: Bool)var contentOffset: CGPoint { get set }
var contentSize: CGSize { get }
var contentInset: EdgeInsets { get set }
var visibleRect: CGRect { get }
var scrollerInsets: EdgeInsets { get }
var magnification: CGFloat { get }
var isLiveMagnify: Bool { get }
```## Events and Gestures
`AdvancedScrollView` won't alter event handling so in most cases you can expect SwiftUI gestures to work as is. But, underlying `NSScrollView`, when magnified, won't correctly translate points from its coordinate system to SwiftUI views. Good news is that `UIScrollView` correctly translates coordinates.
As a solution to this problem `AdvancedScrollView` provides `onTapContentGesture` and `onDragContentGesture` gestures. This replicates `onTap` and `onDrag` view modifiers.
Downside is that this are event handlers are attached to the scroll view itself, so you need to determine which subview should handle an event.
Benefit is that `onDragContentGesture` will manage state for you and even autoscroll content when needed.
If you're building iOS only app, not using magnification, or do not need to handle gestures at a specific location, using SwiftUI gestures with `AdvancedScrollView` should cover your case.
*If you happen to know how to make `NSScrollView` translate coordinates correctly, please reach out.*