Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a well-coded splash screen

We all know there is lots of tutorials about how to do a splash screen on Android. But we also know those are pseudo-splashscreens. I searched for many and I always saw Thread.sleep(x). That's not well coded, this is just to make the app beauty and looking like a professional app, that's not what I want!
Another problem with those splash screens is that they don't solve my problem because they only show it after the activity start and show the content view.

I have an app that does lots of things while initializing and when the app starts the user sees a black screen for a few seconds, enough time to annoy. So that's why I want to show a well-coded splash screen that removes that black screen that appears before the content view has been set.

I tried something. I included the splash screen (a RelativeLayout) into the layout that is set in the MainActivity, but as far as I know Android only shows the content after everything has been loaded, so if I'm trying to show some view from the content view I have to wait until everything has finished. Still, I'll send my code, it can help somehow...

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new SplashTask().execute();
}

private class SplashTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        initializeViews();
        mSplashScreen.setVisibility(View.VISIBLE);
    }

    @Override
    protected Void doInBackground(Void... params) {
        return null;
    }

    @Override
    protected void onPostExecute(Void params) {
        Standard.Initiate(MainActivity.this);
        verifyListStats();
        loadListAdapters();
        setOnClickListeners();
        mSplashScreen.setVisibility(View.GONE); 
    }

}

I tried to load some resources in doInBackground(...) but because I do some operations in onResume() that need those resources I can't do it (or at least I think I can't).

Any idea? I heard about a built-in mechanism similar to iOS launch images, perhaps that can be a way.

like image 229
Sergio Carneiro Avatar asked Aug 13 '13 20:08

Sergio Carneiro


3 Answers

When an activity is launched, Android starts a Zygote, an empty activity which does nothing, and sets your activity theme on it, then launches it. Once your activity is ready for display, it swaps the displayed activity to yours. For more info about Zygote, you can read this article by Cyril Motier

So to answer your question, you can do this :

  1. Create a small theme which a custom window background displaying your splash info (you can use 9-patch to center unscaled content);
  2. In your manifest, use this splash theme for your activity;
  3. in your activity's onCreate() method, call setTheme(R.id.yourActivityTheme) (call it before setContentView() );
  4. enjoy...

That way, your "splash screen" (ie : the zygote with your splash theme) will be visible until your activity is ready to be displayed.

like image 96
XGouchet Avatar answered Oct 22 '22 15:10

XGouchet


Edit: Here is a great tutorial for splash screens where you want the splash screen to appear for a set amount of time, or for some processing to finish. It gives the pros/cons of several approaches as well.

http://blogactivity.wordpress.com/2012/02/24/writing-splash-screens-the-right-way/

like image 28
Sky Kelsey Avatar answered Oct 22 '22 17:10

Sky Kelsey


Create a SplashScreen activity and declare it as default in your app, i.e. add this to your AndroidManifest.xml

  <activity
        android:name="package.SplashScreen"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:noHistory="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

In your SplashActivity onCreate launch a new AsyncTask:

public class SplashScreen extends Activity {

   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.splash_image);

      new InitAsyncTask().execute();
   }

   private class InitAsyncTask extends AsyncTask<?, ?, ?> {

      protected ? doInBackground(?... params) {
         // PERFORM YOUR INITIALIZATION HERE
      }

      protected void onPostExecute(? result) {
          // Initialization is completed, close SplashScreen 
          // and launch your MainActivity:
          SplashScreen.this.finish();
          startActivity(new Intent(MainActivity.class, SplashScreen.this);

     }
   }
}
like image 29
Anton Avatar answered Oct 22 '22 16:10

Anton