Search Unity

Unity & iOS Dark Mode

Discussion in 'iOS and tvOS' started by stanislav-osipov, Jan 8, 2020.

  1. stanislav-osipov

    stanislav-osipov

    Joined:
    May 30, 2012
    Posts:
    1,790
    The black iOS theme is one of the most trending features of the current year, and I think Unity Game and App developers would also like to know if the user is currently configured his device to use the black or light theme, to be able to adjust the game or application UI appearance accordingly.

    I want to share an example of how you can get this info when building with Unity for iOS.

    1. Make The *.mm file (MyPlugin.mm) from example. Place this file under the Assets/Plugins/iOS folder.
    Code (CSharp):
    1. #import <Foundation/Foundation.h>
    2. #import <UIKit/UIKit.h>
    3.  
    4. extern "C" {
    5.    bool _IsDakModeSet() {
    6.        if (@available(iOS 12.0, *)) {
    7.            if(UIScreen.mainScreen.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
    8.                return true;
    9.            }
    10.        }
    11.      
    12.        return false;
    13.    }
    14. }
    2. On the C# side, you can now make the MyPlugin.cs file that will query our native function.
    Code (CSharp):
    1. #if UNITY_IPHONE || UNITY_IOS
    2. using System.Runtime.InteropServices;
    3. #endif
    4.  
    5. public static class MyPlugin
    6. {
    7.    #if UNITY_IPHONE || UNITY_IOS
    8.    [DllImport("__Internal")]
    9.    private static extern bool _IsDakModeSet();
    10.    #endif
    11.  
    12.    public static bool IsDakModeSet()
    13.    {
    14.        #if UNITY_IPHONE || UNITY_IOS
    15.        return _IsDakModeSet();
    16.        #endif
    17.    }
    18. }
    Now when you need to define if the user prefers to use dark or lite mode, you can do it like this:
    Code (CSharp):
    1. if (MyPlugin.IsDakModeSet())
    2. {
    3.    // Use Dark Skin.
    4. }
    5. else
    6. {
    7.    //use Light Skin.
    8. }
    It makes sense to check this flag on your application lunch. And also, if your UI supports a hot skin swap, you can check if the device system preference was changed each time your application is restored from the background. You can do this with Unity OnApplicationPause callback.

    If you like to use already made solution that is constantly supported, take a look at IOS Native Pro or the Ultimate Mobile plugins. Here is the code snippet how you can retrieve the same preference using any of those plugins:

    Code (CSharp):
    1. using SA.iOS.UIKit;
    2. ...
    3.  
    4. var userInterfaceStyle = ISN_UIScreen.MainScreen.TraitCollection.UserInterfaceStyle;
    5. if (userInterfaceStyle == ISN_UIUserInterfaceStyle.Dark)
    6. {
    7.    // Use Dark Skin.
    8. }
    9. else
    10. {
    11.    //use Light Skin.
    12. }
    I hope it was helpful :)
     
  2. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    516
    Kudos
     
    Kaizez likes this.
  3. Kaizez

    Kaizez

    Joined:
    Nov 14, 2018
    Posts:
    1
    And for Android?
     
  4. stanislav-osipov

    stanislav-osipov

    Joined:
    May 30, 2012
    Posts:
    1,790
    Fair enough will add one :)
     
  5. ryandobal_unity

    ryandobal_unity

    Joined:
    Mar 16, 2020
    Posts:
    6
    very cool thanks! :)
     
  6. stanislav-osipov

    stanislav-osipov

    Joined:
    May 30, 2012
    Posts:
    1,790
    As Promised:
    On Android starting from api level 29 (Q) it's possible to define if the user chooses a dark mode as a preference.
    I won't be describing the whole native plugin creation process for the android, since it's ready done in many many articles. I like this one for example:
    http://markcastle.com/steps-to-crea...ity-in-java-using-android-studio-part-1-of-2/


    So here is the simple Java function you need to make:
    Code (CSharp):
    1. public boolean IsDarkMode() {
    2.     Configuration configuration = UnityPlayer.currentActivity.getResources().getConfiguration();
    3.     int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
    4.     switch (currentNightMode) {
    5.         case Configuration.UI_MODE_NIGHT_NO:
    6.             // Night mode is not active, we're using the light theme
    7.             return false;
    8.         case Configuration.UI_MODE_NIGHT_YES:
    9.             // Night mode is active, we're using dark theme
    10.             return true;
    11.     }
    12.    
    13.     return false;
    14. }

    And of course, it's now also available with Android Native Pro
    Wiki:
    https://github.com/StansAssets/com.stansassets.android-native/wiki/Dark-Mode-(Theme)

    Code Sample:
    Code (CSharp):
    1. using SA.Android.App;
    2. using SA.Android.Content.Res;
    3. ...
    4.  
    5. // Only supported from android 10.0 (api 29)
    6. if (AN_Build.VERSION.SDK_INT < AN_Build.VERSION_CODES.Q) {
    7.     Debug.Log("Not supported")
    8.     return;
    9. }
    10.  
    11. var configuration = AN_MainActivity.Instance.GetResources().GetConfiguration();
    12. var currentNightMode =  configuration.UIMode & AN_Configuration.UI_MODE_NIGHT_MASK;
    13. switch (currentNightMode) {
    14.     case AN_Configuration.UI_MODE_NIGHT_NO:
    15.         // Night mode is not active, we're using the light theme
    16.         Debug.Log("Night mode is not active, we're using the light theme");
    17.         break;
    18.     case AN_Configuration.UI_MODE_NIGHT_YES:
    19.         // Night mode is active, we're using dark theme
    20.         Debug.Log("Night mode is active, we're using dark theme");
    21.         break;
    22. }
    And the cross-platfrom Ultimate Mobile plugin:

    Wiki:
    https://github.com/StansAssets/com.stansassets.ultimate-mobile/wiki/Dark-Mode

    Code Sample:
    Code (CSharp):
    1. using SA.CrossPlatform.App;
    2. ...
    3.  
    4. Debug.Log(UM_Application.IsDarkMode
    5.             ? "Night mode is active, we're using dark theme"
    6.             : "Night mode is not active, we're using the light theme");
     
    FauconSpartiate likes this.
  7. sefaenes

    sefaenes

    Joined:
    Jul 12, 2019
    Posts:
    22
    @lacost is there a simple way to check internet connection on apple phone/tablet devices? I wrote a plugin for android but there is no initial example for ios. have any idea?
     
  8. stanislav-osipov

    stanislav-osipov

    Joined:
    May 30, 2012
    Posts:
    1,790
    Are you referring for some specific API.

    1. What is wrong with the default unity way to check the connection type?
    2. The fact that you have a connection doesn't mean that you have internet.
    3. The fact that you do have internet doesn't mean that you can reach the web address you need.

    This means, that the easier way is to the ping IP address you need.
     
  9. FauconSpartiate

    FauconSpartiate

    Joined:
    May 5, 2018
    Posts:
    2
    I tried your piece of code, but I get an error at "UnityPlayer.currentActivity". It doesn't find "UnityPlayer" and I can't find any class to import or workaround to this. Could you help me out?
     
  10. stanislav-osipov

    stanislav-osipov

    Joined:
    May 30, 2012
    Posts:
    1,790
    FauconSpartiate likes this.
  11. TimeLineStudio

    TimeLineStudio

    Joined:
    Dec 30, 2020
    Posts:
    2
    Hello, good morning, I had a question. I use the "
    Ultimate Mobile Pro
    " package, but I can not get this code. Can you help me?

    1. using SA.CrossPlatform.Appک
    2. Debug.Log(UM_Application.IsDarkMode
    3. ? "Night mode is active, we're using dark theme"
    4. : "Night mode is not active, we're using the light theme");
     
  12. msnz

    msnz

    Joined:
    Nov 4, 2020
    Posts:
    31
    Code (CSharp):
    1. UIScreen.mainScreen.traitCollection.userInterfaceStyle
    This iOS code works on a fresh empty project and returns the correct userInterfaceStyle value. However, when used in an actual project, it doesn't work anymore. The userInterfaceStyle value returned is always 1 (light mode) even if I've set the device to use dark mode.

    Could it be that one of the plugins we are using (Facebook, Firebase, etc) is interfering with this code somehow? Are there any usual suspects?

    The thing is, when I display native alerts, the dialog box shown is still using dark mode, which indicates to me that the app is aware that the device is using dark mode. It seems that only the code above is unaware that the device is using dark mode.