ionic-team / ionic-v3

The repo for Ionic 3.x. For the latest version of Ionic, please see https://github.com/ionic-team/ionic
Other
128 stars 85 forks source link

iOS bounce flicker glitch #113

Open tobiasmuecksch opened 7 years ago

tobiasmuecksch commented 7 years ago

Ionic version: (check one with "x") [x] 3.x

I'm submitting a ... (check one with "x") [x] bug report

Current behavior: When bouncing a page there's some strange flickering (see following video). I haven't found out yet what exactly on this page causes the flickering. But my current guess is, that the input fields with placeholders may be the cause.

This glitch does not appear in a PC browser (Safari for Mac e.g.). This only can be observed when you run the app on an iPhone (in my case iPhone 6)

ionic 3 - ios bounce flicker bug-2

In case you can't see the gif, I've additionally uploaded video right here: https://cl.ly/3K0X2T3X0z1l

Expected behavior: Well, the view should bounce without the strange flickering.

Steps to reproduce:

  1. Clone the following repo: https://github.com/tobiasmuecksch/ionic3-overflow-flicker-bug
  2. npm install
  3. ionic cordova build ios --prod
  4. Run it on an iPhone
  5. Bounce at will

PLEASE do not give me advice like: "Just add the no-bounce parameter", because it does only suppress the bug and not fix it.

m-stilling commented 6 years ago

@tobiasmuecksch A lot. These are all from the same page:

It does also happen for me on a page mainly filled with cards, albeit isn't as easy to replicate, possibly because it has a refresher.

tobiasmuecksch commented 6 years ago

@mich356c As I said in my previous comment;

I found out that the glitch only appears when I touch the ion-card while scrolling [...].

This explains why it can be observed on pages mainly with cards.

I'm trying to investigate the ionic code base. This is why I asked for the components you use. Im trying to find a relation...

m-stilling commented 6 years ago

I was just pointing out it was harder for me to replicate on such page, possibly due to the refresher. Poor phrasing on my part.

tobiasmuecksch commented 6 years ago

🎉 GOOD NEWS! 🎉

I finally found a potential root cause of this issue!

There seems to be a bug in iOS safari regarding this line: https://github.com/ionic-team/ionic/blob/0182014fe5166fed044e80fe98889648c9a65456/src/components/card/card.ios.scss#L127

My current guess is that iOS Safari cannot handle the combination of width: and calc() properly.

When you add the following rule to your app, the issue disappears for <ion-card>.

.card-ios {
    width: 100% !important;
}

The Problem:

Additional info

tobiasmuecksch commented 6 years ago

Okay. I got one step further. While the issue is related to the width: calc() part, it's not the one and only cause.

I've created an HTML file, in which I cloned the DOM-Tree of the App and imported all generated ionic styles (including the width: calc() part!). It's nearly the same, but without any JavaScript.

Fun fact: The issue doesn't appear in the pure CSS & HTML scenario....

Conclusion

There must be some JavaScript related side-effect. Maybe some scroll-event-handler... My knowledge of the ionic code base is to small; I don't even know where to start investigating.

Does anyone have a suggestion where to start?

Code

You can download the code here: https://cl.ly/2B2K2A043a02

mhartington commented 6 years ago

Hey @tobiasmuecksch thanks for all your work in investigating this. This leads to my theory that this is bug/issue with scrolling in Webkit, as this error does not appear in chrome. I'll look through the ionic source code and start to work on better alternatives for this.

aMUSiC commented 6 years ago

Some interesting updates:

Tried the same app on an iphone 5s with ios 10.3.1 and there is no flickering at all on bounce (for images, not input fields with placeholders)

No flickering as well on an iPhone 6plus with iOS 11.2.5

wolf88888888 commented 6 years ago

You can debug ios Ionic app using Safari, while debugging you can notice which is efficient.

Add below *-page.scss.

.scroll-content {
    overflow-y: hidden !important;                                              
}

It will disable scrolling of ion-content and also disable scrolling of ion-list.

div.scroll-content {
    bottom: 0px !important;                                                   
}

It is more efficient to disable scrolling of ion-content. It prevents only ion-content but ion-list

jurgen-reconcept commented 6 years ago

I experience the same on a simple login page with an e-mail field and a password field. Interesting thing: if I remove either one of the fields (leaving one ion-input) everything is fine, but as soon as I add the second field, the bug occurs.

