Search Unity

Android Status bar icons color in fullscreen mode

Discussion in 'Android' started by areavisuale, Sep 2, 2021.

  1. areavisuale

    areavisuale

    Joined:
    Jul 23, 2015
    Posts:
    60
    I tried everything but I cannot able to change the color of the Android status bar icons color. I want the icons to be black with transparent background when I'm in fullscreen immersive mode, but they're always white. I'm using an old StatusBarChanger.cs code to hide/show the status bar at runtime (in my case show only when I have devices with notch), but there isn't any option to change the color. My app has white background, so I need the icons to be dark.
    Any suggestions?
     
  2. areavisuale

    areavisuale

    Joined:
    Jul 23, 2015
    Posts:
    60
    I post my solution, because I struggled many hours to find it...
    I had to modify the AndroidManifest declaring a custom theme like this:

    android:theme="@StyLe/UnityTransparentStatusBarTheme">

    and then I had to create a values-v23.xml file inside Plugin->Android->res->values-v23 folder.

    The xml is this:

    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <resources>
    3.     <style name="UnityTransparentStatusBarTheme" parent="UnityThemeSelector">
    4.       <item name="android:windowLightStatusBar">true</item>
    5.       <item name="android:colorPrimaryDark">#00BB86FC</item>
    6.   </style>
    7. </resources>
    android:windowLightStatusBar (only available from sdk 23) make the status bar icons dark
    android:colorPrimaryDark defines the color of the background, #00 is full transparency
     
  3. DavidLTP

    DavidLTP

    Joined:
    Dec 2, 2020
    Posts:
    6
    what unity version did you use? I'm struggling to get it working since unity says that declaring resources in res/values is deprecated. Do you have any solution?
     
  4. buraakd

    buraakd

    Joined:
    Aug 5, 2021
    Posts:
    3
    Weird because it is not solved. Now i am also looking for its solution
     
  5. unity_Iamtuh8VRCw_Zg

    unity_Iamtuh8VRCw_Zg

    Joined:
    Feb 7, 2023
    Posts:
    1
    Any update about this? I have the same problem, i need dark icons on a white background.. I manage to change the background to white using https://github.com/zeh/unity-tidbits/blob/master/application/ApplicationChrome.cs, but icons are still white.

    i tried this snippet of code(Android code), that i found on https://copyprogramming.com/howto/s...bar-and-flag_translucent_status-is-deprecated

    Code (CSharp):
    1.  
    2. Window window = getWindow();
    3. View decorView = window.getDecorView();
    4. WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(window, decorView);
    5. wic.setAppearanceLightStatusBars(true); // true or false as desired.
    6.  
    using unity calls to android, adding this code in ApplicationChrome.cs and calling it in another script
    Code (CSharp):
    1.  
    2. private static void applyLightNavbarThemeAndroid()
    3. {
    4.           runOnAndroidUiThread(applyLightNavbarThemeAndroidInThread);
    5. }
    6.  
    7. private static void applyLightNavbarThemeAndroidInThread() {
    8.    using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    9.    {
    10.        using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
    11.        {
    12.            using (var window = activity.Call<AndroidJavaObject>("getWindow"))
    13.            {
    14.                using(var decorView = window.Call<AndroidJavaObject>("getDecorView"))
    15.                {
    16.                    using(var wic = new AndroidJavaObject("WindowInsetControllerCompat", window, decorView)) {
    17.                         wic.Call<AndroidJavaObject>("setAppearanceLightStatusBars", true);
    18.                    }
    19.                }
    20.            }
    21.        }
    22.    }
    23. }
    24.  
    but doesn't work..

    I'm using Unity 2021.3.18f1 and minimum android API level 30
     
    Last edited: Dec 12, 2023
  6. DavidLTP

    DavidLTP

    Joined:
    Dec 2, 2020
    Posts:
    6
    Any update? Still not resolved.
     
  7. DavidLTP

    DavidLTP

    Joined:
    Dec 2, 2020
    Posts:
    6

    So after a lot of research... I managed to change the status bar icons color from black to white and from white to black by modifying the ApplicationChrome script. Here is the full code:

    Code (CSharp):
    1.  
    2.  
    3. #if UNITY_ANDROID && !UNITY_EDITOR
    4. #define USE_ANDROID
    5. #endif
    6. using System;
    7. using System.Collections.Generic;
    8. using UnityEngine;
    9. /**
    10.  * @author zeh fernando
    11.  */
    12. class ApplicationChrome
    13. {
    14.     /**
    15.     * Manipulates the system application chrome to change the way the status bar and navigation bar work
    16.     *
    17.     * References:
    18.     * . http://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int)
    19.     * . http://forum.unity3d.com/threads/calling-setsystemuivisibility.139445/#post-952946
    20.     * . http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_LAYOUT_IN_SCREEN
    21.     **/
    22.     // Enums
    23.     public enum States
    24.     {
    25.         Unknown,
    26.         Visible,
    27.         VisibleOverContent,
    28.         TranslucentOverContent,
    29.         Hidden
    30.     }
    31.     // Constants
    32.     private const uint DEFAULT_BACKGROUND_COLOR = 0xff000000;
    33. #if USE_ANDROID
    34.         // Original Android flags
    35.         private const int VIEW_SYSTEM_UI_FLAG_VISIBLE = 0;                    // Added in API 14 (Android 4.0.x): Status bar visible (the default)
    36.         private const int VIEW_SYSTEM_UI_FLAG_LOW_PROFILE = 1;                // Added in API 14 (Android 4.0.x): Low profile for games, book readers, and video players; the status bar and/or navigation icons are dimmed out (if visible)
    37.         private const int VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2;            // Added in API 14 (Android 4.0.x): Hides all navigation. Cleared when theres any user interaction.
    38.         private const int VIEW_SYSTEM_UI_FLAG_FULLSCREEN = 4;                // Added in API 16 (Android 4.1.x): Hides status bar. Does nothing in Unity (already hidden if "status bar hidden" is checked)
    39.         private const int VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE = 256;            // Added in API 16 (Android 4.1.x): ?
    40.         private const int VIEW_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512;    // Added in API 16 (Android 4.1.x): like HIDE_NAVIGATION, but for layouts? it causes the layout to be drawn like that, even if the whole view isn't (to avoid artifacts in animation)
    41.         private const int VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024;        // Added in API 16 (Android 4.1.x): like FULLSCREEN, but for layouts? it causes the layout to be drawn like that, even if the whole view isn't (to avoid artifacts in animation)
    42.         private const int VIEW_SYSTEM_UI_FLAG_IMMERSIVE = 2048;                // Added in API 19 (Android 4.4): like HIDE_NAVIGATION, but interactive (it's a modifier for HIDE_NAVIGATION, needs to be used with it)
    43.         private const int VIEW_SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096;        // Added in API 19 (Android 4.4): tells that HIDE_NAVIGATION and FULSCREEN are interactive (also just a modifier)
    44.         private static int WINDOW_FLAG_FULLSCREEN = 0x00000400;
    45.         private static int WINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;
    46.         private static int WINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100;
    47.         private static int WINDOW_FLAG_TRANSLUCENT_STATUS = 0x04000000;
    48.         private static int WINDOW_FLAG_TRANSLUCENT_NAVIGATION = 0x08000000;
    49.         private static int WINDOW_FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000; // Added in API 21 (Android 5.0): tells the Window is responsible for drawing the background for the system bars. If set, the system bars are drawn with a transparent background and the corresponding areas in this window are filled with the colors specified in getStatusBarColor() and getNavigationBarColor()
    50.         // Add the SYSTEM_UI_FLAG_LIGHT_STATUS_BAR flag
    51.         private const int VIEW_SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192;
    52.         // Current values
    53.         private static int systemUiVisibilityValue;
    54.         private static int flagsValue;
    55. #endif
    56.     // Properties
    57.     private static States _statusBarState;
    58.     private static States _navigationBarState;
    59.     private static uint _statusBarColor = DEFAULT_BACKGROUND_COLOR;
    60.     private static uint _navigationBarColor = DEFAULT_BACKGROUND_COLOR;
    61.     private static bool _isStatusBarTranslucent; // Just so we know whether its translucent when hidden or not
    62.     private static bool _isNavigationBarTranslucent;
    63.     private static bool _dimmed;
    64.     private static bool _statusbar_light_mode;
    65.     // ================================================================================================================
    66.     // INTERNAL INTERFACE ---------------------------------------------------------------------------------------------
    67.     static ApplicationChrome()
    68.     {
    69.         applyUIStates();
    70.         applyUIColors();
    71.     }
    72.     private static void applyUIStates()
    73.     {
    74. #if USE_ANDROID
    75.             applyUIStatesAndroid();
    76. #endif
    77.     }
    78.     private static void applyUIColors()
    79.     {
    80. #if USE_ANDROID
    81.             applyUIColorsAndroid();
    82. #endif
    83.     }
    84. #if USE_ANDROID
    85.         private static void applyUIStatesAndroid() {
    86.             int newFlagsValue = 0;
    87.             int newSystemUiVisibilityValue = 0;
    88.             // Apply dim values
    89.             if (_dimmed) newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LOW_PROFILE;
    90.             // Apply color values
    91.             if (_navigationBarColor != DEFAULT_BACKGROUND_COLOR || _statusBarColor != DEFAULT_BACKGROUND_COLOR) newFlagsValue |= WINDOW_FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
    92.             // Apply status bar values
    93.             switch (_statusBarState) {
    94.                 case States.Visible:
    95.                     _isStatusBarTranslucent = false;
    96.                     newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN;
    97.                     break;
    98.                 case States.VisibleOverContent:
    99.                     _isStatusBarTranslucent = false;
    100.                     newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN;
    101.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    102.                     break;
    103.                 case States.TranslucentOverContent:
    104.                     _isStatusBarTranslucent = true;
    105.                     newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN | WINDOW_FLAG_TRANSLUCENT_STATUS;
    106.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    107.                     break;
    108.                 case States.Hidden:
    109.                     newFlagsValue |= WINDOW_FLAG_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN;
    110.                     if (_isStatusBarTranslucent) newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_STATUS;
    111.                     break;
    112.             }
    113.             if (_statusbar_light_mode)
    114.                 newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
    115.             // Applies navigation values
    116.             switch (_navigationBarState) {
    117.                 case States.Visible:
    118.                     _isNavigationBarTranslucent = false;
    119.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE;
    120.                     break;
    121.                 case States.VisibleOverContent:
    122.                     // TODO: Side effect: forces status bar over content if set to VISIBLE
    123.                     _isNavigationBarTranslucent = false;
    124.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE | VIEW_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
    125.                     break;
    126.                 case States.TranslucentOverContent:
    127.                     // TODO: Side effect: forces status bar over content if set to VISIBLE
    128.                     _isNavigationBarTranslucent = true;
    129.                     newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_NAVIGATION;
    130.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE | VIEW_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
    131.                     break;
    132.                 case States.Hidden:
    133.                     newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_FULLSCREEN | VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION | VIEW_SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
    134.                     if (_isNavigationBarTranslucent) newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_NAVIGATION;
    135.                     break;
    136.             }
    137.             if (Screen.fullScreen) Screen.fullScreen = false;
    138.             // Applies everything natively
    139.             setFlags(newFlagsValue);
    140.             setSystemUiVisibility(newSystemUiVisibilityValue);
    141.         }
    142.         private static void runOnAndroidUiThread(Action target) {
    143.             using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    144.                 using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
    145.                     activity.Call("runOnUiThread", new AndroidJavaRunnable(target));
    146.                 }
    147.             }
    148.         }
    149.         private static void setSystemUiVisibility(int value) {
    150.             if (systemUiVisibilityValue != value) {
    151.                 systemUiVisibilityValue = value;
    152.                 runOnAndroidUiThread(setSystemUiVisibilityInThread);
    153.             }
    154.         }
    155.         private static void setSystemUiVisibilityInThread() {
    156.             using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    157.                 using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
    158.                     using (var window = activity.Call<AndroidJavaObject>("getWindow")) {
    159.                         using (var view = window.Call<AndroidJavaObject>("getDecorView")) {
    160.                             // We also remove the existing listener. It seems Unity uses it internally
    161.                             // to detect changes to the visibility flags, and re-apply its own changes.
    162.                             // For example, if we hide the navigation bar, it shows up again 1 sec later.
    163.                             //view.Call("setOnSystemUiVisibilityChangeListener", null);
    164.                             int currentSystemUiVisibility = view.Call<int>("getSystemUiVisibility");
    165.                             // Set the SYSTEM_UI_FLAG_LIGHT_STATUS_BAR flag
    166.                             //if (statusbar_light_mode) {
    167.                             //    view.Call("setSystemUiVisibility", currentSystemUiVisibility | VIEW_SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    168.                             //    Debug.Log("light mode");
    169.                             //    }
    170.                             //else
    171.                                 //view.Call("setSystemUiVisibility", systemUiVisibilityValue);
    172.                                 //| VIEW_SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
    173.                             view.Call("setSystemUiVisibility", systemUiVisibilityValue);
    174.                         }
    175.                     }
    176.                 }
    177.             }
    178.         }
    179.         private static void setFlags(int value) {
    180.             if (flagsValue != value) {
    181.                 flagsValue = value;
    182.                 runOnAndroidUiThread(setFlagsInThread);
    183.             }
    184.         }
    185.         private static void setFlagsInThread() {
    186.             using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    187.                 using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
    188.                     using (var window = activity.Call<AndroidJavaObject>("getWindow")) {
    189.                         window.Call("setFlags", flagsValue, -1); // (int)0x7FFFFFFF
    190.                     }
    191.                 }
    192.             }
    193.         }
    194.         private static void applyUIColorsAndroid() {
    195.             runOnAndroidUiThread(applyUIColorsAndroidInThread);
    196.         }
    197.         private static void applyUIColorsAndroidInThread() {
    198.             using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    199.                 using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
    200.                     using (var window = activity.Call<AndroidJavaObject>("getWindow")) {
    201.                         //Debug.Log("Colors SET: " + _statusBarColor);
    202.                         window.Call("setStatusBarColor", unchecked((int)_statusBarColor));
    203.                         window.Call("setNavigationBarColor", unchecked((int)_navigationBarColor));
    204.                     }
    205.                 }
    206.             }
    207.         }
    208. #endif
    209.     // ================================================================================================================
    210.     // ACCESSOR INTERFACE ---------------------------------------------------------------------------------------------
    211.     public static States navigationBarState
    212.     {
    213.         get { return _navigationBarState; }
    214.         set
    215.         {
    216.             if (_navigationBarState != value)
    217.             {
    218.                 _navigationBarState = value;
    219.                 applyUIStates();
    220.             }
    221.         }
    222.     }
    223.     public static States statusBarState
    224.     {
    225.         get { return _statusBarState; }
    226.         set
    227.         {
    228.             if (_statusBarState != value)
    229.             {
    230.                 _statusBarState = value;
    231.                 applyUIStates();
    232.             }
    233.         }
    234.     }
    235.     public static bool dimmed
    236.     {
    237.         get { return _dimmed; }
    238.         set
    239.         {
    240.             if (_dimmed != value)
    241.             {
    242.                 _dimmed = value;
    243.                 applyUIStates();
    244.             }
    245.         }
    246.     }
    247.     public static bool statusbar_light_mode
    248.     {
    249.         get { return _statusbar_light_mode; }
    250.         set
    251.         {
    252.             if (_statusbar_light_mode != value)
    253.             {
    254.                 _statusbar_light_mode = value;
    255.                 applyUIStates();
    256.             }
    257.         }
    258.     }
    259.     public static uint statusBarColor
    260.     {
    261.         get { return _statusBarColor; }
    262.         set
    263.         {
    264.             if (_statusBarColor != value)
    265.             {
    266.                 _statusBarColor = value;
    267.                 applyUIColors();
    268.                 applyUIStates();
    269.             }
    270.         }
    271.     }
    272.     public static uint navigationBarColor
    273.     {
    274.         get { return _navigationBarColor; }
    275.         set
    276.         {
    277.             if (_navigationBarColor != value)
    278.             {
    279.                 _navigationBarColor = value;
    280.                 applyUIColors();
    281.                 applyUIStates();
    282.             }
    283.         }
    284.     }
    285. }
    286.  
    In your Controller script just call to ApplicationChrome.statusbar_light_mode = true; to change the icons color to black, and put it to false to chage them back to white.