1 Android 控制手机显示或隐藏状态栏的方法
1.1 使用 View 的 setSystemUiVisibility 方法
这个方法允许设置系统 UI 的可见性,包括状态栏。你可以通过组合不同的标志来实现不同的效果。
示例代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取DecorView,这是Activity的最顶层视图
View decorView = getWindow().getDecorView();
// 设置系统UI的可见性
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; // 隐藏状态栏
decorView.setSystemUiVisibility(uiOptions);
}
常用的标志:
- View.SYSTEM_UI_FLAG_FULLSCREEN: 隐藏状态栏。
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION: 隐藏导航栏。
- View.SYSTEM_UI_FLAG_IMMERSIVE: 沉浸式模式,允许用户通过滑动屏幕边缘来显示系统栏。
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY: 类似于 IMMERSIVE,但系统栏在显示后会短暂延迟隐藏。
1.2 使用 Window 的 addFlags 和 clearFlags 方法
可以通过Window对象来添加或清除特定的窗口标志,从而控制状态栏的显示。
示例代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取Window对象
Window window = getWindow();
// 隐藏状态栏
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 如果需要再次显示状态栏
// window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
1.3 处理状态栏的重新显示
在某些情况下,如用户滑动屏幕或收到通知,状态栏可能会重新显示。为了确保用户体验的连贯性,你可能需要在onWindowFocusChanged方法中监听窗口焦点的变化,并相应地调整系统UI的可见性。
示例代码:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // 隐藏导航栏
| View.SYSTEM_UI_FLAG_FULLSCREEN // 隐藏状态栏
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); // 沉浸式模式
}
}
1.4 使用 WindowInsetsController 类
在 Android 开发中,随着版本的更新,API 也提供了更加灵活和强大的方法来控制状态栏的显示或隐藏。从 Android R(API级别30)开始,引入了 WindowInsetsController 类,它提供了一种更直观和强大的方式来控制窗口插入(包括状态栏和导航栏)的可见性。
使用 WindowInsetsController,可以实现更精细的控制,比如平滑地隐藏或显示状态栏,以及处理用户与这些系统 UI 元素的交互。
(1)获取 WindowInsetsController 实例
首先,需要在 Activity 或 Fragment 中获取 WindowInsetsController 的实例。这通常通过 Window 对象来实现。
WindowInsetsController controller;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
controller = getWindow().getInsetsController();
}
确保检查 API 级别,因为 WindowInsetsController 只在 API 级别 30 及更高版本中可用。
(2)控制状态栏的显示或隐藏
一旦有了 WindowInsetsController 的实例,就可以使用它来控制状态栏的显示或隐藏了。
- 隐藏状态栏
if (controller != null) {
controller.hide(WindowInsets.Type.statusBars());
}
- 显示状态栏
if (controller != null) {
controller.show(WindowInsets.Type.statusBars());
}
(3)设置状态栏的行为和外观
除了基本的显示和隐藏,WindowInsetsController 还允许设置状态栏的行为和外观。
- 设置状态栏的外观
可以使用 setAppearanceLightStatusBars 和 setAppearanceDarkStatusBars 方法来改变状态栏的颜色模式。
if (controller != null) {
// 设置状态栏为亮色模式
controller.setAppearanceLightStatusBars(true);
// 或者设置为暗色模式
controller.setAppearanceDarkStatusBars(true);
}
- 设置状态栏的隐藏模式
还可以设置状态栏隐藏时的行为模式,比如是否允许用户通过滑动来显示状态栏。
if (controller != null) {
// 设置沉浸式模式,允许用户通过滑动来显示状态栏
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
(4)监听状态栏的变化
可以添加监听器来监听状态栏的变化,以便在状态栏显示或隐藏时执行特定的操作。
if (controller != null) {
controller.addOnControlVisibilityChangeListener(new View.OnControlVisibilityChangeListener() {
@Override
public void onControlVisibilityChange(ControlVisibility controlVisibility) {
if (controlVisibility.statusBars == ControlVisibility.VISIBLE) {
// 状态栏变为可见
} else {
// 状态栏变为隐藏
}
}
});
}
2 提供 js 调用 Android 方法
重点注意:需要通过异步的方式调用显示或隐藏状态栏的方法,否则 JS 会报错,并且设置失败。
(1)创建 JavaScriptInterface 类
首先,需要创建一个 Java 类,实现 WebView.JavascriptInterface 接口。这个类将作为 JavaScript 和 Android 原生代码之间的桥梁。
import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
// 隐藏系统栏
@JavascriptInterface
public void hideSystemUI() {
executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
WindowInsetsController controller = ((Activity) mContext).getWindow().getInsetsController();
if (controller != null) {
// 隐藏状态栏
controller.hide(WindowInsets.Type.statusBars());
// 如果你想在用户交互后自动显示系统栏,可以使用SYSTEM_BARS_BEHAVIOR_SHOW_TRANSIENT_BARS或SYSTEM_BARS_BEHAVIOR_SHOW_BARS_BY_SWIPE
// controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
return "";
}
});
try {
// 当需要结果时,阻塞等待Future完成
String result = future.get();
System.out.println("异步操作结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown(); // 关闭ExecutorService
}
}
// 显示系统栏
@JavascriptInterface
public void showSystemUI() {
executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
WindowInsetsController controller = ((Activity) mContext).getWindow().getInsetsController();
if (controller != null) {
// 显示状态栏
controller.show(WindowInsets.Type.statusBars());
}
}
return "";
}
});
try {
// 当需要结果时,阻塞等待Future完成
String result = future.get();
System.out.println("异步操作结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown(); // 关闭ExecutorService
}
}
}
注意,@JavascriptInterface 注解是必须的,该注解允许 Android 识别哪些方法可以被 JavaScript 调用。
(2)在 WebView 中启用 JavaScript 并添加接口
然后,在 Activity 或 Fragment 中,需要初始化 WebView,启用 JavaScript,并将创建的 JavaScriptInterface 实例添加到 WebView 中。
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
// 加载一个HTML页面,或者直接使用webView.loadDataWithBaseURL()加载包含JavaScript的字符串
webView.loadUrl("file:///android_asset/my_page.html");
}
}
这里,addJavascriptInterface 方法的第一个参数是 JavaScriptInterface 的实例,第二个参数是 JavaScript 中用来访问这个接口的对象名(这里使用了 “Android”)。
(3)在 HTML 中调用 Android 设置显示或隐藏状态栏的方法
在 HTML 页面中,即可以使用 JavaScript 来调用 Android 方法。
<!DOCTYPE html>
<html>
<head>
<title>WebView JavaScript Interface Example</title>
<script type="text/javascript">
function hideSystemUI() {
// 调用Android方法
Android.hideSystemUI();
}
function showSystemUI() {
// 调用Android方法
Android.showSystemUI();
}
</script>
</head>
<body>
<h1>WebView JavaScript Interface Example</h1>
<button onclick="hideSystemUI()">隐藏状态栏</button>
<button onclick="showSystemUI()">显示状态栏</button>
</body>
</html>