iOS App Launch blink fix

If you have been developing apps for iOS with AIR, I am almost sure that you have come across the issue with the “App launch blink” that appears between, when your app has launched( showing the Launch Image) and when your app is instantiating its views.
Here I will explain a simple way to fix this annoying issue.

EDIT: Jeff Ward pointed out in the comments section, that you can actually just let the Bitmat stay, until your Starling has loaded and initialized, and then just remove the Bitmap.
This is possible because the “Normal” flash display list is above the Stage3D. I don’t know why I didn’t think of that :)

You need to apply these 2 steps in your app.

  1. Add a flash.display.Bitmap copy of your LaunchScreen image to your Document Class.
  2. when everything (loading texures, initialising view, ect) is finished. Fade that flash.display.Bitmap out.

Step 1

This is in you Document Class where you set up your Starling instance.

// flash.display.Bitmap
private static var _background:Bitmap;

private function initializeStarling(stage:Stage):void
{
     stage.align = StageAlign.TOP_LEFT;
     stage.scaleMode = StageScaleMode.NO_SCALE;
     stage.frameRate = 60;
     var viewPort:Rectangle = new Rectangle(0, 0, stage.fullScreenWidth, stage.fullScreenHeight);

     // Find out what device is running and create a flash.display.Bimap
     if (Globals.scale == 1)
     {
          _background = new Embeds.loading_1x_iphone();
     }
     else
     {
          _background = Globals.isIphone5 ? new Embeds.loading_2x_iphone5() : new Embeds.loading_2x_iphone();
     }
     // Add the flash.display.Bitmap on top of everything. // Remember Flash DisplayList is above the Stage3D
     addChild(_background);

     // Setup Starling
     _starling = new Starling(MainStarlingView, stage, viewPort);
     .... Other Starling setup code...
     _starling.addEventListener(starling.events.Event.ROOT_CREATED, function rootCreated(event:Object, main:MainStarlingView):void
     {
          _starling.removeEventListener(starling.events.Event.ROOT_CREATED, rootCreated);
          main.initialize();
          _starling.start();
     });
}

// This will be called from your Main Starling View when
// all is loaded and initialized.
public static function removeLaunchImage( onRemoved:Function ):void
{
     Starling.juggler.tween(_background, 1,
     {
          alpha:0,
          onComplete:function():void
          {
               _background.parent.removeChild(_background);
               _background.bitmapData.dispose();
               _background = null;
               onRemoved();
          }
     });
}

Step 2

This is in your Main Starling Class.


public function initialize():void
{
     var appDir:File = File.applicationDirectory;
     var device:String = "iphone";
     var scale:int = Globals.scale;
     var texturepacker:String = formatString("assetifier/assets/texturepacker/{0}/{1}x", device, scale);
     var glyphdesigner:String = formatString("assetifier/assets/glyphdesigner/{0}/{1}x", device, scale);

     Globals.AM = new AssetManager(scale);
     Globals.AM.verbose = true;
     Globals.AM.enqueue
     (
          appDir.resolvePath(texturepacker),
          appDir.resolvePath(glyphdesigner)
     );
     Globals.AM.loadQueue(function progress(value:Number):void
     {
          // All Loaded
          if (value == 1)
          {
               // trace("ASSETS LOADED");
               removeLaunchAndInit();
          }
     });
 }

private function removeLaunchAndInit():void
{
      _gameView = new GameView(new GameModel());
      addChild(_gameView);
      ThreeCrates.removeLaunchImage( _gameView.start );
}