diff --git a/nymea-app/platformintegration/android/platformhelperandroid.cpp b/nymea-app/platformintegration/android/platformhelperandroid.cpp index 9386cf36..33df72c2 100644 --- a/nymea-app/platformintegration/android/platformhelperandroid.cpp +++ b/nymea-app/platformintegration/android/platformhelperandroid.cpp @@ -4,8 +4,24 @@ #include #include + +// WindowManager.LayoutParams +#define FLAG_TRANSLUCENT_STATUS 0x04000000 +#define FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 0x80000000 +// View +#define SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 0x00002000 + + static PlatformHelperAndroid *m_instance; +static QAndroidJniObject getAndroidWindow() +{ + QAndroidJniObject window = QtAndroid::androidActivity().callObjectMethod("getWindow", "()Landroid/view/Window;"); + window.callMethod("addFlags", "(I)V", FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.callMethod("clearFlags", "(I)V", FLAG_TRANSLUCENT_STATUS); + return window; +} + PlatformHelperAndroid::PlatformHelperAndroid(QObject *parent) : PlatformHelper(parent) { m_instance = this; @@ -77,6 +93,33 @@ void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType QtAndroid::androidActivity().callMethod("vibrate","(I)V", duration); } +void PlatformHelperAndroid::setTopPanelColor(const QColor &color) +{ + PlatformHelper::setTopPanelColor(color); + + if (QtAndroid::androidSdkVersion() < 21) + return; + + QtAndroid::runOnAndroidThread([=]() { + QAndroidJniObject window = getAndroidWindow(); + window.callMethod("setStatusBarColor", "(I)V", color.rgba()); + }); + + if (((color.red() * 299 + color.green() * 587 + color.blue() * 114) / 1000) > 123) { + setTopPanelTheme(Light); + } else { + setTopPanelTheme(Dark); + } +} + +void PlatformHelperAndroid::setBottomPanelColor(const QColor &color) +{ + PlatformHelper::setBottomPanelColor(color); + + if (QtAndroid::androidSdkVersion() < 21) + return; +} + void PlatformHelperAndroid::permissionRequestFinished(const QtAndroid::PermissionResultMap &result) { foreach (const QString &key, result.keys()) { @@ -84,3 +127,20 @@ void PlatformHelperAndroid::permissionRequestFinished(const QtAndroid::Permissio } emit m_instance->permissionsRequestFinished(); } + +void PlatformHelperAndroid::setTopPanelTheme(PlatformHelperAndroid::Theme theme) +{ + if (QtAndroid::androidSdkVersion() < 23) + return; + + QtAndroid::runOnAndroidThread([=]() { + QAndroidJniObject window = getAndroidWindow(); + QAndroidJniObject view = window.callObjectMethod("getDecorView", "()Landroid/view/View;"); + int visibility = view.callMethod("getSystemUiVisibility", "()I"); + if (theme == Theme::Light) + visibility |= SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + else + visibility &= ~SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + view.callMethod("setSystemUiVisibility", "(I)V", visibility); + }); +} diff --git a/nymea-app/platformintegration/android/platformhelperandroid.h b/nymea-app/platformintegration/android/platformhelperandroid.h index 4d8c9dd7..147af2d4 100644 --- a/nymea-app/platformintegration/android/platformhelperandroid.h +++ b/nymea-app/platformintegration/android/platformhelperandroid.h @@ -9,6 +9,8 @@ class PlatformHelperAndroid : public PlatformHelper { Q_OBJECT public: + enum Theme { Light, Dark }; + explicit PlatformHelperAndroid(QObject *parent = nullptr); Q_INVOKABLE void requestPermissions() override; @@ -24,6 +26,10 @@ public: Q_INVOKABLE void vibrate(HapticsFeedback feedbackType) override; + void setTopPanelColor(const QColor &color) override; + void setTopPanelTheme(Theme theme); + void setBottomPanelColor(const QColor &color) override; + private: static void permissionRequestFinished(const QtAndroid::PermissionResultMap &); diff --git a/nymea-app/platformintegration/ios/platformhelperios.cpp b/nymea-app/platformintegration/ios/platformhelperios.cpp index d0fc8945..7b41b420 100644 --- a/nymea-app/platformintegration/ios/platformhelperios.cpp +++ b/nymea-app/platformintegration/ios/platformhelperios.cpp @@ -1,10 +1,16 @@ #include "platformhelperios.h" #include #include - +#include +#include PlatformHelperIOS::PlatformHelperIOS(QObject *parent) : PlatformHelper(parent) { + QScreen *screen = qApp->primaryScreen(); + screen->setOrientationUpdateMask(Qt::PortraitOrientation | Qt::LandscapeOrientation | Qt::InvertedPortraitOrientation | Qt::InvertedLandscapeOrientation); + QObject::connect(screen, &QScreen::orientationChanged, qApp, [this](Qt::ScreenOrientation) { + setBottomPanelColor(bottomPanelColor()); + }); } @@ -83,6 +89,13 @@ void PlatformHelperIOS::setTopPanelColor(const QColor &color) void PlatformHelperIOS::setBottomPanelColor(const QColor &color) { PlatformHelper::setBottomPanelColor(color); - setBottomPanelColorInternal(color); + + // In landscape, ignore settings and keep it to black. On notched devices it'll look crap otherwise + if (qApp->primaryScreen()->orientation() == Qt::LandscapeOrientation || qApp->primaryScreen()->orientation() == Qt::InvertedLandscapeOrientation) { + setBottomPanelColorInternal(QColor("black")); + } else { + setBottomPanelColorInternal(color); + } + } diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 7d9fcc05..ef7653ad 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -14,6 +14,7 @@ ApplicationWindow { minimumWidth: 360 minimumHeight: 480 visibility: kioskMode ? ApplicationWindow.FullScreen : settings.viewMode + color: Material.background // Those variables must be present in the Style title: appName @@ -49,6 +50,8 @@ ApplicationWindow { Component.onCompleted: { styleController.setSystemFont(app.font) + PlatformHelper.topPanelColor = app.primaryColor + PlatformHelper.bottomPanelColor = Material.background } RootItem { diff --git a/nymea-app/ui/RootItem.qml b/nymea-app/ui/RootItem.qml index f60d5d28..ce78b9e1 100644 --- a/nymea-app/ui/RootItem.qml +++ b/nymea-app/ui/RootItem.qml @@ -10,17 +10,6 @@ import "connection" Item { id: root - // Workaround flickering on pageStack animations when the white background shines through - Rectangle { - anchors.fill: parent - color: Material.background - - Component.onCompleted: { - PlatformHelper.topPanelColor = app.primaryColor - PlatformHelper.bottomPanelColor = color - } - } - function handleAndroidBackButton() { return swipeView.currentItem.handleAndroidBackButton() }