Xamarin.Forms Splashscreen in Android

Hi, In Forms how to add SplashScreen to Android appliaction? Thanks in advance.

«1

Posts

  • MihaMarkicMihaMarkic SI ✭✭✭✭

    Out of curiosity, why are you calling Finish in SplashActivity?

  • DanielLDanielL PLInsider ✭✭✭✭
    edited July 2014

    @MihaMarkic Good catch, with NoHistory = true attribute set on SplashActivity, there's no need to call Finish, activity is automatically finished when another one is opened.

  • RaviKumarGNRaviKumarGN USMember

    Thank you DanielL, you solution is working.

  • GrahamMcDonaldGrahamMcDonald CHMember, University

    Being new to Xamarin development and just finishing off my first Xamarin.Forms app I have just a small question :-)

    What screen resolutions do I need to support and where should they be setup?

    many thanks in advance on this one - this is my last nut to crack!

  • GrahamMcDonaldGrahamMcDonald CHMember, University

    A couple of small things -
    1. the SplashScreen.cs goes in the Forms portable or Android project?
    2. the SplashScreen ctor gets called via the SetPage redirection to the portable project?
    3. the graphic is an Image in the SplashScreen.xaml or a resource defined elsewhere (see first question)?

    Basically I am not sure how the sequence of event works here.

  • DanielLDanielL PLInsider ✭✭✭✭
    edited October 2014

    @GrahamMcDonald‌

    1. SplashScreen.cs goes into an Android Project, as all other Android specific files.
    2. Yes, here: SetPage(App.GetMainPage()); - GetMainPage returns new instance of the SplashScreen Activity
    3. SplashScreen.xml is a definition of a bitmap (you can tune size, centering, etc) which includes custom drawable (@drawable/icon). You can also change it to any custom canvas or drawable (http://developer.android.com/guide/topics/graphics/2d-graphics.html)

    What screen resolutions do I need to support and where should they be setup?

    You should do exactly the same as any native Android App: http://developer.android.com/guide/practices/screens_support.html

    If there's no resource for a specific device size - it is scaled (up/ down).

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:

    Hi Daniel
    First, thanks a lot that you have posted your implementation here…
    I am trying to implement a splash screen in the Android-project of my XF-App (according to your description) and have some problems (as I have no experience with Android).

    Note: I don’ have used a theme in my android-project until now.
    Therefore, I don’t have an entry Theme="@android:style/Theme.Holo", in my MainActivity.cs

    I have now:

    • Added an Image (to show at startup) named SplashScreen.png to my \Resources\-Folder in the Android-project
    • created a SplashScreen.cs file in the root of my XF-Android-project (Changed “MyApp” with the real name of my app ;-)
    • Leaved ,Theme = "@style/Theme.Splash” from your example
    • Created a new folder \Resources\Values\ (I think, you mean \Resources\Values\Styles.xml), if you write Resources.Values.Styles.xml)?
    • Created a new file “Styles.xml” in this folder (overtake your example in the Styles.xml file)

    If I try to compile, I have the error:
    No resource found that matches the given name (at 'android:windowBackground' with value ' @Drawable/SplashScreen
    I also have tried to change SplashScreen to SplashScreen.png - same error-message
    Not sure, if the image is not found, or ‘android:windowBackground' is not found...?

    If I try to add also the SplashScreen.xml (in the \Resources\Drawable-folder), I have and additional error-message “Resource entry splashscreen is already defined.” To the SplashScreen.xml-file.

    As I don’t see the context of the files (which of the files I really need), I'm also cannot see, where the problem lies.

    I specially also don’t see the link to the image in your example (or does the image in your example don’t have a file-extension / does the reference to the image have to be wrote without extension for a special reason?)

    Can you please bring some light in my darkness and tell me, what I have to do, to bring the SplashScreen to work…?

    Thanks very much for your help!

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    Update:
    I have changed the image-name and also the path to the image to lowercase (although my drawable-folder has uppercase (\Drawable):

    <item name="android:windowBackground">
          @drawable/splashscreen
    

    Now, I am able to compile and debug (without SplashScreen.xlm), but.. my app is deployed two times to the device now (one time with splashscreen, one time without)... very strange...!
    Also the image is stretched what looks terrible (I think (hope) that there are some settings, how to display the image (aspect-ration, etc.).

    Daniel: Do you have an idea, what can cause the "dual-deployment" (both icons are removed first by deploy and the copied once again)?

  • DanielLDanielL PLInsider ✭✭✭✭

    @FredyWenger‌
    Yes, theme Theme.Splash should be in Resources->values->Styles.xml

    Resources.Drawable.SplashScreen.xml is very important. It is used in Theme.Splash definition. And prevents image from stretching!!! (centers it)

    Check if your resources file have Build Action set to AndroidResource it is also very important.

    but.. my app is deployed two times to the device now (one time with splashscreen, one time without)... very strange...!

    Check SplashScreen and MainMenu activity attributes. You probably have MainLauncher set to true on both of them.

    SplashScreen.cs:

    [Activity(Label = "MyApp", MainLauncher = true, NoHistory = true, Theme = "@style/Theme.Splash", 
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    

    MainActivity.cs:

    [Activity(Label = "MyApp", Theme="@android:style/Theme.Holo", 
    ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    
  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:
    Thanks for your (fast) reply .-)
    Both: my "real" splashscreen(.png) and splashscreen.xml are marked as AndroidResource.
    In both .cs-files (SplashScreen.cs and MainActivity.cs) the option MainLauncher = true is included.
    But in MainActivity.cs, I don't have included Theme="@android:style/Theme.Holo"
    Do I really need this (I think, this is for the whole app and I don't want a theme)?
    As soon as I include splashscreen.xml in the project, I have the error "Resource entry splashscreen is already defined."
    Note: The image splashscreen.png and also splashscreen.xml are stored in the resources-Folder (same name, but different extension).
    As I wrote in my posting, I don't see the real link in your example to the image...?
    Thanks for a further reply...

  • DanielLDanielL PLInsider ✭✭✭✭

    @FredyWenger‌

    In both .cs-files (SplashScreen.cs and MainActivity.cs) the option MainLauncher = true is included.

    This is wrong. It should only be in SplashScreen.cs.

    As soon as I include splashscreen.xml in the project, I have the error "Resource entry splashscreen is already defined."

    As the error states, you have duplicate definitions! Try searching in drawable-hdpi, drawable-mdpi etc folders. It should only be in drawable" folder.

    Note: The image splashscreen.png and also splashscreen.xml are stored in the resources-Folder (same name, but different extension).

    Change the name of splashscreen.png to something else.

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭
    edited November 2014

    @DanielL:
    It seems, as the MainLauncher = true has caused the double install (I have removed it now from the MainActivity.cs and it seems, as this problem has gone:-)
    I don't have any duplicate definitions in any subfolder...
    But.. as I wrote... the splashscreen.xml and my (real) image splashscreen.png have the same name but another extension and I think, this causes the problem.
    But... I think I see now the (my) confusion:
    In your example, you have:
    android:src="@drawable/icon

    I think' that's the (my) "missing link" from SplashScreen.xml to the real image (in your project named Icon)

    So.. I have changed the name of my image from SplashScreen.png to AndroidSplashScreen.png, changed
    android:src="@drawable/icon to android:src="@drawable/AndroidSplashScreen.png and now...
    ...all seems to work (including not to stretch the image, if I start the app in landscape-orientation:-))

    So thank you very much, for your help!

    And.. for other newbies (like me;-):
    Resources.Drawable.SplashScreen.xml means \Resources\Drawable\SplashScreen.xml (for all files in example)
    If you don't have already a subfolder \Resources\Values (for Resources.Values.Styles.xml) you have to create it.
    You don't have to add the Theme="@android:style/Theme.Holo", in your MainActivity.cs (if you don't have it already / if you don't want it)
    In your files, always write drawable lowercase (also, if your folder in real world is named with uppercase (\Drawable)
    In your MainActivity.cs you have to remove MainLauncher = true as soon as you activate your SplashScreen.cs with MainLauncher = true (else your app will be "doubled" by deploying to the device).

    Finally once more: thanks a lot Daniel - you have helped me (and I think many other developers) al lot with your posting!

  • DanielLDanielL PLInsider ✭✭✭✭
    edited November 2014

    @FredyWenger‌ Not a problem! It's nice to hear it's working now ;)

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:
    I have a last question - maybe you can help "in short".
    If not, I will post the question in the Android-forum (so that you don't have to waste your time;-)

    As I wrote, the SplashScreen works now as expected - I only have a small issue.
    If I also can fix this small issue, the SplashScreen will work perfectly for me.
    Issue short-description:
    I know, that I should create various images for various device-sizes and device-resolutions, to have a "perfect look" on any device. But I don't have the time to create the images now and - I think - also the size of the final app then will increase much... so - at least for now - I want to include a single image to display on all devices.
    My main goal is, that a "viewable" Image is displayed by start of the app (instead of a "black screen".
    Therefore, I have taken my (already existing) splash-screen for iOS (IPhone) also for Android.
    This works fine (Android-Phone, Android-Tablet) with one small issue:

    • If I start the App on my tablet (Samsung SM-T900) in portrait-orientation:

      • The image is scaled (zoomed) with the correct aspect-ratio and showed centered (also the quality is O.K.)
        => Perfect!
    • If I start the App on my tablet (Samsung SM-T900) in landscape-orientation:

      • the images is showed in correct aspect-ratio centered in the screen (what is correct), but not scaled, so that the image is cut (not the whole image is showed)

    In addition to your example, I have added
    android:adjustViewBounds="true" (as this - according to the Android-description, I found here
    developer.android.com/reference/android/R.attr.html#adjustViewBounds,
    should "adjust the ImageView to its bounds to preserve the aspect ratio of its drawable"...
    Unfortunately, it seems, as this option don't change the behavior (maybe not together with the other "gravity-options"?).

    My whole SplashScreen.xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
      android:src="@drawable/AndroidSplashScreen"
      android:gravity="center"
      android:adjustViewBounds="true"
      android:layout_gravity="center"/>
    

    Question:
    Don you have an idea, how I can reach my goal (center the image, size the image to the available space by keeping the aspect-ratio)..?

    If not... no problem - I will post the question in the Android-Forum...
    Thanks for a short replay...

  • DanielLDanielL PLInsider ✭✭✭✭

    @‌FredyWenger
    If you want to provide only one drawables size it is recommended to put them into "drawable-xxhdpi" folder (480dpi). You could also experiment with adding "drawable-land-xxhdpi" which is only used in landscape modes.

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:
    Thanks for your reply.. but does this change the behavior of how the image is scaled generally (phone/tablet...portrait(landscape..?).
    As I wrote, the quality is O.K. for me (an for now), the only problem is, that the image isn't scaled down, if the resolution (height) is to small...
    I thought (hoped), that there should be another "property" in SplashScreen.xml (or some combination of properties)?

  • DanielLDanielL PLInsider ✭✭✭✭
    edited November 2014

    Yes, It should scale images down.

    XXHDPI to XHDPI and lower

    XHDPI to HDPI and lower

    and so on...

    Scaling factors are:

    ldpi = 0.00625 * 120 -> 0.75

    mdpi = 0.00625 * 160 -> 1.0

    hdpi = 0.00625 * 240 -> 1.5

    xhdpi = 0.00625 * 320 -> 2.0

    xxhdpi = 0.00625 * 480 -> 3.0

    xxxhdpi = 0.00625 * 640 -> 4.0

    If you use default "drawable" folder it is scaled as it was MDPI (almost, with some exceptions etc) and if your device is >MDPI (almost all devices now) it probably won't be scaled down

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:
    Thanks a lot... I will check it out... :-)

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @Daniell:
    I now have:

    • created a high-density image
    • created a folder \drawable-xxhdpi\ (parallel to the existing folder \drawable\
    • changed (in SplashScreen.xml -> stored in \drawable):

    android:src="@drawable-xxhdpi/AndroidSplashScreen"

    Note: The file is named AndroidSplashScreen.png (it seems, as the extension doesn't matter here) .
    The problem is, that the .png isn't found....
    Error-message:

    No resource found that matches the given name (at 'src' with value '@drawable-xhdpi/AndroidSplashScreen')

    The image is marked as AndroidResource...
    The spelling is correct....
    What can this be...?

    Thanks a lot...

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    Update to my last post:
    If I leave the src= to @drawable (as it was before) and only additionally include the new folder with the new .png:

    • the deploy to my tablet works:

      • the new image is used automatically
      • but the image is not scaled (cut on all sides)
    • the deploy to my phone (ZWX C2) crashes (reboot of phone)

  • DanielLDanielL PLInsider ✭✭✭✭

    You're doing it wrong, don't do anything like
    android:src="@drawable-xxhdpi/AndroidSplashScreen"
    Android automatically chooses folder to suit your device, don't add any xxhdpi etc

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @Daniell:
    I have seen that (see "Update to my last post") .
    As I wrote, with the new \drawable-xxhdpi-folder and the hi-res image:

    • I can deploy to my tablet, the new image is taken, but not downscaled
      => Your wrote in your earlier posting, that the image should be downscaled

      => Do I missing something?

    • I can deploy to the ZWX C2 Android-Phone
      => If the app then is started (by debugger or from phone), the app crashes hard and reboot the device
      => I think, it is not able to show the image what causes the crash
      => I wonder, that this happens as the old (smaller) version of the image further is stored under \drawable\ and
      android should take the smaller image automatically...?
      ==> Do you have an idea what can cause the hard-crash (with reboot)...?

  • DanielLDanielL PLInsider ✭✭✭✭
    edited December 2014

    Hello @FredyWenger‌,

    Please read this:

    http://developer.android.com/guide/practices/screens_support.html

    http://developer.android.com/design/style/devices-displays.html

    In Xamarin.Android (and also Xamarin.Forms for Android), it's exactly the same. There is a lot of useful informations there.

  • nbevansnbevans USMember ✭✭✭

    Splash screens aren't good practice. Any time you have a SplashScreenActivity, especially with some sort Thread.Sleep happening, you should think twice.

    The proper way to do splash screen on Android is to provide a 9-patch image that can be displayed by the app's Zygote process during startup. Read about the Zygote process on Android to know more.

  • DanielLDanielL PLInsider ✭✭✭✭

    @nbevans‌ Isn't it what we are using here? (With a difference that we're using bitmap instead of 9patch and using another activity for splash, which we can change to only using MainActivity with SetTheme method in OnCreate()). Can you post some details?

    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 :

    Create a small theme which a custom window background displaying your splash info (you can use 9-patch to center unscaled content);
    In your manifest, use this splash theme for your activity;
    in your activity's onCreate() method, call setTheme(R.id.yourActivityTheme) (call it before setContentView() );
    enjoy...
    That way, your "splash screen" (ie : the zygote with your splash theme) will be visible until your activity is ready to be displayed.

  • DanielLDanielL PLInsider ✭✭✭✭

    @nbevans‌ So the difference from my earlier example is not using separate activity for splash but changing theme in OnCreate method? Nice approach. It can be less resource consuming to avoid using separate activity for a splash.

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL:
    Thanks for your input. I have read the information's behind your links before and unfortunately don't found any clear information's.
    What I want (try to reach), is to include a (one) Image in my app, that is displayed as splash-screen and is scaled at runtime.
    "Scaled" = centered on screen, downscaled (= whole image is visible, nothing cut) with the correct aspect ratio.
    According to your postings, I hoped, exactly that should be possible with a (one) xxhdpi-image.
    As I wrote:

    • on tablet-device, the xxhdpi-image is showed with correct aspect-ration but not scaled (=no solution for me)
    • on phone-device, the phone (not only the app) crashes, if i include the xxhdpi-image in project (= now solution for me)
      => It seems, as it (unfortunately) is not possible, to scale the image correct in Android.- :-(
      I hoped, that there would be some special settings (that I don't have found until now), that are doing the job...
      @nbevans‌:
      Thanks also for your reply.
      If I understand your post correct, you say, that the splashscreen (with this implementation) also can be displayed (unwanted) by other events (Thread.Sleep).
      Do I understand you correct?

    Create a small theme which a custom window background displaying your splash info (you can use 9-patch to center unscaled content);

    "Unscaled content" means, that a large (e.g. xxhdpi)-image is not scaled (with correct aspect ratio) to fit the available page-space?

  • nbevansnbevans USMember ✭✭✭

    @DanielL yeah and it also saves a bunch of work with "forwarding" new intents onto the MainActivity.

  • DanielLDanielL PLInsider ✭✭✭✭
    edited December 2014

    @nbevans‌ I'll definitely try it!

    @FredyWenger‌ It's possible. On solution is to use only xxhdpi drawable, then:

    SplashScreen.xml

        <?xml version="1.0" encoding="utf-8" ?>
        <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
          android:src="@drawable/AndroidSplashScreen"
          android:gravity="center"
          android:adjustViewBounds="true"
          android:layout_gravity="center"/>
    

    Create few versions of SplashScreen.xml (in hdpi, xhdpi, xxhdpi, etc folders) and modifying them to use ScaleDrawable (http://developer.android.com/reference/android/graphics/drawable/ScaleDrawable.html) or something similar with appropriate scaling set for each of device screen sizes.

    SplashScreen.xml is responsible for how you'll render your bitmap.

    BTW: In my opinion it is better to create different sized bitmaps for each device size (performance!)

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @DanielL (and @ all others that want only one splash-screen for Android)

    I heave searched now the Internet for hours and have tried all suggested versions of parameter-combinations... nothing have worked...
    It's unbelievable, how many options (and combinations!) exits for Android and how bad basic needs (use one image, scale it in the correct apspect ratio in the available space of the device) are described...
    I was minutes away to give up...
    Now, I have found a configuration, that works for me:

    <?xml version="1.0" encoding="utf-8" ?>
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
     android:src="@drawable/AndroidSplashScreen"
     android:gravity="clip_horizontal|clip_vertical" 
     />
    

    The "trick" is, to use "clip_horizontal|clip_vertical" in one option and don't use any other option.
    Now, the image is scaled in (almost -> not 100%) correct aspect-ratio to fit the height and width of the device-screen.
    As I wrote, I have only ONE image in the drawable folder (Image in portrait-orientation, 776 KB, 640 x 1135).
    Note:
    As soon, as I include the hires-version (folder \drawable-xxhdpi\ parallel to drawable):

    • The phone is crashing (very) hard => reboot of device
    • The tablet then is using the hires-version of the image, but does not scale it correct (although, I have placed a
      SplashScreen.xml also in the \drawable-xxhdpi-folder)

    So... I finally have a solution, that works for me (not optimal, but acceptable for now -> maybe I later will try to optimize it).

    Finally many thanks to Daniel Luberda for the information's how to implement an Android splash-screen:-).

    I hope, this posting help some other developers...

  • CybrosysCybrosys USMember ✭✭
    edited December 2014

    I'm using the same splash screen pattern except that I have 1 splash screen and 2 possible starting routes. One of these routes have NoHistory = false because it's the main app. The problem I have is that you can get back to the splash screen due to actions in the main app such as clearing your credentials.

    I'm using Finish() when starting the splash activity but for some reason it is possible to use the back button to navigate back to the main app from the splash screen when you cleared your credentials.

    So yeah, Finish does not work because it doesn't remove the current Activity from the navigation stack.

  • nbevansnbevans USMember ✭✭✭

    @Cybrosys The solution I posted is the proper way of doing things.

  • CybrosysCybrosys USMember ✭✭
    edited December 2014

    I haven't been clear but my app needs to be able to switch the root page and remove any navigation history, which I've just achieved using multiple Activities, some with NoHistory = true and others with NoHistory = false. When navigation from a NoHistory = false activity to a NoHistory = true activity I need to call SetFlags on the Intent:
    SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

    This removes the NoHistory = false task from the navigation stack, so when back is pressed the app closes instead of going back to the previous activity.

  • CybrosysCybrosys USMember ✭✭

    @DanielL‌ thanks for the info. I solved it by having NoHistory = true and when I start those activities with an Intent I set two flags on the intent: SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

  • DanielLDanielL PLInsider ✭✭✭✭

    @Cybrosys‌ Sorry, I didn't notice your second post.

  • About @Daniell solution, does anybody facing issues when hiding the application? It's throwing an exception on event "OnDestroy": UnhandledException_internal

    Here is an attached project wich reproduces the error.

  • DanielLDanielL PLInsider ✭✭✭✭
    edited January 2015

    @Alexandrem‌ Yeap (I think it's a bug). When you minimize app and reopen it through Android Task Manager. Take a look at: http://forums.xamarin.com/discussion/comment/89844/#Comment_89844

«1
Sign In or Register to comment.