You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用QAndroidApplication::runOnAndroidMainThread修改Android应用的状态栏与导航栏颜色?

如何使用QAndroidApplication::runOnAndroidMainThread修改Android应用的状态栏与导航栏颜色?

刚接触Qt/QML时,在Android上修改状态栏和导航栏颜色确实容易摸不着头脑——尤其是旧的QtAndroid::runOnAndroidThread在Qt6里不再推荐,而新的QAndroidApplication::runOnAndroidMainThread又找不到现成示例。我来一步步带你实现这个需求,保证能跑通!

一、前置准备

首先要确认你使用的是Qt6及以上版本(这个API是Qt6新增的),然后在代码中引入必要的头文件:

#include <QNativeInterface/QAndroidApplication>
#include <QtAndroid>

二、编写核心工具函数

我们可以封装一个专门的函数,用来统一设置状态栏和导航栏的颜色,同时处理Android版本兼容性:

void setSystemBarsColor(const QColor& statusBarColor, const QColor& navBarColor, bool isLightStatusBar = false)
{
    // 使用QAndroidApplication::runOnAndroidMainThread将代码调度到Android主线程执行
    QNativeInterface::QAndroidApplication::runOnAndroidMainThread([statusBarColor, navBarColor, isLightStatusBar]() -> QVariant {
        // 获取当前的Android Activity(Qt应用的主Activity)
        QJniObject activity = QNativeInterface::QAndroidApplication::context();
        if (!activity.isValid()) {
            return QVariant();
        }

        // 获取Activity对应的Window对象(Android中所有UI相关的设置都通过Window操作)
        QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
        if (!window.isValid()) {
            return QVariant();
        }

        // 设置状态栏颜色:传入ARGB格式的颜色值(QColor::rgba()正好返回这个格式)
        window.callMethod<void>("setStatusBarColor", "(I)V", statusBarColor.rgba());
        
        // 设置导航栏颜色
        window.callMethod<void>("setNavigationBarColor", "(I)V", navBarColor.rgba());

        // 处理状态栏文字颜色(仅Android 6.0+,即API 23及以上生效)
        if (QtAndroid::androidSdkVersion() >= 23) {
            QJniObject decorView = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
            if (decorView.isValid()) {
                int currentFlags = decorView.callMethod<int>("getSystemUiVisibility");
                if (isLightStatusBar) {
                    // 开启浅色状态栏文字(适合深色状态栏背景)
                    currentFlags |= QJniObject::getStaticField<int>("android/view/View", "SYSTEM_UI_FLAG_LIGHT_STATUS_BAR");
                } else {
                    // 关闭浅色状态栏文字(适合浅色状态栏背景)
                    currentFlags &= ~QJniObject::getStaticField<int>("android/view/View", "SYSTEM_UI_FLAG_LIGHT_STATUS_BAR");
                }
                decorView.callMethod<void>("setSystemUiVisibility", "(I)V", currentFlags);
            }
        }

        return QVariant();
    });
}

三、调用方式

方式1:在C++中直接调用

比如在应用启动时就设置好颜色,在main.cpp里:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    // 示例:设置状态栏为深蓝色,导航栏为深灰色,状态栏文字为白色(非浅色)
    setSystemBarsColor(QColor(0x1a, 0x23, 0x7e), QColor(0x21, 0x21, 0x21), false);

    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/main.qml"_qs);
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

方式2:注册到QML中调用

如果需要在QML界面里动态调整颜色,可以把这个工具函数封装成QML可调用的类:

  1. 先创建一个辅助类:
#include <QObject>
#include <QColor>

class AndroidSystemBarHelper : public QObject
{
    Q_OBJECT
public:
    explicit AndroidSystemBarHelper(QObject *parent = nullptr) : QObject(parent) {}

    // 标记为Q_INVOKABLE,让QML可以调用
    Q_INVOKABLE void setSystemBarsColor(const QColor& statusBarColor, const QColor& navBarColor, bool isLightStatusBar = false)
    {
        // 把上面的setSystemBarsColor函数内容复制到这里
    }
};
  1. main.cpp中注册这个类到QML:
#include <QQmlEngine>
#include <QJSEngine>

// ... 其他代码 ...

qmlRegisterSingletonType<AndroidSystemBarHelper>("com.example.SystemBarHelper", 1, 0, "SystemBarHelper",
    [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
        Q_UNUSED(engine);
        Q_UNUSED(scriptEngine);
        return new AndroidSystemBarHelper();
    });
  1. 在QML中调用:
import QtQuick 2.15
import QtQuick.Controls 2.15
import com.example.SystemBarHelper 1.0

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("System Bar Demo")

    Button {
        text: "切换深色系统栏"
        onClicked: {
            SystemBarHelper.setSystemBarsColor("#1a237e", "#212121", false)
        }
    }

    Button {
        text: "切换浅色系统栏"
        y: 60
        onClicked: {
            SystemBarHelper.setSystemBarsColor("#f5f5f5", "#e0e0e0", true)
        }
    }
}

四、注意事项

  • 为什么必须用runOnAndroidMainThread?因为Android的UI操作必须在主线程执行,Qt的这个API帮我们把代码安全地调度到Android主线程,避免崩溃。
  • 颜色值必须是ARGB格式,QColor::rgba()会自动转换为符合要求的整数。
  • 状态栏文字颜色的设置仅在Android 6.0(API 23)及以上版本生效,低版本无法修改文字颜色。
  • 如果应用使用了全屏/沉浸式模式,可能需要额外设置SYSTEM_UI_FLAG_LAYOUT_STABLESYSTEM_UI_FLAG_LAYOUT_FULLSCREEN等标记,确保颜色设置正常显示。
  • 建议在真实Android设备上测试,模拟器可能存在显示差异。

备注:内容来源于stack exchange,提问作者Ahmet97

火山引擎 最新活动