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

bug: White flash appearing when switching between tabs on Android #3907

Closed wonderdogone closed 8 years ago

wonderdogone commented 9 years ago

Type: bug

Platform: android 4.4 webview

when switching between tabs ONLY on Android platform, the app show a white flash. This is in 1.0.0 stable. Not using crosswalk. Forum post http://forum.ionicframework.com/t/white-flash-appearing-when-switching-between-tabs-on-android-in-1-0-0-stable/24774

ghost commented 9 years ago

Any word about the status of this issue?

GentryRiggen commented 9 years ago

Having same issue. Any updates?

hadarge commented 9 years ago

+1

mhartington commented 9 years ago

Please provide a minimal example that has this issue.

hadarge commented 9 years ago

Just create a new ionic app (tabs template) change the background to any color either then white. build and run on android device (4.4, i'm tested on nexus 5) and you will notice that there is a white flick for few millis on every tab change.

GentryRiggen commented 9 years ago

I have found that this is due to ion-header-bar being redefined in each view. I moved ion-header-bar to my main layout template and no longer see the flicker. I believe the default generated project puts the header bar in each view which is why you see it there as well.

hadarge commented 9 years ago

the 'ion-header-bar's is automatically generated for me, where (and how) you manually use it ?

mhartington commented 9 years ago

So @GentryRiggen you mean the ion-nav-bar?

GentryRiggen commented 9 years ago

@mhartington I am using ion-side-menu with a ion-tabs inside of the ion-side-menu-content.

<ion-side-menus>
  <ion-side-menu side="left" class="left-side-menu">
    <ion-content drag-content="false" overflow-scroll="false" direction="y" delegate-handle="leftMenu">
      <div class="list">
        <a menu-close class="item item-icon-left" >Something</a>
        <a menu-close class="item item-icon-left" >Something</a>
        <a menu-close class="item item-icon-left" >Something</a>
      </div>
    </ion-content>
  </ion-side-menu>

  <ion-side-menu-content>
    <ion-header-bar align-title="center" class="bar-positive">
      <button class="button button-icon icon ion-navicon" menu-toggle="left"></button>
      <div class="titles">
            <h>TITLE</h1>
      </div>
    </ion-header-bar>

    <ion-tabs class="tabs-positive tabs-icon-only dark-background">
      <ion-tab>
        <ion-nav-view name="tab-1"></ion-nav-view>
      </ion-tab>

      <ion-tab>
        <ion-nav-view name="tab-2"></ion-nav-view>
      </ion-tab>

      <ion-tab>
        <ion-nav-view name="tab-3"></ion-nav-view>
      </ion-tab>
    </ion-tabs>
  </ion-side-menu-content>

</ion-side-menus>
mhartington commented 9 years ago

Don't use the ion-header-bar for that, use the ion-nav-bar.

hadarge commented 9 years ago

@mhartington Im using the 'ion-nav-bar' and the screen flickering (while moving between tabs)... so how do you suggest to fix it ?

wonderdogone commented 9 years ago

the simple tabs "starter" from ionic built for android shows the flash between navigating and that i believe uses ion-nav-bar.

mhartington commented 9 years ago

Hmm, I'm not seeing it in my tests.

https://youtu.be/_ja8a08iSPE

hadarge commented 9 years ago

You can see it in the video .. It's the white screen flash when you change tabs.. It appears for just few milliseconds... If you want the see that more clearly change the background color to red, blue or any dark color .

mhartington commented 9 years ago

Are you talking about the fading nav bar

didbarbosa commented 9 years ago

He is talking about the white screen (ion-content perimeter) that briefly appears when you switch tabs. You can clearly see it in your video when you switch the first time from "Status" to "Chats". But it actually appears every time.

hadarge commented 9 years ago

@mhartington I attached a video form my app (slow motion) you can clearly see it append there. I would like to take a action and help you guys to solve that issue, but I need at least a start point from you.. where should I start ?

youtube link : https://youtu.be/TTuNPlL6Fmg

Thanks.

didbarbosa commented 9 years ago

I've looked at the code and to me the error is in the tabSelected function (ionTab directive) It seems to hide the previous tab before showing the new one.

This dirty hack i've made seem to work. But I'd love to see a proper fix. Just add a timeout around $ionicViewSwitcher.viewEleIsActive(childElement, false);

Line 55025 of ionic.bundle.js

$timeout(function () {
 $ionicViewSwitcher.viewEleIsActive(childElement, false);
}, 100);
lloy0076 commented 9 years ago

This is happening to me with:

I'm running Android 5.1.1 on a Nexus 4.

To reproduce it, I just simply make a "tabs" starter app, change the colour of the navbar to blue (e.g. by changing -stable to -positive) and the flickering becomes obvious. It does actually flicker with the white navbar but you can't see white on white flickering.

I have attempted to add styles to force the transition-time to 0ms on Android and verified that the app has applied these styles to any header item by checking with an attached chrome inspector and inspecting the computed CSS values. I double checked by removing the styles and verifying they went from 0ms to some other number (0.2ms or 0.5ms - and actually about as fast as the flashing effect).

I tried doing @didbarbosa fix but Chrome on the browser and the phone app both complained that $timeout was not defined. When I logged the value of $timeout, it was indeed not defined.

didbarbosa commented 9 years ago

@lloy0076 you need to inject it into the directive

IonicModule
.directive('ionTab', [
  '$compile',
  '$ionicConfig',
  '$ionicBind',
  '$ionicViewSwitcher',
  '$timeout',
function($compile, $ionicConfig, $ionicBind, $ionicViewSwitcher,$timeout) {
lloy0076 commented 9 years ago

@didbarbosa - Actually I just noticed that my version of Ionic isn't the latest release; thus I changed my "bower.json" to read:

{ "name": "HelloIonic", "private": "true", "devDependencies": { "ionic": "driftyco/ionic-bower#~1", "platform.js": "platform#~1.3.0"

...and would you believe it theres no flickering even without the $timeout solution...

Maybe if you tried the same with the CSS transition solution it might just "fix" itself - although I hate problems that magically fix themselves like that.

didbarbosa commented 9 years ago

Yes it seems to be disapeared with the nightly release. Good news :)

didbarbosa commented 9 years ago

Actually it is not fixed for me.

hadarge commented 9 years ago

not fixed for me 2 :\

rollback91 commented 9 years ago

Any news about this issue?

harryzun commented 9 years ago

I have this issue on iOS as well.

simplesmiler commented 9 years ago

@harryzun regarding iOS please see https://github.com/driftyco/ionic/issues/4395

Zorgatone commented 9 years ago

On iOS it's not the same issue

gentlemanjohn commented 9 years ago

I just started noticing this on Android too sometime after I upgraded to v1.1. Not sure when it started though.

wonderdogone commented 9 years ago

it started around v1

arenddeboer commented 9 years ago

If anyone has a (temporary) fix, I would love to hear it.

capellmarcos commented 8 years ago

I'm the same bug... anybody have more info?? :octopus:

EnSabanNur commented 8 years ago

Probably not related, but I had a similar issue earlier, and for some bizarre reason deleting cache: false from my state definition for the offending sibling tab state cleared the issue. I have zero idea why, as we're using this same pattern, with the same controller+template combo, in 3 other places in our tab setup with out any issue.

update

So I just spent a little bit of time trying to get down to the bottom of the issue we saw, kinda interesting and a little bit of naivety on my part lead to the flicker of black prior to stateChangeSuccess.

So as mentioned above, we use the same pattern all over our application, but with one key difference: this state actually had a API backed resolve in its state definition to get around a shortcoming we currently have on our back end that we didn't need to be accounted for with the other x3 states that use this pattern.

The "chat" state was a sibling of main the state for the tab. To reach this state you'd simply click on a member in the main view and you'd end up in the sibling chat state. When navigating into it from the sibling, no black flash was observed, the main state would be visible until the resolve had finished, and then normal navigation would finish. When navigating back to the tab (from another tab) with the chat view as the current state in history, ui-router + ionic would execute the swap to the new tab immediately, but the black screen would be visible until the resolve had been completed.

This also makes sense as to why removing cache: false and defaulting to true fixed the issue.

Makes perfect sense when you think about it I guess. Hopefully this might be able to save someone a headache if they stumble upon this via google (same way I did).

andreialecu commented 8 years ago

I tracked this down to this line: https://github.com/driftyco/ionic/blob/af1bfef327e685585244c6051c4d38b98aa6c62a/js/angular/service/viewSwitcher.js#L194

          if (renderStart && renderEnd) {
            // CSS "auto" transitioned, not manually transitioned
            // wait a frame so the styles apply before auto transitioning
            //$timeout(onReflow, 16); <- original
            onReflow(); // removes flicker
          } else if (!renderEnd) {

It's the cause for the one frame flicker when tabs are switched, because the new tab is not set to visible until 16 ms later.

I'm not sure what the point of that line is when tabs are involved, but if you replace the $timeout call with a simple method call of onReflow(), perceived performance is greatly improved and there is no more flicker. Not even in the nav bar.

@mhartington any thoughts regarding this? Perhaps it should be made configurable at the very least.

Seems to be introduced by https://github.com/driftyco/ionic/commit/8ebde73d0b8afac1bf1c1787c90a72a28a88bc3a from @adamdbradley

Edit: a better fix seems to be to just change the if condition to:

if (direction !== 'swap' && renderStart && renderEnd) {

Edit2: An even better fix that gets rid of any potential side effects is to replace the $timeout call with: ionic.requestAnimationFrame(onReflow); I will send a PR with it.

andreialecu commented 8 years ago

Opened PR https://github.com/driftyco/ionic/pull/4654

didbarbosa commented 8 years ago

Very well done! Fixes the issue to me.

Thanks a lot mate.

AdrienDC commented 8 years ago

Didn't work for me... I've updated my ionic-angular.js file but I see no change even if I'm increasing the initial timeout value. Am I missing something? For the nav bar flickering I used this fix https://forum.ionicframework.com/t/flickering-when-navigating-via-tabs-on-android/27281 but now content is it flickering.

AdrienDC commented 8 years ago

Finally it's working but it's still flickering once the first time for each tab, any idea why?

fdu-axiometrics commented 8 years ago

Is there any release plan on this issue? 1.2 or 1.3 ?

ghost commented 8 years ago

It's included in the recent 1.2 release.

FreezeSoul commented 8 years ago

+1 , is there any other solutions?

wonderdogone commented 8 years ago

wow this is still going on.eh..Was figuring the core team would have a good idea what this wasAnyone have a good pointer to source code we might start experimenting with?

mlynch commented 8 years ago

Did 1.2 fix this? There was a commit in there that should have addressed this issue.

ghost commented 8 years ago

The bug is still here on 1.2 to 1.2.2

ghost commented 8 years ago

I tried again and it is solved if you put :

ionic.requestAnimationFrame(onReflow);  

as he said, and not :

$timeout(function() {
              ionic.requestAnimationFrame(onReflow);
            });

Obviously, $timeout is doing something

andreialecu commented 8 years ago

@mlynch maybe you remember what this was for? https://github.com/driftyco/ionic/commit/d0246cf975bb4022eb890d3b0c28964e3065644c#diff-e25bdd32bda2f4f00f01c823ec86b1f3

Seems to have broken it again.

ghost commented 8 years ago

Maybe this is why :

if code is queued using $timeout, it should run after the DOM has been manipulated by Angular, and after the browser renders (which may cause flicker in some cases)

mlynch commented 8 years ago

Reviewing for 1.2.5

mlynch commented 8 years ago

Unfortunately, this broke #4782 which caused the back view to sometimes not animate correctly. Removing $timeout is probably too simplistic of a solution for this.

AdrienDC commented 8 years ago

still have the issue even when I remove the timeout..