Native Scrolling in Ionic: A Tale in Rhyme
“Scrolling’s complicated,” he stated. “The reasons to avoid JS scrolling have faded.” So JS scrolling was enabled, and the features it allowed were fabled. It appeared JS scrolling was underrated.
As iOS and Android matured, native scrolling events were assured. “The time has come,” the Web Wizard said, “for native scrolling now to spread. A new functionality must be procured.”
Pull to Refresh; List Reordering; Infinite Scroll: All were configured to meet this goal. Even the $ionicScrollDelegate was carefully made to relegate itself to optional native scroll view control.
Once these changes were complete, there appeared a problem with collection-repeat. After conducting an investigation, the necessary changes caused frustration; they totaled JS scrolling nearly complete.
It is now my privilege to announce native scrolling’s time to pounce. For the devices that support it, you no longer must port it. Yes, it even has that native bounce!
The Real Story
Ionic was created in the fall of 2013, which by all accounts is just year and a half ago. But in mobile web time, it was a generation ago! Back then, iOS 6 still had dominant market share, and Android 2.3 demanded support.
Among other things, those browsers lacked proper scroll events. This meant that to pull off features like pull to refresh and infinite scrolling, JS scrolling would be required. Once we added it, we found we were also able to do things like list reordering and even collection-repeat.
However, Android 4.1+ supports native scroll events, and now with Lollipop and chromium webviews, those scroll events are asynchronous and won’t interrupt the smooth display of scrolling behavior. It’s an exciting time for scroll events in Android!
On the other hand, iOS is a bit of a different story. With iOS 8, Apple introduced WkWebView, which includes native scroll events. The one problem, though, is in iOS 8 Beta 3, WkWebView’s support for the file protocol broke and was never fixed. That meant that Cordova was stuck using the UIWebView that had been mostly unchanged since iOS 7, which lacked complete native scroll events.
One popular solution is to bind to touchmove events and create fake scroll events. This works nicely, until the user lets go, and iOS’s inertia scrolling takes over. We were able to accurately recreate Apple’s inertia formula but unable to get a consistently accurate read of the velocity that that equation depends on, because that’s determined in native land. We’re only provided occasional touchmove events to guess. Turns out 18ms is a long time when it comes to determining accurate velocity, and our best tests still had a 30% margin of error.
This means that iOS, for the time being, still requires JS scrolling. Android, however, gets to enjoy Ionic’s new native scrolling support. Pull to Refresh, Infinite Scrolling, List Reordering, and the
$ionicScrollDelegate all work with native scrolling now!
One important caveat is that because of how collection-repeat works, it requires rapidly shifting the scroll content, hijacking the scroll behavior, and recreating the scrollbar. That’s pretty much JS scrolling, so we set it so that collection-repeat will force an ion-content to use JS scrolling.
Native scrolling can be enabled using
overflow-scroll=”true” on your
ion-content or using the
$ionicConfigProvider to set it globally in current versions of Ionic. We want to let it be a bit more battle tested before making it the default in Android, but give it a shot in the current nightly and let us know how it’s working for you!