Unity在5.3以上的版本里把状态栏的显隐功能去掉了,但是iOS的没有去掉,果然安卓不是亲儿子啊,前两天做项目,需要这个功能,我开发用的是5.6版本,怎么找都没找到这个功能,还以为放在其他地方了呢,还特意去官网看了Unity的更新内容,结果百度了一下,果然5.3以后,安卓就没有这个功能了。后来在网上看到有人写了两个代码,就把这个问题搞定了,我稍微整理了一下,下面放代码。文章源自大腿Plus-https://www.shijunzh.com/archives/513
using System; using System.Collections.Generic; using UnityEngine; public class AndroidStatusBar { // Enums public enum States { Unknown, Visible, VisibleOverContent, TranslucentOverContent, Hidden, } // Constants private const uint DEFAULT_BACKGROUND_COLOR = 0xff000000; #if UNITY_ANDROID // Original Android flags private const int VIEW_SYSTEM_UI_FLAG_VISIBLE = 0; // Added in API 14 (Android 4.0.x): Status bar visible (the default) 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) 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. 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) private const int VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // Added in API 16 (Android 4.1.x): ? 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) 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) 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) 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) private static int WINDOW_FLAG_FULLSCREEN = 0x00000400; private static int WINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800; private static int WINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100; private static int WINDOW_FLAG_TRANSLUCENT_STATUS = 0x04000000; private static int WINDOW_FLAG_TRANSLUCENT_NAVIGATION = 0x08000000; 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() // Current values private static int systemUiVisibilityValue; private static int flagsValue; #endif //Properties private static States _statusBarState; private static uint _statusBarColor = DEFAULT_BACKGROUND_COLOR; private static bool _isStatusBarTranslucent; private static bool _dimmed; static AndroidStatusBar() { applyUIStates(); applyUIColors(); } private static void applyUIStates() { if (Application.platform == RuntimePlatform.Android) { int newFlagsValue = 0; int newSystemUiVisibilityValue = 0; // Apply dim values if (_dimmed) newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LOW_PROFILE; // Apply color values if (_statusBarColor != DEFAULT_BACKGROUND_COLOR) newFlagsValue |= WINDOW_FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; // Apply status bar values switch (_statusBarState) { case States.Visible: _isStatusBarTranslucent = false; newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN; break; case States.VisibleOverContent: _isStatusBarTranslucent = false; newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN; newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; break; case States.TranslucentOverContent: _isStatusBarTranslucent = true; newFlagsValue |= WINDOW_FLAG_FORCE_NOT_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN | WINDOW_FLAG_TRANSLUCENT_STATUS; newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; break; case States.Hidden: newFlagsValue |= WINDOW_FLAG_FULLSCREEN | WINDOW_FLAG_LAYOUT_IN_SCREEN; if (_isStatusBarTranslucent) newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_STATUS; break; } if (Screen.fullScreen) Screen.fullScreen = false; // Applies everything natively setFlags(newFlagsValue); setSystemUiVisibility(newSystemUiVisibilityValue); } } private static void applyUIColors() { if (Application.platform == RuntimePlatform.Android) { runOnAndroidUiThread(applyUIColorsAndroidInThread); } } #if UNITY_ANDROID private static void runOnAndroidUiThread(Action target) { using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { activity.Call("runOnUiThread", new AndroidJavaRunnable(target)); } } } private static void setSystemUiVisibility(int value) { if (systemUiVisibilityValue != value) { systemUiVisibilityValue = value; runOnAndroidUiThread(setSystemUiVisibilityInThread); } } private static void setSystemUiVisibilityInThread() { using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { using (var window = activity.Call<AndroidJavaObject>("getWindow")) { using (var view = window.Call<AndroidJavaObject>("getDecorView")) { view.Call("setSystemUiVisibility", systemUiVisibilityValue); } } } } } private static void setFlags(int value) { if (flagsValue != value) { flagsValue = value; runOnAndroidUiThread(setFlagsInThread); } } private static void setFlagsInThread() { using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { using (var window = activity.Call<AndroidJavaObject>("getWindow")) { window.Call("setFlags", flagsValue, -1); // (int)0x7FFFFFFF } } } } private static void applyUIColorsAndroidInThread() { using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { using (var window = activity.Call<AndroidJavaObject>("getWindow")) { window.Call("setStatusBarColor", unchecked((int)_statusBarColor)); } } } } #endif public static States statusBarState { get { return _statusBarState; } set { if (_statusBarState != value) { _statusBarState = value; applyUIStates(); } } } public static bool dimmed { get { return _dimmed; } set { if (_dimmed != value) { _dimmed = value; applyUIStates(); } } } public static uint statusBarColor { get { return _statusBarColor; } set { if (_statusBarColor != value) { _statusBarColor = value; applyUIColors(); applyUIStates(); } } } }
上面的代码是调用了Unity打包成安卓后自动生成的UnityPlayerActivity类里面的状态栏显示隐藏的方法,所以不需要任何其他的安卓的jar包。文章源自大腿Plus-https://www.shijunzh.com/archives/513
下面是使用方法:文章源自大腿Plus-https://www.shijunzh.com/archives/513
using UnityEngine; using System.Collections; public class AppStatusBar : MonoBehaviour { [Tooltip("状态栏是否显示状态及通知")] public bool statusBar; [Tooltip("状态栏样式")] public AndroidStatusBar.States states = AndroidStatusBar.States.Visible; // Use this for initialization void Awake() { if (Application.platform == RuntimePlatform.Android) { AndroidStatusBar.dimmed = !statusBar; //当AndroidStatusBar.dimmed=false时,状态栏显示所有状态及通知图标 //当AndroidStatusBar.dimmed=true时,状态栏仅电量和时间,不显示其他状态及通知 ////显示状态栏,占用屏幕最上方的一部分像素 //AndroidStatusBar.statusBarState = AndroidStatusBar.States.Visible; ////悬浮显示状态栏,不占用屏幕像素 //AndroidStatusBar.statusBarState = AndroidStatusBar.States.VisibleOverContent; ////透明悬浮显示状态栏,不占用屏幕像素 //AndroidStatusBar.statusBarState = AndroidStatusBar.States.TranslucentOverContent; ////隐藏状态栏 //AndroidStatusBar.statusBarState = AndroidStatusBar.States.Hidden; AndroidStatusBar.statusBarState = states; } } }
可以直接将上面的代码拖到任意一个GameObject上,但是只有发布出来后才能看到效果。文章源自大腿Plus-https://www.shijunzh.com/archives/513
2018年4月2日 上午10:06 1F
登录回复
你好,我用这个出现一个问题, 5.3的时候mUnityPlayer.setOnSystemUiVisibilityChangeListener是好着的,5.5之后我在安卓部分添加了 mUnityPlayer.setOnSystemUiVisibilityChangeListener 函数后,发现这个函数并不能完全监听到所有的消息,有时候会丢消息,导致我的显示有时候会有问题, 我可以留个QQ交流下 493213418
2018年4月2日 上午10:12 B1
登录回复
@ Rex 这个可能和Unity版本的问题,我记得在哪个版本里面Unity的Activity里面的内容发生了一些变化,还用之前的方法可能会存在问题。
2018年4月2日 上午10:44 2F
登录回复
哦,那有没有什么参考可以说下,这部分内容用的人比较少~~ 困扰很久了~
2018年4月2日 上午10:46 B1
登录回复
@ Rex 这个我也没怎么用过,可以问一下安卓原生开发的人,好久没有碰安卓原生的东西了,我也不太清楚了。
2018年4月2日 上午10:51 B2
登录回复
@ 大腿Plus 好的,谢谢了
2018年7月6日 下午7:32 3F
登录回复
你好 这种方法很实用 我想问一下 有什么方法可以获取状态栏的高度吗 因为不同机型他的状态栏高度不一样 如果有的话 可以尽量说详细点
2018年7月6日 下午7:40 B1
登录回复
@ 上面有个状态栏样式的那个可以控制占用上方屏幕的像素,不用去获取状态栏宽度,只要设置好UI锚点应该不会有什么问题