ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.03k stars 13.51k forks source link

Occasional flicker on nav transition #1531

Closed mlynch closed 10 years ago

mlynch commented 10 years ago

Occasionally there will be a flickr when navigating between views in recent Ionic versions. For some reason I'm really only able to make it happen when going "back" rather than forwards.

We should think about getting this fix merged in with the upcoming platform transition changes and Beta 7.

juliancesar commented 10 years ago

I have the same problem, but i always had, even before the beta 7!

CoenWarmer commented 10 years ago

Second this

ghost commented 10 years ago

Yeah, I'm having this issue when is a dynamic view (load angularjs variables).

edit: the problem is when you have a navbar in the main view and in the child views you override the buttons in the navbar causes this flicker.

travisdahl commented 10 years ago

I also noticed this after updating to "ionic": "1.0.0-beta.11" and "angular": "~1.3.0-beta.17". Wasn't sure which one was the culprit. When I first updated both, there were a few z-index issues on ng-leave and ng-enter but those were pretty easy to fix for slide-left-right-ios7 in the css. Still experiencing the flicker though when using a device and phonegap iOS. I don't see it on my desktop browser though. Even on the device its very intermittent, sometimes it happens and sometimes it doesn't. The problem Im seeing is that the transition finishes correctly, then the previous screen will flash. My guess is that it is flashing right before the markup is removed at the end of the transition.

perrygovier commented 10 years ago

So I spent some time investigating this today. It appears the first time UI Router loads a template file. I haven't dug in to UI Router to confirm this, but it's my suspicion that the first time it loads, it loads the new page asynchronously, where it has a digest cycle where it starts the page transition animation before the new template is ready. Therefore you see a flicker when the template is loaded and parsed, after the page transition animation has already started.

To help validate my assessment, try adding this to your project's $ionicPlatform.ready():

    var templates = [
      "tab-front-page",
      "tab-newest",
      "tab-search",
      "tab-comments"
    ];
    templates.forEach(function(tpl){
      $http.get('templates/'+tpl+'.html', { cache: $templateCache });
    })

Where each item in templates is the name of a template file

Or something like it so it fires an $http.get() that uses the $templateCache when your app is initially loading.

If I'm correct, the flicker should go away in most cases.

perrygovier commented 10 years ago

Still digging in, but here's a video that demonstrates the problem and some logging around it. Flicker Bug Demonstration

Step through the page transitions frame by frame and take note of the console logs. Note that updateView() is called 3 times, twice from $stateChangeSuccess is called twice.

When the page is not yet in the templateCache, the first time updateView() fires locals and viewLocals are unequal. Therefore the rest of the method fires and the old view is dismissed. Then again on the third time, they're unequal again, and it updates with the new view data.

When the page exists in the templateCache, locals and viewLocals are not equal until the third time updateView() is called. This mean the previous view is not dismissed until the new view is ready. It can delay the loading of the new view, but imho, that's on the developer to make sure they're not trying to load a 1mb template file in just a few MS. They should use a loader or some other convention.

I want to be very cautious with whatever fix I implement, as a poor fix here could cause a lot of trouble. I'll be investigating ways to effectively dismiss the first time updateView() is called, or when it's not called from $stateChangeSuccess.

dbaq commented 10 years ago

I don't know if it is really related to this issue, but I also have a flicker the first time I am opening a modal on the latest beta (11). Caching the template at the loading with $http.get('views/signin-email.html', { cache: $templateCache }); did the job and the flicker is gone. Let me know if you need more details or a plunker.

mlynch commented 10 years ago

Okay, so I'm 99% sure this is the source of the issue:

https://github.com/driftyco/ionic/blob/master/js/angular/service/viewService.js#L483

When we add and remove the disable-pointer-events body class, the entire element gets repainted, causing a flicker on iOS Safari. Removing this removes the flicker.

@adamdbradley what do you think the implications would be of disabling this? Could we instead tell the click handler to just not listen for clicks then?

mlynch commented 10 years ago

@adamdbradley I created a test of the "master switch" for tap, along with changing the pointer-event stuff in view service to see how it works:

https://github.com/driftyco/ionic/pull/2072

but it's still buggy, especially for back buttons and stuff :(

Also, hmm. Just had an idea of not applying a class but instead setting the style directly for pointer-events none?

mlynch commented 10 years ago

or! Hide and show a "click blocker" element http://www.thecssninja.com/javascript/pointer-events-60fps/comment-page-1#comment-7379

travisdahl commented 10 years ago

In my particular case, the culprit ended up being having a sibling element (in my case a footer) after </ion-content> in one of my views, if I hide that element until after the view is loaded, it solves the flicker.

lazamar commented 8 years ago

In my case it was happening in only one view and was solved by removing the resolve conditions in the view.