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