SwiftUI: Scroll like in UIKit using only SwiftUI _hidden APIs

Eugene Dudnyk
Nerd For Tech
Published in
2 min readOct 20, 2021

Imagine you could configure the SwiftUI ScrollView

Nostalgia on UIScrollView and Interface builder (or maybe not).

Imagine you could do pagination without introspection.

Imagine you could manipulate with

  • content offset (programmatically scroll with animation to the defined offset)
  • content insets
  • indicator insets
  • deceleration rate
  • bouncing options
  • enabling or disabling of scrolling
  • interactive drag allowance

in other words, most of the configurable properties of UIScrollView in UIKit, but with pure SwiftUI.

SwiftUI actually allows all these options to be configured, but in order to learn about it one would have to find out the hidden public SwiftUI types in the .swiftinterface of SwiftUI.

Previously I wrote about another discovery of the hidden types in SwiftUI — the _ViewTest protocol.

This time, I prepared a special library SolidScroll which liberates _ScrollView and _PagingView of SwiftUI. It contains only type aliases to the hidden SwiftUI types, a couple of initializers for the convenience, and documentation in DocC.

Let’s learn more about this SwiftUI treasure.

_ScrollView

The hidden _ScrollView type represents the scroll view that is configured with _ScrollViewConfig and _ScrollableContentProvider.

public init<Provider>(contentProvider: Provider, config: _ScrollViewConfig = _ScrollViewConfig()) where Provider : _ScrollableContentProvider

In SolidScroll library, the corresponding type aliases which make these types visible, are:

  • SolidScrollView (alias for _ScrollView)
  • ScrollViewConfig (alias for _ScrollViewConfig)
  • AligningContentProvider (alias for _AligningContentProvider)
  • ContainedScrollViewKey (preference key, alias for _ContainedScrollViewKey)
  • SolidScrollViewProxy (alias for _ScrollViewProxy)

The way of handling the SolidScrollView is very similar to a regular ScrollViewReader which you are probably already familiar with (or, in case if you’ve never heard of it, I recommend this story for reading), but instead of creating the reader, we are listening to the preference change of the ContainedScrollViewKey preference.

The example of SolidScrollView usage.

Once we’ve got the preference’s value, and we have the scroll view proxy, we can call setContentOfsset(_:animated:completion:) on it in order to scroll programmatically (with or without animation) to the concrete position in the scrollable content.

Also, now we have access to the properties and methods of the underlying scroll view:

The public interface of the hidden _ScrollViewProxy type in SwiftUI

_PagingView

The hidden _PagingView type represents the scroll view with preconfigured paging. The configuration for the paging is provided via _PagingViewConfig.

In SolidScroll library, the corresponding type aliases which make these types visible, are:

  • PagingView (alias for _PagingView)
  • PagingViewConfig (alias for _PagingViewConfig)

The approach to handle PagingView is very simple — just provide your paging view config and the collection of views which will be the pages of the PagingView.

The example of PagingView usage.

The possible limitation which I see here is that both PagingViewConfig and ScrollViewConfig only allow for all pages of the same size. If you need to have the pages of different size, you’ll have to get a bit creative.

I’ve recorded a small demo video for the SolidScroll library, check it out:

Thanks for reading!

--

--

Eugene Dudnyk
Nerd For Tech

iOS / Fullstack Design System Developer with more than 10 years of iOS development experience.