MobileUI allows QML applications to interact with Mobile specific features, like Android and iOS status bar and Android navigation bar.
You can see it in action in the MobileUI demo.
Supports Qt6 with CMake and QMake.
Supports iOS 11+ (tested up to iOS 17.5 devices).
Supports Android API 21+ (tested up to API 34 devices).
- Set Android
status barandnavigation barcolors and theme - Set iOS
status bartheme (iOS has no notion of status bar color, and has no navigation bar) - Get device theme (light or dark mode)
- Get device
safe areas - Lock screensaver
- Set screen orientation
- Set screen brightness
- Trigger haptic feedback (vibration)
- Android back button helper
To get started, simply checkout the MobileUI repository as a submodule, or copy the
MobileUI directory into your project, then include the library files with either
the CMakeLists.txt CMake project file or the MobileUI.pro QMake project file.
add_subdirectory(MobileUI/)
target_link_libraries(${PROJECT_NAME} MobileUI::MobileUI)include(MobileUI/MobileUI.pri)First, you need to register the MobileUI QML module in your C++ main.cpp file.
You can also use MobileUI directly in the C++ code if you want to.
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <MobileUI>
int main() {
QGuiApplication app();
MobileUI::registerQML(); // that is required
MobileUI::setStatusbarColor("white"); // use it directly if you want
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}Example usage in QML:
import QtQuick
import MobileUI
Window {
MobileUI {
id: mobileUI
statusbarColor: "white"
statusbarTheme: MobileUI.Light
navbarColor: "white"
navbarTheme: MobileUI.Light
}
}- It looks like forcing the screen orientation on an iPad is not allowed.
-
Transition between the splash screen and the application window will glitch. As far as I know there is no way to fix that.
You'll see the window beeing resized (more or less the size of the status bar), and the status bar changing color, usually to black, but you might be lucky and get a light grey depending on your device. It's bad if you're coming from a white splash screen, seeing a black bar appear, and going to a white application background... -
The infamous "white bar" bug (a white line visible between the Android status bar and the Qt appliation content) make the "regular" window mode pretty much useless (pre Qt 6.7).
-
Screen rotation is mostly broken (pre Qt 6.7).
-
Keyboard always appears when an application is brought back to the foreground if
android:windowSoftInputMode="adjustResize"is set in the manifest (Qt 6.7). -
Keyboard doesn't resize/adjust the app view when appearing. (Qt 6.7).
-
Switching dynamically between the three window modes is very glitchy, and not advised. Especially between the "regular" mode and the other twos.
-
When using the "Regular with transparent bars" window mode, screen rotation will break presentation if no status bar color has been set. Setting a transparent color seems to be enough to fix the issue.
-
When using Qt 6.9 / 6.10, Qt has introduced its own "SafeArea" system. Because it's still fairly buggy, I would advise not to use it yet, and for that you'll need to use regular
Windowinstead ofApplicationWindowQML item.
All in all, window modes, geometry, rotation and many smaller things are just very buggy on Android, and subtly broken depending on which Qt version is used.
There are three modes you can use on Android and iOS applications:
Window {
flags: Qt.Window
visibility: Window.AutomaticVisibility
}- Black status bar on iOS (you can't change that).
- User can set colors for both status and navigation bars on Android.
- Available geometry is fullscreen - system bars height.
- No need to handle safe areas.
That is the default mode on Android, but the infamous "white bar" bug make it pretty much useless (pre Qt 6.7.x).
Window {
flags: Qt.Window | Qt.MaximizeUsingFullscreenGeometryHint
visibility: Window.AutomaticVisibility
}- The status bar is transparent on iOS, and you can choose the theme. Your application can draw a bar "manually" to visualize it.
- The status bar is transparent on Android, and you can choose the theme. Your application can draw a bar "manually" to visualize it, or force a system bar color (it will be drawn above everyting).
- The navigation bar is transparent on Android, and you can choose the theme. MobileUI will prevent you from forcing a color, because that would change the windows mode back to "regular", but not really.
- Available geometry is the full screen, including what's behind system bars.
That is the default mode on iOS.
Window {
flags: Qt.Window | Qt.MaximizeUsingFullscreenGeometryHint
visibility: Window.FullScreen
}- No system bars drawn at all.
- Available geometry is the full screen.
"Regular with transparent bars" is really the mode I would recommend. It offers the most flexibility, but you'll need to handle the space occupied by the status and navigation bars yourself.
Switching dynamically between the three modes on Android is very glitchy, and not advised. Especially between the "regular" mode and the other two.
All in all, window modes and window geometry are just very buggy on Android, and subtly broken depending on which Qt version is used.
statusbarColor
Set the status bar color (if available).
This is a QColor, so you can use a hexadecimal value "#fff" or even a named color "red". And you can use "transparent" too.
Settings a color will also set a theme, by automatically evaluating if the bar color is more light or dark. You can force a theme if you are not satisfied by the result.
statusbarTheme
Set the status bar theme explicitly, MobileUI.Light or MobileUI.Dark.
On iOS and Android API 28+, the theme must be set each time the window visibility or orientation changes. This is done automatically.
navbarColor
Set the navigation bar color (if available).
This is a QColor, so you can use a hexadecimal value "#fff" or even a named color "red". And you can use "transparent" too.
Settings a color will also set a theme, by automatically evaluating if the bar color is more light or dark. You can force a theme if you are not satisfied by the result.
navbarTheme
Set the navigation bar theme explicitly, MobileUI.Light or MobileUI.Dark.
On Android API 28+, the theme must be set each time the window visibility or orientation changes. This is done automatically.
deviceTheme
You can get the device OS theme by reading the deviceTheme property.
MobileUI doesn't listen to the change affecting this value and won't signal you when it's changed.
You should probably not switch your app theme while it's being used anyway, so it may be wise to only check this value when the application is loading or brought back to the foreground.
Connections {
target: Qt.application
function onStateChanged() {
case Qt.ApplicationActive:
console.log("device theme (%1)".arg(mobileUI.deviceTheme ? "dark" : "light"))
break
}
}Safe areas handling is not straightforward, unfortunately. Most of it will be left into your care.
statusbarHeight
navbarHeight
Status bar and navigation bar size, in pixels. These values do not change when the screen is rotated.
Status bar is always on top of the screen when visible.
The navigation bar can be left/right of the screen, when the phone is rotated.
safeAreaTop
safeAreaLeft
safeAreaRight
safeAreaBottom
These values are what's returned by the OS, and you'll need to understand what's what, depending on what window mode and screen rotation you're in, and especially, what do you want to do with them depending on the need of your application.
These values are changed by the OS when the screen is rotated.
Either call setScreenAlwaysOn(true/false) or set screenAlwaysOn: true/false in QML.
This will disable/enable the device screensaver.
mobileUI.setScreenAlwaysOn(true)
mobileUI.screenAlwaysOn: trueThis will force the device screen orientation into one of the available values. This cannot be used to read the actual device orientation.
Either call setScreenOrientation(MobileUI.ScreenOrientation) or set screenOrientation: MobileUI.ScreenOrientation in QML.
mobileUI.setScreenOrientation(MobileUI.Landscape_left)
mobileUI.screenOrientation: MobileUI.Landscape_rightAvailable orientations:
Unlocked
Portrait
Portrait_upsidedown // only available on Android?
Portrait_sensor // only available on Android
Landscape_left
Landscape_right
Landscape_sensor // only available on Android
Set screen brightness for the currently running application (on Android) or system wide (on iOS).
Slider {
from: 0
to: 100
value: mobileUI.screenBrightness
onMoved: mobileUI.screenBrightness = value
}Produce a simple haptic feedback, called "notification feedback" on iOS or a "tick" on Android.
No model of iPad includes a haptic engine. Android tablets usually have one.
mobileUI.vibrate()You can use this method to bypass the default behavior for the Android back button, which is to kill the application instead of doing what every single Android application does, going back to the home screen...
Either use it on your application window 'onClosing' signal:
onClosing: (close) => {
if (Qt.platform.os == "android") {
close.accepted = false
mobileUI.backToHomeScreen()
}
}Or on an appropriate 'onBackPressed' signal:
Keys.onBackPressed: {
mobileUI.backToHomeScreen()
}Going back to the home screen from an application is not possible on iOS, and thus this function does nothing.
This project is licensed under the MIT license.
This project is based on qtstatusbar by jpnurmi.
