apache / cordova-ios

Apache Cordova iOS
https://cordova.apache.org/
Apache License 2.0
2.16k stars 990 forks source link

DisallowOverscroll does not work on iOS 16 #1244

Closed PeterBenko closed 2 years ago

PeterBenko commented 2 years ago

Bug Report

Problem

The same code that worked as expected on iOS 15 seems to now be broken on the latest iOS 16 public beta. DisallowOverscroll used to successfully prevent the full app from bouncing, but on iOS 16 seems to have no effect.

What is expected to happen?

The full app should not bounce on scroll.

What does actually happen?

The app bounces on scroll

Information

We have investigated the issue and it seems like setting the scrollView bounces to NO doesn't fulfill its purpose anymore.

This would imply a change on iOS 16 side, but it is unclear if this is a bug or the new intended behaviour and thus a necessary change for cordova-ios.

Note: We could fix the issue in our application by additionally setting alwaysBounceVertical to NO but this doesn't align with Apple's documentation. The fix did however not work on a clean cordova-ios project so there must be some other factor to this that we could not yet determine.

Command or Code

The issue is reproducible with the base Cordova iOS app, with the "DisallowOverscroll" config set to TRUE: the same application behaves differently on iOS 15 than on iOS 16 when scrolling (at least for vertical scrolls).

Environment, Platform, Device

iOS 16, iPad

Version information

cordova 11.0 cordova-ios 6.2.0

Checklist

dpogue commented 2 years ago

iOS 16 supports the CSS overscroll-behaviour property to control this.

dpogue commented 2 years ago

This has been identified as a WebKit issue: https://bugs.webkit.org/show_bug.cgi?id=243270 & https://github.com/WebKit/WebKit/pull/2794

PeterBenko commented 2 years ago

Great, thanks for the reference!

skmbr commented 2 years ago

Adding overscroll-behaviour: none to the body and/or html tags under the latest iOS 16 beta doesn't appear to have any effect for me. 😞

The OP mentions alwaysBounceVertical. Is there any way I can set that myself as a workaround if the webkit issue doesn't get fixed before the full rollout of iOS 16?

breautek commented 2 years ago

The OP mentions alwaysBounceVertical. Is there any way I can set that myself as a workaround if the webkit issue doesn't get fixed before the full rollout of iOS 16?

Cordova doesn't expose an interface to set these native properties afaik, but you can fork cordova-ios and add the configuration options.

I'm not an iOS developer myself, but it seems like alwaysBounceVertical & alwaysBounceHorizontal are ScrollView settings, ~which neither is the WKWebView~ or our containing view is a UISrollView. Rather they are UIView's instead.

WKWebView's UIScrollView is exposed under a scrollView property, and I'm guessing you can set the scroll settings from there to workaround iOS 15 issues.

~So you may need to update https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVViewController.m#L503 to create a UIScrollView instead of a UIView and set the settings you want on it.~

Then you can install your fork from github, using cordova platform add <github clone url> When forking and making changes, I'd recommend branching off a release tag, as the repository may contain commits that haven't yet been voted on for release.

Edit Notes:

Applied https://github.com/apache/cordova-ios/issues/1244#issuecomment-1237373707 to my comment.

dpogue commented 2 years ago

The UIScrollView is internal to WKWebView's view hierarchy, and exposed as webView.scrollView.

From the WebKit changelog, it appears that the DisallowOverscroll preference should work as expected in the latest iOS 16 betas, and that overscroll-behaviour should be available in CSS if you do not set the DisallowOverscroll preference.

vbraun commented 2 years ago

There is no workaround, is there?

The new overscroll-behaviour: none only does something if the scroll container hits the top, but e.g. your app title bar (html div) is already at the top of the page. So you can always drag down the app title bar, regardless of the overscroll behavior setting.

Moreover, even if you ignore the title bar issue, setting overscroll-behaviour: none also disables bounce on that scroll container. So the content below the app title bar does not bounce any more, also not particularly nice.

Why is this issue closed, is this fixed upstream? Or is it at least clear that upstream is going to fix it, because the webkit bug has some discussion that makes it at least unclear to me. And then there is the whole question of whether Apple actually pull that into Safari.

What works for me is to edit CDVWebViewEngine.m to set alwaysBounceVertical as follows:

    // By default, DisallowOverscroll is false (thus bounce is allowed)
    BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);

    // prevent webView from bouncing
    if (!bounceAllowed) {
        if ([wkWebView respondsToSelector:@selector(scrollView)]) {
            UIScrollView* scrollView = [wkWebView scrollView];
            scrollView.bounces = NO;
            scrollView.alwaysBounceVertical = NO;   /* iOS 16 workaround */
        } else {

Is there any interest into turning that into a PR?

dpogue commented 2 years ago

The pull request to fix this in WebKit is still open and being worked on: https://github.com/WebKit/WebKit/pull/2794 However, it probably won't get released until iOS 16.2 or 16.3.

In a test, I was able to use overscroll-behavior: none on the html element to disable all scroll bouncing. You should be able to use overscroll-behavior: contain on scrollable areas to retain the bounce effect on specific regions of content.

However, if setting alwaysBounceVertical and alwaysBounceHorizontal to false is a workaround for iOS 16, I think we'd accept a PR to add that.

vbraun commented 2 years ago

The only way I can see that overscroll-behavior: none on the <html> tag can do anything is if the body is the scroll container. In that case it works. But anything that resembles an app has a layout where the body must fit the screen

[    Title bar     ]
[------------------]
[ scroll container ]
[------------------]
[  optional footer ]

so the body is not scrolling. Then overscroll-behavior: none on the <html> does not prevent you from bounce-scrolling the whole page by dragging the title bar down.

vbraun commented 2 years ago

I now get an App Store Connect Operation Error: The app references non-public selectors whether or not I add the alwaysBounceHorizontal, will report back when the app store is working again.

EDIT: Actually the app is uploaded to testflight despite the error, seems like others also encounter that app store bug: https://developer.apple.com/forums/thread/714465 🤨

OscarGonzalez04 commented 1 year ago

My solution was to add the following code to the global styles :)

ion-content{
  &::part(scroll){
    overscroll-behavior: none;
  }
}
Tioecomp commented 1 year ago

My solution was to add the following code to the global styles :)

ion-content{
  &::part(scroll){
    overscroll-behavior: none;
  }
}

Where is it? Global styles?

OscarGonzalez04 commented 1 year ago

My solution was to add the following code to the global styles :)

ion-content{
  &::part(scroll){
    overscroll-behavior: none;
  }
}

Where is it? Global styles?

If global styles. In the file: global.scss

tamsel12 commented 1 year ago

My solution was to add the following code to the global styles :)

ion-content{
  &::part(scroll){
    overscroll-behavior: none;
  }
}

Yes it is working fine in IOS 16.2 version