I've also noticed two other interesting things @mhartington:

  1. the flickering only seems to happen on release
  2. and only when I overflow scroll in the opposite direction that I did last time. So: first I scroll all the way to the bottom to bounce back up, I get a flicker. If I try that a second time, everything seems fine, even if I do it ten times. But if I alternate between overflow scroll down / overflow scroll up, i get a flicker every time.

E-mailadres

Wachtwoord

flugg commented 6 years ago

I'm experiencing the same problems, however, I'm not using Ionic, only Angular. The problem only seems to occur when I scroll touching a card (https://material.angular.io/components/card/overview). It only happens on iOS and it seems to be very similar to what @tobiasmuecksch reported. Is it possible this bug may be related to Angular itself?

tobiasmuecksch commented 6 years ago

@flugger @jurgen-reconcept As @mhartington already mentioned, this bug seems to be related to some misbehavior of iOS Safari / Webkit. I worked around it by creating my own cards that do not rely on width: calc(/*...*/);

jurgen-reconcept commented 6 years ago

@tobiasmuecksch my understanding was that this would still be investigated / possibly solved. I am not using cards, just the normal ion-input. Does this mean that there is no solution for me right now?

Golem765 commented 6 years ago

I am not really sure if it is even webview related, I've been using app called 'Day One journal' and it have very similar bug on text input, if text is taller than the screen and you try scrolling the same way - it starts to make those flickering bug and eventually make the app unresponsive. Yet they do have some custom logic of scroll down and I am not sure whether the app is native or cordova. So it's not 100%, but might be a guess

tobiasmuecksch commented 6 years ago

@jurgen-reconcept I'm afraid there's no solution this issue-page can offer you right now. I just can recommend you to read my posts on how I investigated this issue. Maybe it'll point you to your custom workaround. My latest information is, that @mhartington is working on the issue. I guess that he's focusing on a solution for ionic 4.x, which might be the reason why this issue got quiet again.

@Golem765 I too know some hybrid apps that suffer from this bug in production.

kensodemann commented 6 years ago

@liamdebeasi - did you ever post a link to the directive you mention here: https://github.com/ionic-team/ionic/issues/11844#issuecomment-321851213 ?

kensodemann commented 6 years ago

Related to ZenDesk ticket number 12983.

I created a sample app that shows this issue occurring just with placeholders added to inputs. The only difference between the Flicker and No Flicker tabs is the placeholders. No extra JavaScript code on either screen.

Repo: https://github.com/kensodemann/test-flicker Screencast: https://www.dropbox.com/s/ska1u83ic2ctbkg/ScreenRecording_04-02-2018%2013-15-33.MP4?dl=0

kensodemann commented 6 years ago

Thanks to @mlynch for this patch: https://github.com/kensodemann/test-flicker/commit/b8b0ebc7d256f8a0a8c0e5b83589455f5a59edfe

This fixed the issue in my sample repo anyhow, which was only using placeholders. Not sure how many (if any) other cases were here that didn't use placeholders, but if your sample code did, try the above patch.

mlynch commented 6 years ago

Submitted a PR with a possible fix. Needs more testing to verify no regressions but it does remove the flicker. See PR #14265 for a code snippet you could patch your apps with if you wish.

tskweres commented 6 years ago

OMG Finally. You have to position your placeholder absolute, then adjust the padding and margin of the parent input to make it fit properly. Trying to use top 50% and transform: translate on the placeholder does not work. Here's an example:

<ion-input type="text" placeholder="ICauseProblems" (keypress)="keyEvent($event)"></ion-input>

// somewhere in your css ......

ion-input {
    input {
          width: 100% !important;
          padding-left: 0 !important;
          padding-right: 0 !important;
          margin: 0;
          padding-top: 11px;
          &::-webkit-input-placeholder {
            position: absolute;
          }
    }
}

Depending on your other css and overrides I'm not sure if the importants are necessary. But make the placeholder absolute, then adjust the parent input's top margin / padding to make the placeholder sit in the proper spot. BOOM - no flicker.

glemiere commented 6 years ago

Any news about this ? It's been a while...

daansystems commented 6 years ago

The flickering seems to be caused by the bouncing of a scrolling view. So if you want momentum scrolling ("-webkit-overflow-scrolling: touch") and no flickering one way for now is to disable bouncing in the plugin Objective-C code. The "DisallowOverscroll" setting for the WKWebView Cordova plugin doesn't really work for scrolling DIVs, because it only disables bouncing for the main body UIScrollView. Every HTML element that has the CSS "overflow: scroll" style has it's own UIScrollView created, which has "bounces = YES" by default. So to completely disable bouncing in the WKWebView we need to make sure all UIScrollView elements have "bounces = NO". A quick way of doing this is to add to CDVWKWebViewEngine.m:

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
   [super didMoveToWindow];
   self.bounces = NO;
}
@end

