Ok and now I have a blank solution with Android app ready to go, so I do what all of us do. That is, go to his majesty Google.com and start digging for the keywords Xamarin Forms Splash Screen Android.
And voila, the first of the results is a page from the Xamarin.com site itself,
Creating a Splash Screen. Great.
So let us start doing what they suggest.
Official recipe
Ok, let us do it by the book, but instead of their “
Loading…” image in the Resources/Drawable folder, I'll use the following Logo image:
MCN = My Company Name. How imaginative is that! And the file name:
MCNLogo.png.
Ok, we're done with the image, let's do our Splash Screen theme as they suggest:
- Create a new folder under the Android project folder "Resources" with the name "Values".
- In that folder add a new "Styles.xml" file. Add -> New Item, then XML File. Make sure after creating this file to have the property "Build Action" set to the default value: "AndroidResource". In this file we will create a new theme "Theme.Splash" that set the background of our Splash with our logo.
- Edit the file to be as follows:
- <?xml version="1.0" encoding="utf-8" ?>
- <resources>
- <style name="Theme.Splash" parent="android:Theme">
- <item name="android:windowBackground">@drawable/mcnlogo</item>
- <item name="android:windowNoTitle">true</item>
- </style>
- </resources>
- Add a Splash Activity to the Android Project using Add -> New Item, then Activity. Let's name it SplashActivity.
- Change the attributes of the activity to set the theme attribute to "@styles/Theme.Splash", MainLauncher attribute to "True", and NoHistory also to "True". The Theme attribute is responsible for the style of the activity, the MainLauncher is responsible for making this activity the first activity to show and NoHistory is responsible for preventing navigation back to this activity. The activity attributes should look like the following:
- [Activity(Theme = "@style/Theme.Splash", MainLauncher = true, NoHistory = true)]
- Add the following code to the "OnCreate" method in Splash activity immediately after the comments // Create your application here:
- System.Threading.Thread.Sleep(10000);
- StartActivity(typeof(MainActivity));
The first line simulates a long-loading process.
The second line Start our MainActivity where our application will run main tasks after the Splash is shown.
- Just before running the application, we need to ensure that the MainLancher attribute of the MainActivity is set to false:
- [Activity (Label = "AppWithSplashScreen", Icon = "@drawable/icon", MainLauncher = false, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
- And let's run the application. (I don't like working with emulators so I will run it on my Samsung S5).
Pretty simple isn't it? Well wait a second.
Observations
Well, I got my splash screen. But here are some observations of the app:
- The app icon on my devices is the standard Android icon, and that is easy to fix. Just add an icon attribute of the SplashActivity to match that as the MainActivity:
- [Activity(Theme = "@style/Theme.Splash", Icon = "@drawable/icon", MainLauncher = true, NoHistory = true)]
- Sometimes also Xamarin will install the package to your mobile with some random name instead of the name of the application: AppWithSplashScreen. That is also not that complex to fix in many ways, but for now I'll just add the label attribute of SplashScreen to the one in MainActivity:
- [Activity(Label = "AppWithSplashScreen", Theme = "@style/Theme.Splash", Icon = "@drawable/icon", MainLauncher = true, NoHistory = true)]
- This observation is not a big deal, but wouldn't it be better to have the splash screen in full screen mode? In order to do that just change the parent theme in Styles.xml to "android:Theme.Holo.Light.NoActionBar.Fullscreen".
- <style name="Theme.Splash" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen">
- 10000 in Sleep line in SplashActivity.cs is good to watch the now but it is too long (10 sec) for a splash screen. So I will reduce it to 5000 and in the final version of my app it will go to 2000 even.
- The most "dangerous" observation is:
My logo is stretched all over the screen for whatever reason and it is ugly.
Revised Task
Build an app with Splash Screen that contains a logo at the center of the window!
Official Recipe again
So after searching with same keywords of the revised task, I came to this solution at Xamarin forums. Basically it says that instead of having an image (MCNLogo) as background in Styles.xml, we can redirect to the compiler to another XML resource where we set the image and some of its attributes to center it in the screen.
So:
- In Styles.xml replace the value of the "windowBackground" attribute to "@drawable/backgroundstyle" instead of "@drawable/mcnlogo":
- <item name="android:windowBackground">@drawable/backgroundstyle</item>
- In the Resource/Drawable folder add a new XML file and name it "BackgroundStyle.xml" with the following code inside:
- <?xml version="1.0" encoding="utf-8" ?>
- <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/mcnlogo"
- android:gravity="center"
- android:layout_gravity="center"/>
"gravity" and "layout_gravity" are set to center and centers the image in the Activity.
- Run the application:
Here you are, a centered logo in a full screen activity. If this is what you want, then you can stop reading this article and start writing your application code after the splash screen, but there is more that can be done.
More Observations
It is too dark, isn't it? I wonder if it would be better to have a White background?
Revised Revised Task
Build an app with Splash Screen that contains a logo at the center of the window with a White background!
Shibbs Recipe
Searching Google with these keywords didn't give me an answer, but I found this question in Stack Overflow that matches mine.
One of the answers (Shibbs' answer) was very interesting. Basically he suggests, why have the logo image as the background image? The SplashActivity is an activity at the end. So it can have it is own AXML layout where we can do whatever we want (almost). But the most interesting thing is the way he queues the MainActivity in the ThreadPool, allowing the splash screen to draw the XAML layout. Without this we will have only the blank splash screen:
- In Styles.xml, remove the entire line where the "windowBackground" attribute and value are. Instead insert the following line specifying that the background is of White color:
- <item name="android:colorBackground">@android:color/white</item>
- In the Resources folder, create a new folder "Layout". Here we will add our layout for the SplashActivity.
- In the Layout folder, add a new Android Layout: Add->New Item...->Android Layout. let's call it "SplashLayout.xaml".
- Edit the source of SpalshLayout to match the following markup:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:minWidth="25px"
- android:minHeight="25px"
- android:gravity="center">
- <ImageView
- android:src="@drawable/mcnlogo"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:id="@+id/imageView1"
- android:layout_gravity="center" />
- </LinearLayout>
Here we have an ImageView in the center with source (src) of mcnlogo in the drawable folder.
- In SpalshActivity.cs, edit the "OnCreate" method to match the following code:
- protected override void OnCreate(Bundle bundle)
- {
- base.OnCreate(bundle);
-
- SetContentView(Resource.Layout.SplashLayout);
- System.Threading.ThreadPool.QueueUserWorkItem(o => LoadActivity());
- }
In this code, we set the content view of the SplashActivity to our SplashLayout.xaml and then we queue the MainActivity in the ThreadPool object using the LoadActivity method that we will write in the next step.
- Add a new method to the SpalshActivity class called "LoadActivity":
- private void LoadActivity()
- {
- System.Threading.Thread.Sleep(5000);
- RunOnUiThread(() => StartActivity(typeof(MainActivity)));
- }
Note how we shifted the sleep period to this method.
- Run the application:
Here's our splash screen with centered logo and White background. If you reached your goal, you can stop reading this article. But something is bothering me. What about having a different (custom) background color? Let's say light Aqua color, it would be nice with our bluesh logo.
More observations again
- There is a White blank screen showing for a small period before our logo is shown. In debug mode it takes longer than in the real app. Anyway, It is not a big deal as long as the colors match.
- As long as you use the "Theme.Holo.Light.NoActionBar.Fullscreen" theme as your parent theme in Styles.xml, the color will be White. I tried to write "android:color/black", the color remains White. As a matter of fact, even if you remove the entire line of the colorBackground attribute, the color remains White. I even tried to play around with custom color references like here but no matter what , if you stick to the parent theme, the color will remain White.
Back to Official Recipes
So, we cannot change the background color in this theme, but we can change the background itself, right?
- Create to 8x8 png image with whatever color you wish for your background. I want Aqua:
Let's call the file: "BackgroundShape.png".
- Add the file to the Resource/Drawable folder.
- In Styles.xml, remove the line for the "colorBackground" attribute and instead add the following line:
- <item name="android:background">@drawable/backgroundstyle</item>
Remember this "BackgoundStyle.xml" file in Resource/Drawable folder? Thank God I didn't delete it.
- In BackgroundStyle.xml, remove the reference to our logo "mcnlogo" and instead put "backgroundshape". This will make the small PNG as our background. Then we should specify the tileMode to "repeat" in order for the image to be painted all over the Activity. And let's also make the dither attribute to "true" to enable dithering the image if it doesn't have the same pixel configuration as the screen.
So our BackgroundStyle.xml file will contain the following markup:
- <?xml version="1.0" encoding="utf-8" ?>
- <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/backgroundshape"
- android:tileMode="repeat"
- android:dither="true"/>
- Run the application:
Basically we're done. Mission accomplished, that is to have a splash screen on full screen with custom background a centered logo. So, again, if this is your goal, you can stop reading.
But, what about some "Loading..." animation? Something like this: