Unity在5.3以上的版本里把状态栏的显隐功能去掉了,但是iOS的没有去掉,果然安卓不是亲儿子啊,前两天做项目,需要这个功能,我开发用的是5.6版本,怎么找都没找到这个功能,还以为放在其他地方了呢,还特意去官网看了Unity的更新内容,结果百度了一下,果然5.3以后,安卓就没有这个功能了。后来在网上看到有人写了两个代码,就把这个问题搞定了,我稍微整理了一下,下面放代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
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.zhaoshijun.com/archives/513
下面是使用方法:文章源自大腿Plus-https://www.zhaoshijun.com/archives/513
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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.zhaoshijun.com/archives/513 文章源自大腿Plus-https://www.zhaoshijun.com/archives/513
我的微信
微信扫一扫
![weinxin](https://www.zhaoshijun.com/wp-content/uploads/2021/12/wechat.png)
shijun_z
我的QQ
QQ扫一扫
![weinxin](https://www.zhaoshijun.com/wp-content/uploads/2023/11/qq.jpg)
846207670
1F
你好,我用这个出现一个问题, 5.3的时候mUnityPlayer.setOnSystemUiVisibilityChangeListener是好着的,5.5之后我在安卓部分添加了 mUnityPlayer.setOnSystemUiVisibilityChangeListener 函数后,发现这个函数并不能完全监听到所有的消息,有时候会丢消息,导致我的显示有时候会有问题, 我可以留个QQ交流下 493213418
B1
@ Rex 这个可能和Unity版本的问题,我记得在哪个版本里面Unity的Activity里面的内容发生了一些变化,还用之前的方法可能会存在问题。
2F
哦,那有没有什么参考可以说下,这部分内容用的人比较少~~ 困扰很久了~
B1
@ Rex 这个我也没怎么用过,可以问一下安卓原生开发的人,好久没有碰安卓原生的东西了,我也不太清楚了。
B2
@ 大腿Plus 好的,谢谢了
3F
你好 这种方法很实用 我想问一下 有什么方法可以获取状态栏的高度吗 因为不同机型他的状态栏高度不一样 如果有的话 可以尽量说详细点
B1
@ 上面有个状态栏样式的那个可以控制占用上方屏幕的像素,不用去获取状态栏宽度,只要设置好UI锚点应该不会有什么问题