using UnityEngine;
using System.Collections;
public class AppStatusBar : MonoSingleton<AppStatusBar>
{
[Tooltip("状态栏是否显示状态及通知")]
public bool statusBar;
[Tooltip("状态栏样式")]
public AndroidStatusBar.States states = AndroidStatusBar.States.Visible;
public bool _IsStatusVisible = false;
// Use this for initialization
public override void Awake()
{
AndroidStatusBar.Init();
Screen.fullScreen = true;
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;
}
}
public void SetVisible(bool b)
{
if (_IsStatusVisible != b)
{
_IsStatusVisible = b;
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;
if (b)
{
//AndroidStatusBar.statusBarState = AndroidStatusBar.States.VisibleOverContent;
//yield return new WaitForSeconds(0.5f);
AndroidStatusBar.statusBarState = AndroidStatusBar.States.Visible;
}
else
{
AndroidStatusBar.statusBarState = AndroidStatusBar.States.Hidden;
}
}
}
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
/**
* @author zeh fernando
* @modify MemoryC_2017-02-05
*/
public class AndroidStatusBar
{
/**
* Manipulates the system application chrome to change the way the status bar and navigation bar work
*POSTS FROM :
*http://zehfernando.com/2015/unity-tidbits-changing-the-visibility-of-androids-navigation-and-status-bars-and-implementing-immersive-mode/
*[url=http://www.manew.com/thread-100054-1-1.html]http://www.manew.com/thread-100054-1-1.html[/url]
* References:
* . http://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int)
* . http://forum.unity3d.com/threads/calling-setsystemuivisibility.139445/#post-952946
* . http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_LAYOUT_IN_SCREEN
**/
// 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 States _navigationBarState;
private static uint _statusBarColor = DEFAULT_BACKGROUND_COLOR;
// private static uint _navigationBarColor = DEFAULT_BACKGROUND_COLOR;
private static bool _isStatusBarTranslucent; // Just so we know whether its translucent when hidden or not
// private static bool _isNavigationBarTranslucent;
private static bool _dimmed;
// ================================================================================================================
// INTERNAL INTERFACE ---------------------------------------------------------------------------------------------
static AndroidStatusBar()
{
applyUIStates();
applyUIColors();
}
public static void Init()
{
applyUIStates();
applyUIColors();
}
private static void applyUIStates()
{
#if UNITY_ANDROID && !UNITY_EDITOR
int newFlagsValue = 0;
int newSystemUiVisibilityValue = 0;
// Apply dim values
if (_dimmed) newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LOW_PROFILE;
// Apply color values
// if (_navigationBarColor != DEFAULT_BACKGROUND_COLOR || _statusBarColor != DEFAULT_BACKGROUND_COLOR) newFlagsValue |= WINDOW_FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
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;
}
// Applies navigation values
/*
switch (_navigationBarState) {
case States.Visible:
_isNavigationBarTranslucent = false;
newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE;
break;
case States.VisibleOverContent:
// TODO: Side effect: forces status bar over content if set to VISIBLE
_isNavigationBarTranslucent = false;
newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE | VIEW_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
break;
case States.TranslucentOverContent:
// TODO: Side effect: forces status bar over content if set to VISIBLE
_isNavigationBarTranslucent = true;
newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_NAVIGATION;
newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE | VIEW_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
break;
case States.Hidden:
newSystemUiVisibilityValue |= VIEW_SYSTEM_UI_FLAG_FULLSCREEN | VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION | VIEW_SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
if (_isNavigationBarTranslucent) newFlagsValue |= WINDOW_FLAG_TRANSLUCENT_NAVIGATION;
break;
}
*/
if (Screen.fullScreen) Screen.fullScreen = false;
// Applies everything natively
setFlags(newFlagsValue);
setSystemUiVisibility(newSystemUiVisibilityValue);
#endif
}
private static void applyUIColors()
{
#if UNITY_ANDROID && !UNITY_EDITOR
runOnAndroidUiThread(applyUIColorsAndroidInThread);
#endif
}
#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()
{
//Debug.Log("SYSTEM FLAGS: " + systemUiVisibilityValue);
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()
{
//Debug.Log("FLAGS: " + flagsValue);
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"))
{
//Debug.Log("Colors SET: " + _statusBarColor);
window.Call("setStatusBarColor", unchecked((int)_statusBarColor));
// window.Call("setNavigationBarColor", unchecked((int)_navigationBarColor));
}
}
}
}
#endif
// ================================================================================================================
// ACCESSOR INTERFACE ---------------------------------------------------------------------------------------------
/*
public static States navigationBarState {
get { return _navigationBarState; }
set {
if (_navigationBarState != value) {
_navigationBarState = value;
applyUIStates();
}
}
}
*/
public static States statusBarState
{
get { return _statusBarState; }
set
{
if (_statusBarState != value)
{
_statusBarState = value;
applyUIStates();
}
}
}
//当AndroidStatusBar.dimmed=false时,状态栏显示所有状态及通知图标
//当AndroidStatusBar.dimmed=true时,状态栏仅电量和时间,不显示其他状态及通知
//AndroidStatusBar.dimmed = !AndroidStatusBar.dimmed;
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();
}
}
}
/*
public static uint navigationBarColor {
get { return _navigationBarColor; }
set {
if (_navigationBarColor != value) {
_navigationBarColor = value;
applyUIColors();
applyUIStates();
}
}
}
*/
}
应用:
AppStatusBar.Instance.SetVisible(true);