「Unity3D」在Unity中使用C#控制显示Android的状态栏
Unity打包的Android默认都是全屏,如果想要在真机上显示状态栏,就需要额外设置,有两种方式:
- 第一种,使用Android的Java代码去控制,然后以插件的方式放到Unity中,被C#调用。
- 第二种,使用Unity封装的C#代码,直接调用Android上的Java代码,去控制。
本文采用第二种方法,简单快捷,但会有几个坑,全部避开之后才能正确显示,先给正确代码,再指出踩坑点——只有一个函数,直接运行即可,内部精确控制,可以自定义。
private void ShowStatusBar()
{
#if UNITY_ANDROID && !UNITY_EDITOR
Screen.fullScreen = false;
using var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
using var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
activity.Call
(
"runOnUiThread", new AndroidJavaRunnable
(
() =>
{
// WINDOW_FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS |
// WINDOW_FLAG_FORCE_NOT_FULLSCREEN |
// WINDOW_FLAG_LAYOUT_IN_SCREEN |
// WINDOW_FLAG_TRANSLUCENT_STATUS
var flags = unchecked((int) 0x80000000) | 0x00000800 | 0x00000100 | 0x04000000;
// VIEW_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
// SYSTEM_UI_FLAG_LIGHT_STATUS_BAR (black text and icons)
var uiOptions = 0x00000400 | 0x00002000;
// the outer unityPlayer and activity will be disposed by other thread
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");
// 0xAARRGGBB
// window.Call("setStatusBarColor", unchecked((int) 0xFF000000));
window.Call("setFlags", flags, unchecked((int) 0xFFFFFFFF));
view .Call("setSystemUiVisibility", uiOptions);
}
)
);
#endif
}
需要注意的地方,在于:
-
Screen.fullScreen = false——需要设置,否则状态栏会自动隐藏。
-
runOnUiThread——需要控制Android UI的调用,在UI线程中执行。
-
window.setFlags——设置布局,view.setSystemUiVisibility——设置外观。
-
unchecked((int) 0x80000000)——这个越界int类型了,C#向Java传递会有问题,需要控制一下溢出。
-
unityPlayer和activity——在匿名函数中需要重新获取,外部的会在外层函数结束时释放资源,内部的在UI线程中执行,所以不能用闭包捕获外层的使用。
-
setFlags的第二个mask参数——这个0xFFFFFFFF会越界int类型,需要unchecked一下。
更多布局与外观的控制,查看WINDOW_FLAG_与SYSTEM_UI_FLAG的设定,添加到flags与uiOptions即可,注意int类型的越界处理。