• APP开发_ js 控制手机是否显示状态栏


    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);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    常用的标志:

    • 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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();  
    }
    
    • 1
    • 2
    • 3
    • 4

    确保检查 API 级别,因为 WindowInsetsController 只在 API 级别 30 及更高版本中可用。

    (2)控制状态栏的显示或隐藏
    一旦有了 WindowInsetsController 的实例,就可以使用它来控制状态栏的显示或隐藏了。

    • 隐藏状态栏
    if (controller != null) {  
        controller.hide(WindowInsets.Type.statusBars());  
    }
    
    • 1
    • 2
    • 3
    • 显示状态栏
    if (controller != null) {  
        controller.show(WindowInsets.Type.statusBars());  
    }
    
    • 1
    • 2
    • 3

    (3)设置状态栏的行为和外观

    除了基本的显示和隐藏,WindowInsetsController 还允许设置状态栏的行为和外观。

    • 设置状态栏的外观

    可以使用 setAppearanceLightStatusBars 和 setAppearanceDarkStatusBars 方法来改变状态栏的颜色模式。

    if (controller != null) {  
        // 设置状态栏为亮色模式  
        controller.setAppearanceLightStatusBars(true);  
        // 或者设置为暗色模式  
        controller.setAppearanceDarkStatusBars(true);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 设置状态栏的隐藏模式

    还可以设置状态栏隐藏时的行为模式,比如是否允许用户通过滑动来显示状态栏。

    if (controller != null) {  
        // 设置沉浸式模式,允许用户通过滑动来显示状态栏  
        controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);  
    }
    
    • 1
    • 2
    • 3
    • 4

    (4)监听状态栏的变化

    可以添加监听器来监听状态栏的变化,以便在状态栏显示或隐藏时执行特定的操作。

    if (controller != null) {  
        controller.addOnControlVisibilityChangeListener(new View.OnControlVisibilityChangeListener() {  
            @Override  
            public void onControlVisibilityChange(ControlVisibility controlVisibility) {  
                if (controlVisibility.statusBars == ControlVisibility.VISIBLE) {  
                    // 状态栏变为可见  
                } else {  
                    // 状态栏变为隐藏  
                }  
            }  
        });  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
            }
        }
    }
    
    • 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

    注意,@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");
        }
    }
    
    • 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

    这里,addJavascriptInterface 方法的第一个参数是 JavaScriptInterface 的实例,第二个参数是 JavaScript 中用来访问这个接口的对象名(这里使用了 “Android”)。

    (3)在 HTML 中调用 Android 设置显示或隐藏状态栏的方法

    在 HTML 页面中,即可以使用 JavaScript 来调用 Android 方法。

    DOCTYPE html>
    <html>
    <head>
        <title>WebView JavaScript Interface Exampletitle>
        <script type="text/javascript">
            function hideSystemUI() {
                // 调用Android方法
                Android.hideSystemUI();
            }
            function showSystemUI() {
                // 调用Android方法
                Android.showSystemUI();
            }
        script>
    head>
    <body>
        <h1>WebView JavaScript Interface Exampleh1>
        <button onclick="hideSystemUI()">隐藏状态栏button>
        <button onclick="showSystemUI()">显示状态栏button>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    在 MATLAB 中显示 3D 图像
    除硅树脂-HP4500
    java netty 实现 websocket 服务端和客户端双向通信 实现心跳和断线重连 完整示例
    什么是机器学习分类算法?【K-近邻算法(KNN)、交叉验证、朴素贝叶斯算法、决策树、随机森林】
    【FreeRTOS】FreeRTOS学习笔记(7)— 手写FreeRTOS双向链表/源码分析
    【深入理解C++】new/delete和new[]/delete[]探秘
    动手实现深度学习(5):计算图的实现
    超链接标签a实现跳转
    传输层TCP协议
    解决GDAL 写FileGDB的中文属性字段和字段值乱码。
  • 原文地址:https://blog.csdn.net/h8062651/article/details/138079732