This causes no bouncing and no flickering. Have a nice day.

TianleZhang commented 6 years ago

Yes, this solves our issue, thx

stewones commented 6 years ago

works awesome @daansystems thank you

mlynch commented 6 years ago

See my comment above for the real issue and fix. Unfortunately it had some side effects that made it hard to merge into master for now, but should work for you. Disabling bounce is not a workaround we recommend

mlynch commented 6 years ago

See my comment above for the real issue and fix. Unfortunately it had some side effects that made it hard to merge into master for now, but should work for you. Disabling bounce is not a workaround we recommend

glemiere commented 6 years ago

We can continue the discussion right here : https://github.com/ionic-team/cordova-plugin-wkwebview-engine/pull/198#event-1648040736

Scobee commented 5 years ago

@mlynch - the PR url does not work anymore - https://github.com/kensodemann/test-flicker/commit/b8b0ebc7d256f8a0a8c0e5b83589455f5a59edfe Is there anyway I can look at your fix ? Thank you

nbusseneau commented 5 years ago

@Scobee: Found PR link: https://github.com/ionic-team/ionic/pull/14265

@mlynch: We are also experiencing this issue on iOS with @ionic/angular 4.0.0-beta.7. Video displaying the issue: https://i.imgur.com/V42mZSo.gifv

Behaves like @tobiasmuecksch detailed in the OP: not working only on iPhone (both Safari and in-app browser), while working properly in Safari on Mac.

Apparently, the PR over at https://github.com/ionic-team/ionic/pull/14265 was never merged. I have not tested yet if it fixes the issue on our end, I will report back tomorrow.

Should we continue discussion here or create a new issue over at ionic-team/ionic? Related issue ionic-team/ionic/#10733 has been locked...

tobiasmuecksch commented 5 years ago

@Skymirrh I'd suggest to go straight to ionic-team/ionic and open a new Issue over there. For two reasons:

  1. I think the v3 repo has very low priority for the Ionic guys (understandably). So I wouldn't expect any further discussion here.
  2. If this issue is still present in v4 it's just making sense to mention this issue over there too.

But don't forget to reference this issue, so they can benefit from the information gathered here and they also still have the chance to identify this as potential duplicate.

nbusseneau commented 5 years ago

Thanks for your input, I'll make a new issue over at the v4 repo once I confirm this still happens with the latest version of v4.

SimonKomlos commented 5 years ago

@Skymirrh were you able to fix this issue? I'm having the exact same problem you are showing in your video.. It's been about 2 months so I thought I'd ask! Would love to know where you're at with that problem now :)

nbusseneau commented 5 years ago

@SimonKomlos We've put that issue on hold because of other priorities, however before doing that we confirmed it still happens with Ionic v4.

We had started to look into other ways to fix the issue by modifying the structure of our app, because we believe this only started to happen after we added several layers of containing elements above a list of items that gets filled after the view is initialized, whereas before it was working fine (confirmed with a git bisect and going back to before we added a lot of stuff).

We wanted to make sure to find out how to reproduce the issue reliably before opening an issue at the Ionic v4 repo. If you find anything I'll be interested ;)

SimonKomlos commented 5 years ago

@Skymirrh Thanks for the quick response! Yeah it also started happening for me after adding several layers of code, so I think I'll be able to figure this out. I'll update if I figure out the root cause!

tobiasmuecksch commented 5 years ago

@SimonKomlos I've already dug through a lot of Ionic code. And I can tell you, that the code is mostly clean and I've found no error source. Above I've identified a few workarounds (e.g. https://github.com/ionic-team/ionic-v3/issues/113#issuecomment-360416592). But it all boils down to the suspicion, that the bug is to be found within WKWebView.

SimonKomlos commented 5 years ago

@tobiasmuecksch Thanks for your input. I took a look at my code to see if any of my ion tags were using a calc operator but they weren't.

