Search code examples
androidandroid-studioxamarinxamarin.android

How can I make an Android splash screen with text & background color that changes if my phone is in light or dark mode?


I have been working on this for some time and unfortunately I've not been able to achieve the desired effect without using an image. I have researched on Stack Overflow and almost everywhere and still found no solution that does exactly this.

What I am still trying to do is this:

  • Phone is in light mode > Splash screen has a white background with the word ABC in black in the center

  • Phone is in dark mode > Splash screen has a black background with the word ABC in white in the center

Here is what I have so far:

SplashActivity.cs

namespace Japanese.Droid
{
    [Activity(Label = "Anki+", Theme = "@style/LaunchTheme", MainLauncher = true, NoHistory = true)]
    public class SplashActivity : Activity
    {

styles.xaml

<style name="LaunchTheme" parent="Theme.AppCompat">
    <item name="android:windowBackground">@drawable/splash_screen</item>
    <item name="android:navigationBarColor">#ffffff</item>
</style>

splash_screen.xaml

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

splash_screen_night.xaml

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

splash_activity

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Views;

namespace Test.Droid
{
    [Activity(Label = "Test+", Theme = "@style/LaunchTheme", MainLauncher = true, NoHistory = true)]
    public class SplashActivity : Activity
    {

        public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
        {
            base.OnCreate(savedInstanceState, persistentState);

            //==================================== Code to hide the bottom 3 buttons on Android.
            int uiOptions = (int)Window.DecorView.SystemUiVisibility;
            uiOptions |= (int)SystemUiFlags.LowProfile;
            uiOptions |= (int)SystemUiFlags.Fullscreen;
            uiOptions |= (int)SystemUiFlags.HideNavigation;
            uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
            Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
            //===================================

            base.SetTheme(Resource.Style.MainTheme);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        }

        // Launches the startup task
        protected override void OnResume()
        {
            base.OnResume();

            //==================================== Code to hide the bottom 3 buttons on Android.
            int uiOptions = (int)Window.DecorView.SystemUiVisibility;
            uiOptions |= (int)SystemUiFlags.LowProfile;
            uiOptions |= (int)SystemUiFlags.Fullscreen;
            uiOptions |= (int)SystemUiFlags.HideNavigation;
            uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
            Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
            //===================================

            System.Threading.Tasks.Task startupWork = new System.Threading.Tasks.Task(() => { SimulateStartup(); });
            startupWork.Start();
        }


        // Simulates background work that happens behind the splash screen
        async void SimulateStartup()
        {
            await System.Threading.Tasks.Task.Delay(1000); // Simulate a bit of startup work.
            StartActivity(new Intent(Application.Context, typeof(MainActivity)));
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        public override void OnBackPressed() { }
    }
}

This uses an image but I would like to do it with text.

Does anyone know of a way to do it. I've researched this as much as possible, asked for help from two Android devs but still nobody can come up with a simple solution to do this without using an image.

Is it possible to do this with text only and not an image for my Xamarin Android application?


Solution

  • To echieve this you need to make a SplashScreen.xml in the Layout folder in Android Project. Also you need to make the styles in two folders, values and values-night.

    Also you need a separate SplashActivity.cs. I am attaching the code herewith.

    1. SplashScreen.xml

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout 
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="center_vertical" 
         android:background="#fff"
         android:id="@+id/splashview">
         <TextView
              android:id="@+id/txtAppVersion"
              android:text="Anki+"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentBottom="true"
              android:layout_marginLeft="30dp"
              android:layout_marginBottom="30dp"
              android:textColor="#000"
              android:textSize="24sp"
              android:gravity="center_vertical" 
              android:layout_centerHorizontal="true"/>
          </RelativeLayout>
      
    2. Styles.xml in values folder.

      <style name="MainTheme" parent="MainTheme.Base">
          <item name="android:textAllCaps">false</item>
      </style>
      
      <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
          <item name="windowNoTitle">true</item>
          <item name="windowActionBar">false</item>
          <item name="windowActionModeOverlay">true</item>
          <item name="elevation">0dp</item>
      </style>
      
      <style name="LaunchTheme" parent="Theme.AppCompat">
          <item name="android:windowNoTitle">true</item>
          <item name="android:windowActionBar">false</item>
          <item name="android:windowFullscreen">true</item>
          <item name="android:windowContentOverlay">@null</item>
          <item name="android:windowDisablePreview">true</item>
      </style>
      

