LibGdx: Add a Splash or Loading screen to Android libgdx project

When running LibGdx on Android, it takes a little while for anything but a black screen to show. My game only has three fonts and a small ui skin that it has to load and it takes roughly 8 seconds. That means a user who is trying your app for the first time might think that its laggy and then uninstall it. To me, this is a big issue. My solution to this problem was to use a splash screen.

A splash screen cant be implemented inside the core project because it wont draw anything until LibGdx is initialized, so for our solution, we need to do some Android trickery.

First of all, we need to add a callback to our game class in the core project. Create an interface called OnLoadListener

public interface OnLoadListener
{
	public void onLoad();
}

then in your game class (mine is called RhythmtapGame) add a constructor that takes a listener and one that takes no parameters so that it wont mess up your other platforms

public class RhythmtapGame extends ApplicationAdapter
{
	private OnLoadListener onLoadListener;
        public RhythmtapGame()
	{
		super();
		this.onLoadListener = null;
	}
	
	public RhythmtapGame(OnLoadListener listener)
	{
		super();
		this.onLoadListener = listener;
	}
}

then in your create function

@Override
public void create ()
{
  //This is where you load your fonts, skins, images etc...
  //
  //
  //
  //done loading

  if(onLoadListener != null)
  {
     onLoadListener.onLoad();
  }
}

Now that the callback is in place we need to add our loading screen to the android code. For my game, I used an ImageView for my loading screen, but you can use any sort of Android view that you want to be displayed while LibGdx is initializing.

If you aren’t too familiar with Android, here’s the gist of what we are going to do. We are going to add a FrameLayout that has two children: our splash screen and the game view. When the callback is triggered, we remove the splash screen so that the game view is visible.

public class AndroidLauncher extends AndroidApplication 
{
	private FrameLayout baseLayout;
	private ImageView loadingImage;
	
	@Override
	protected void onCreate (Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
		config.useAccelerometer = false;
		config.useCompass = false;

		// Do the stuff that initialize() would do for you
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

		baseLayout = new FrameLayout(this);
		FrameLayout.LayoutParams frameParams =  new FrameLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
		baseLayout.setLayoutParams(frameParams);

		createGameView();
		createLoadingImage();

		setContentView(baseLayout);
	}

	private void createLoadingImage()
	{
		try
		{
			loadingImage = new ImageView(this);
			Drawable drawable = Drawable.createFromStream(getAssets().open("loadingbackground.png"), null);
			loadingImage.setImageDrawable(drawable);
			FrameLayout.LayoutParams imageParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
			loadingImage.setScaleType(ScaleType.FIT_XY);
			loadingImage.setLayoutParams(imageParams);
			baseLayout.addView(loadingImage);
		} catch (IOException e)
		{
			//No Image for you
		}
	}

	private View createGameView(AndroidApplicationConfiguration cfg)
	{
		RhythmtapGame gameObject = new RhythmtapGame(new OnLoadListener()
		{
			@Override
			public void onLoad()
			{
				//Very important to run this on the UI thread or it will crash
				runOnUiThread(new Runnable()
				{
					@Override
					public void run()
					{
						baseLayout.removeView(loadingImage);
					}
				});
			}
			
		});
		gameView = initializeForView(gameObject, cfg);
		FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
		gameView.setLayoutParams(params);
		baseLayout.addView(gameView);
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve this equation to verify you are a not a computer * Time limit is exhausted. Please reload the CAPTCHA.