Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus
-
Problem
I want a simple Qt Quick app that does NOT draw under the notch / status bar / nav bar. I’m not going for immersive; I’m not setting
Qt.ExpandedClientAreaHint
. I bind my layout margins toSafeArea.margins.*
(similar to the Qt 6.9 blog post “Expanded Client Areas & Safe Areas” by Tor Arne Vestbø).Issue: On Android (targetSdk 35), at cold start my content still shows under the system bars. Debug logs show
SafeArea.margins = 0
. As soon as I tap a TextField (IME shows), SafeArea updates to non-zero and the layout snaps to the correct padded position.So it seems
SafeArea
isn’t initialized with valid insets until the first insets/resize event.Minimal-ish Repro (closer to my real app)
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtCore Window { id: root visible: true width: 360 height: 640 title: "Demo" // design padding in addition to SafeArea property int designPadding: 12 // SafeArea bindings property real safeTop: SafeArea.margins.top property real safeBottom: SafeArea.margins.bottom property real safeLeft: SafeArea.margins.left property real safeRight: SafeArea.margins.right // Debug: watch SafeArea Timer { interval: 500; running: true; repeat: true onTriggered: console.log("[safe]", root.safeTop, root.safeBottom, root.safeLeft, root.safeRight) } // Pretend persistent settings (trimmed) Settings { id: saved property string host: "" property string port: "" } // Layout that should be padded out of unsafe areas ColumnLayout { anchors.fill: parent anchors.topMargin: root.designPadding + root.safeTop anchors.bottomMargin: root.designPadding + root.safeBottom anchors.leftMargin: root.designPadding + root.safeLeft anchors.rightMargin: root.designPadding + root.safeRight spacing: 10 Label { text: "App" font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter } TextField { id: hostInput Layout.fillWidth: true placeholderText: "Host" text: saved.host } TextField { id: portInput Layout.fillWidth: true placeholderText: "Port" text: saved.port.length ? saved.port : "5300" } Item { Layout.fillHeight: true } Button { text: "Connect" Layout.fillWidth: true } } }
Observed logs:
• Before tapping input: all SafeArea margins 0; content under status bar.
• After tapping input (IME): SafeArea margins become non-zero; layout correct.⸻
Extra: I tried forcing a 1-px geometry “nudge” after visible (resize there & back) to provoke inset delivery; did not help reliably.
Is this expected behavior for SafeArea on Android with a plain Window?
Should I be waiting for a specific signal, or just switch to ApplicationWindow for early safe-area padding?
If this looks like a bug/regression, happy to file a Qt bug report — let me know what data would help.Thanks!
-
Problem
I want a simple Qt Quick app that does NOT draw under the notch / status bar / nav bar. I’m not going for immersive; I’m not setting
Qt.ExpandedClientAreaHint
. I bind my layout margins toSafeArea.margins.*
(similar to the Qt 6.9 blog post “Expanded Client Areas & Safe Areas” by Tor Arne Vestbø).Issue: On Android (targetSdk 35), at cold start my content still shows under the system bars. Debug logs show
SafeArea.margins = 0
. As soon as I tap a TextField (IME shows), SafeArea updates to non-zero and the layout snaps to the correct padded position.So it seems
SafeArea
isn’t initialized with valid insets until the first insets/resize event.Minimal-ish Repro (closer to my real app)
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtCore Window { id: root visible: true width: 360 height: 640 title: "Demo" // design padding in addition to SafeArea property int designPadding: 12 // SafeArea bindings property real safeTop: SafeArea.margins.top property real safeBottom: SafeArea.margins.bottom property real safeLeft: SafeArea.margins.left property real safeRight: SafeArea.margins.right // Debug: watch SafeArea Timer { interval: 500; running: true; repeat: true onTriggered: console.log("[safe]", root.safeTop, root.safeBottom, root.safeLeft, root.safeRight) } // Pretend persistent settings (trimmed) Settings { id: saved property string host: "" property string port: "" } // Layout that should be padded out of unsafe areas ColumnLayout { anchors.fill: parent anchors.topMargin: root.designPadding + root.safeTop anchors.bottomMargin: root.designPadding + root.safeBottom anchors.leftMargin: root.designPadding + root.safeLeft anchors.rightMargin: root.designPadding + root.safeRight spacing: 10 Label { text: "App" font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter } TextField { id: hostInput Layout.fillWidth: true placeholderText: "Host" text: saved.host } TextField { id: portInput Layout.fillWidth: true placeholderText: "Port" text: saved.port.length ? saved.port : "5300" } Item { Layout.fillHeight: true } Button { text: "Connect" Layout.fillWidth: true } } }
Observed logs:
• Before tapping input: all SafeArea margins 0; content under status bar.
• After tapping input (IME): SafeArea margins become non-zero; layout correct.⸻
Extra: I tried forcing a 1-px geometry “nudge” after visible (resize there & back) to provoke inset delivery; did not help reliably.
Is this expected behavior for SafeArea on Android with a plain Window?
Should I be waiting for a specific signal, or just switch to ApplicationWindow for early safe-area padding?
If this looks like a bug/regression, happy to file a Qt bug report — let me know what data would help.Thanks!
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2 -
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2Thanks, @ekkescorner
Unfortunately for me is not working, hope 6.9.2 will be released soon.
Thanks! -
@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2Thanks, @ekkescorner
Unfortunately for me is not working, hope 6.9.2 will be released soon.
Thanks!@Pann sorry I forgot these lines
in ApplicationWindow:flags: Qt.platform.os === "android"? Qt.Window : Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint
and Component.onCompleted:
if(Qt.platform.os === "android") { window.flags = Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint window.visibility = Window.Windowed }
-
I've tried this solution (currently working with Qt 6.10)... and it has no effect.
My app STILL shows up under the Status Bar and Navigation Bar on startup... Rotating to landscape and back fixes this... but, when in landscape, it shows up under the Nav Bar, but not the Status Bar. -
just noticed that my workaround isn't always working :(
runs on Android 14 Motorola Device, Android 13 Samsung Device,
but fails on Android 15 Pixel9a Device
seems we have to wait for 6.9.2: https://bugreports.qt.io/browse/QTBUG-135808 -
I actually react on the onCompleted
Component.onCompleted: { applyNewMargins() }
to fetch the safe area margins
function applyNewMargins(){ if(isMobile){ var map = safeMargins.getSafeAreaMargins(mainWindow) safeMarginLeft = map["left"] * 2 / 3 safeMarginRight = map["right"] * 2 / 3 safeMarginTop = map["top"] * 2 / 3 safeMarginBottom = map["bottom"] * 2 / 3 } }
from my c++ backend. Haven't noticed any new timing issues. But this was ma solution way back in the day where the margins weren't available on application start. Don't see any flickering either
-
thx for the info.
I want to use the Qt 6.9 SafeArea. works well on iOS and hopefully with 6.9.2 on Android, too - so ATM I'll wait for 6.9.2 -
BTW: if you want to opt-out from Android-35 edge-to-edge
you have to add styles.xml and add in Manifest... activity... android:theme="@style/NormalTheme"
see the details here:
https://codereview.qt-project.org/c/qt/qtbase/+/630376 -
BTW: if you want to opt-out from Android-35 edge-to-edge
you have to add styles.xml and add in Manifest... activity... android:theme="@style/NormalTheme"
see the details here:
https://codereview.qt-project.org/c/qt/qtbase/+/630376@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
BTW: if you want to opt-out from Android-35 edge-to-edge
you have to add styles.xml and add in Manifest... activity... android:theme="@style/NormalTheme"
see the details here:
https://codereview.qt-project.org/c/qt/qtbase/+/630376This worked for me...Thanks!
-
@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
BTW: if you want to opt-out from Android-35 edge-to-edge
you have to add styles.xml and add in Manifest... activity... android:theme="@style/NormalTheme"
see the details here:
https://codereview.qt-project.org/c/qt/qtbase/+/630376This worked for me...Thanks!
@BTSTOnline cool :)