    3. Styles.xml in values-night folder.

      <style name="MainTheme" parent="MainTheme.Base">
          <item name="android:textAllCaps">false</item>
      </style>
      
      <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
          <item name="windowNoTitle">true</item>
          <item name="windowActionBar">false</item>
          <item name="windowActionModeOverlay">true</item>
          <item name="elevation">0dp</item>
      </style>
      
      <style name="LaunchTheme" parent="Theme.AppCompat">
          <item name="android:windowNoTitle">true</item>
          <item name="android:windowActionBar">false</item>
          <item name="android:windowFullscreen">true</item>
          <item name="android:windowContentOverlay">@null</item>
          <item name="android:windowDisablePreview">true</item>
      </style>
      

    4. SplashActivity.cs

      using System;
      using Android.App;
      using Android.Content;
      using Android.Content.Res;
      using Android.OS;
      using Android.Runtime;
      using Android.Views;
      using Android.Widget;
      using Plugin.CurrentActivity;
      
      namespace MyProject.Droid
      {
          [Activity(Label = "MyProject+", Theme = "@style/LaunchTheme", 
      MainLauncher = true, NoHistory = true)]
      public class SplashActivity : Activity
      {
      
          public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
          {
              base.OnCreate(savedInstanceState, persistentState);
      
              //==================================== Code to hide the bottom 3 buttons on Android.
              int uiOptions = (int)Window.DecorView.SystemUiVisibility;
              uiOptions |= (int)SystemUiFlags.LowProfile;
              uiOptions |= (int)SystemUiFlags.Fullscreen;
              uiOptions |= (int)SystemUiFlags.HideNavigation;
              uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
              Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
              //===================================
      
              base.SetTheme(Resource.Style.MainTheme);
              Xamarin.Essentials.Platform.Init(this, savedInstanceState);
          }
      
          // Launches the startup task
          protected override void OnResume()
          {
              base.OnResume();
              SetContentView(Resource.Layout.SplashScreen);
              bool isDarkTheme;
      
              //var isDarkTheme = Preferences.Get("isDarkTheme", false);
              if (Build.VERSION.SdkInt >= BuildVersionCodes.Froyo)
              {
                  var uiModeFlags = CrossCurrentActivity.Current.AppContext.Resources.Configuration.UiMode & UiMode.NightMask;
                  if (uiModeFlags == UiMode.NightYes)
                      isDarkTheme = true;
                  else isDarkTheme = false;
              }
              else
                  isDarkTheme = false;
      
              if (isDarkTheme)
              {
                  FindViewById<RelativeLayout>(Resource.Id.splashview).SetBackgroundColor(Android.Graphics.Color.ParseColor("#000000"));
                  FindViewById<TextView>(Resource.Id.txtAppVersion).SetTextColor(Android.Graphics.Color.ParseColor("#FFFFFF"));
              }
              else
              {
                  FindViewById<RelativeLayout>(Resource.Id.splashview).SetBackgroundColor(Android.Graphics.Color.ParseColor("#FFFFFF"));
                  FindViewById<TextView>(Resource.Id.txtAppVersion).SetTextColor(Android.Graphics.Color.ParseColor("#000000"));
              }
      
              // FindViewById<TextView>(Resource.Id.txtAppVersion).Text = $"Version {PackageManager.GetPackageInfo(PackageName, 0).VersionName}";
      
              //==================================== Code to hide the bottom 3 buttons on Android.
              int uiOptions = (int)Window.DecorView.SystemUiVisibility;
              uiOptions |= (int)SystemUiFlags.LowProfile;
              uiOptions |= (int)SystemUiFlags.Fullscreen;
              uiOptions |= (int)SystemUiFlags.HideNavigation;
              uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
              Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
              //===================================
      
              System.Threading.Tasks.Task startupWork = new System.Threading.Tasks.Task(() => { SimulateStartup(); });
              startupWork.Start();
          }
      
          // Simulates background work that happens behind the splash screen
          async void SimulateStartup()
          {
              await System.Threading.Tasks.Task.Delay(1000); // Simulate a bit of startup work.
              StartActivity(new Intent(Application.Context, typeof(MainActivity)));
          }
      
          public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
          {
              Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
              base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
          }
      
          public override void OnBackPressed() { }
      }
      }