For me it's been happening on an ion-list. I have 3 very similar pages and on 2 of them the flickering occurs but on the 3rd it doesn't... I've been trying to compare and find out what the issue might be but to no luck. The only real difference between the 3 pages is that the 2 with flickering also have an ion-infinite-scroll element to it, but I've tried removing and it still flickers unfortunately. As far as I can tell it doesn't seem to be a surface-level issue. I'd rewrite the entire page if it fixed this silly flickering but I don't know what I can and can't use :(

tmk1991 commented 5 years ago

Same issue tends to happen with photos and videos. We get flickering on cards that have and

Ionic V4

szabikr commented 5 years ago

Using Ionic v3 to implement an ion-list with a virtualScroll property and experienced the flickering as well when bouncing off from scrolling all the way to the top. Tried a few things already, but no modification seems to fix it.

oveshparasara commented 4 years ago

The flickering seems to be caused by the bouncing of a scrolling view. So if you want momentum scrolling ("-webkit-overflow-scrolling: touch") and no flickering one way for now is to disable bouncing in the plugin Objective-C code. The "DisallowOverscroll" setting for the WKWebView Cordova plugin doesn't really work for scrolling DIVs, because it only disables bouncing for the main body UIScrollView. Every HTML element that has the CSS "overflow: scroll" style has it's own UIScrollView created, which has "bounces = YES" by default. So to completely disable bouncing in the WKWebView we need to make sure all UIScrollView elements have "bounces = NO". A quick way of doing this is to add to CDVWKWebViewEngine.m:

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
   [super didMoveToWindow];
   self.bounces = NO;
}
@end

This causes no bouncing and no flickering. Have a nice day.

this is working fine thank you

gianlazz commented 4 years ago

I'm also having this issue from a css animation on iOS. I'm using capacitor. I know there is a number of animations and I'm wondering why this one causes the problem when the ionic skeleton text for example doesn't?

The everything is smooth during scrolling however when it goes past the scroll into the bounce the screen flickers back out of the bounce then back into the bounce seemingly in time with the animation changes.

Here's some details on the versions: "@capacitor/cli": "^1.4.0", "@capacitor/core": "^1.4.0", "@capacitor/ios": "^1.4.0", "@ionic-native/core": "^5.0.0", "@ionic/angular": "^4.1.0",

@keyframes anim-glow {
    0% {
        box-shadow: 0 0 rgba(#61EF61, 1);
    }
    100% {
        box-shadow: 0 0 10px 8px transparent;
        border-width: 2px;
    }
}

.dot    {
    border-radius: 50%;
    border: 2px solid #61EF61;
    width: 10px;
    height: 10px;
    text-align: center;
    position: relative;
    animation: anim-glow 2s ease infinite; <-- commenting out this line fixes the problem
SSuarezBrooktec commented 4 years ago

same issue here when we draw a component every 2 seconds without fixed height (Only in ios/safari using capacitor)

lincolnthree commented 4 years ago

This bug is related to: https://bugs.webkit.org/show_bug.cgi?id=209968, and affects any element with a transformation/animation/opacity change during scroll-bouncing.

sardapv commented 4 years ago

I managed to get bounce completely removed thank you @glemiere & @daansystems

CDVWKWebViewEngine.m

//Add this block in every update of webview which disables bounce on iOS WkWebView

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
   [super didMoveToWindow];
   self.bounces = NO;
}
@end
ivinantony commented 3 years ago

In ionic 5 i also had the same issue. I fixed it by removing ion-subtitle form my card then the issue gone.

ollyde commented 3 years ago

I managed to get bounce completely removed thank you @glemiere & @daansystems

CDVWKWebViewEngine.m

//Add this block in every update of webview which disables bounce on iOS WkWebView

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
   [super didMoveToWindow];
   self.bounces = NO;
}
@end

New to Ionic, saw this nasty bug but can't find CDVWKWebViewEngine, I'm using Capacitor; where would this be?

sardapv commented 3 years ago

@ollydixon you can find it from platform ios folder easily via XCode. just search for it in Xcode

ollyde commented 3 years ago

I found the solution but disabling the iOS bounce also causes a host of other issues such as pull down to refresh.

@sardapv it's not there and there's no reference to it in Capacitor. Actually you need to create a file; something like DisableBounce.m and then copy this code into it (the full code)

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
    [super didMoveToWindow];
    self.bounces = NO;
}
@end
sardapv commented 3 years ago

I found the solution but disabling the iOS bounce also causes a host of other issues such as pull down to refresh.

@sardapv it's not there and there's no reference to it in Capacitor. Actually you need to create a file; something like DisableBounce.m and then copy this code into it (the full code)

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@implementation UIScrollView (NoBounce)
- (void)didMoveToWindow {
    [super didMoveToWindow];
    self.bounces = NO;
}
@end

Oh yes..it could be different for Cordova vs capacitor..never tried capacitor. Yes it totally disables bounce on webview which was my use case. Might not suite for everyone