0
votes

In our Xamarin Android app we want our splash screen to load a custom image from the app properties (or some other storage mechanism). Therefor the image is not available as a Android resource in the APK (compile time). I can replace the window background using Window.SetBackgroundDrawable(Resources, Drawable) in the Activity, but then the background is only applied when loading is almost complete. If I configure the a similar background image directly (but static) in the drawable XML it is loaded fast and properly.

Any ideas on how to show the image in a timely fashion?

Our splash screen drawable:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <color android:color="@color/splash_background"/>
  </item>
  <item>
    <bitmap
      android:src="@drawable/splash"
      android:tileMode="disabled"
      android:gravity="center"/>
  </item>
</layer-list>

Our splash theme:

<style name="CompanySplashTheme" parent ="Theme.AppCompat.Light.NoActionBar">
  <item name="android:windowBackground">@drawable/splash_screen</item>
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowFullscreen">true</item>
</style>

Activity:

using System.Text;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Graphics.Drawables;
using Android.Support.V7.App;

namespace Provisior.Mobile.Droid
{
    [Activity(Theme = "@style/CompanySplashTheme", MainLauncher = true, NoHistory = true)]
    public class SplashActivity : AppCompatActivity
    {
        protected override void OnResume()
        {
            base.OnResume();
            ReplaceBackground();
            new Task(() => StartActivity(new Intent(Application.Context, typeof(MainActivity)))).Start();
        }

        private void ReplaceBackground()
        {
            var imageBytes = Encoding.UTF8.GetBytes(App.Current.Properties["splash_background"] as string);
            var backgroundBitmap = global::Android.Graphics.BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
            var backgroundDrawable = new BitmapDrawable(Resources, backgroundBitmap);
            Window.SetBackgroundDrawable(backgroundDrawable);
        }

        public override void OnBackPressed() { }
    }
}
1
Using a "static" resource via a theme will always be faster... Instead of storing a bitmap as a string in app properties, and then getting those utf8 bytes, decoding that to a bitmap, converting that to a drawable, etc... just store the actual bitmap file in the cache directory and load that.... - SushiHangover
@SushiHangover Thnx. Noted, but even when I retrieve the drawable with GetDrawable(Resources, Resourse.Drawable.background) the problem persists. You also say that a static resource will always be faster, but we are talking milliseconds here, right? Not seconds? - Twan
we are talking milliseconds here, right? Not seconds? That really depends upon the image, device, etc... also Themes/Resources/Drawables are highly optimized (build/compile time and runtime) - SushiHangover
also Themes/Resources/Drawables are highly optimized (build/compile time and runtime) Any way to optimize the image in the same way? The same image is loaded in a split second when directy defined in a layer-list xml file. So, layer-list with drawable loaded by the Android framework is faster than just that same drawable set with Window.SetBackgroundDrawable in OnCreate. That sounds strange to me. - Twan
It might has something to do with the .NET runtime. When setting a breakpoint on the first line of OnCreate in my activity I see that the drawable as defined in XML is rendered immediately, but the breakpoint is only hit after a bunch of assemblies have been loaded. - Twan

1 Answers

1
votes

Put ReplaceBackground() for changing your background to the splash in the onCreate() method of the activity.

edit: just realized it wasn't java, answer still applies