I've noticed that starting version 5.4 of the Map Viewer template fills the top notch and bottom "chin" areas on my iPhone 12, the area around the notch gets the custom background color and the map fills the whole bottom area. The older version of the app just had a black bar at the bottom and the status bar area is black as well, my custom app has the same behavior. I have been looking at the code for the newer version if Map Viewer, but I can't figure out how they got it to display in these areas.
I copied the code for detecting if a notch exists based on the device name, and tried setting a header Toolbar on the page with the height and topPadding set based on notchHeight like in the template's code. However, in my app the header still displays below the notch area.
Is there some other settings or special trick to get the app to fill these areas of the screen?
Solved! Go to Solution.
@TrevorFrameI finally figured this out and now feel slightly silly. In appinfo.json you need to manually set the property:
"statusBar": true,
within the "display" group. I had read something about setting the statusbar property but i thought that this was set automatically by "status bar" toggle in the devices section of the settings menu in AppStudio. After setting "statusBar": true, the app displays in the status bar area around the notch and in the bottom chin area.
Hi @JamesGough ,
You're on the right track of adjusting for notch based on the unix machine. The code you're looking for in Map Viewer is in /views/MapViewerApp.qml file. There is a property "notchHeight" which checks if the device is an iOS device and will adjust based on if the iOS device is portrait or landscape mode. This property is then referenced throughout the app to adjust the ToolBar or other component's heights. Something similar can be done for bottom indicators.
Best,
Trevor
Hey @TrevorFrame ,
Thanks for the reply. I have copied those properties and functions into my app's root component, but I'm having trouble figuring out how to use them to paint in the notch area.
When I look at the code StartPage.qml in the MapViewer app I don't see any usage of notchHeight (or any of the other iPhone specific properties) yet this page does display full screen on my iPhone 12 including the notch and home-screen switcher at the bottom. How is this accomplished?
Looking at another page in MapViewer, GalleryPage.qml, I do see notchHeight being used here to set the topPadding and height for the ToolBar header Item. I tried doing this in my app, yet the ToolBar was just displayed below the notch area instead of extending into it.
Edit: I created a fresh sample app to make it easier to test this. See attached screenshot and code below.
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls.Material 2.1
import QtPositioning 5.3
import QtSensors 5.3
import ArcGIS.AppFramework 1.0
import Esri.ArcGISRuntime 100.14
import "controls" as Controls
//------------------------------------------------------------------------------
App {
id: app
width: 414
height: 736
function units(value) {
return AppFramework.displayScaleFactor * value
}
property real scaleFactor: AppFramework.displayScaleFactor
property int baseFontSize : app.info.propertyValue("baseFontSize", 15 * scaleFactor) + (isSmallScreen ? 0 : 3)
property bool isSmallScreen: (width || height) < units(400)
readonly property real heightOffset: isIphoneX ? app.units(20) : 0
readonly property real widthOffset: isIphoneX && isLandscape ? app.units(40) : 0
property bool isIphoneX: false
property bool isWindows7: false
property bool isIphoneXAndLandscape: isNotchAvailable() && !isPortrait
property real notchHeight: ( Qt.platform.os === "ios") ? ( isPortrait ? getHeightPortrait() : getHeightLandscape() ) : 0
property bool isPortrait: app.width < app.height
function getHeightLandscape() {
return isNotchAvailable() ? 0 : 20
}
function getHeightPortrait() {
return isNotchAvailable() ? 40 : 20
}
function isNotchAvailable(){
let unixName
if ( AppFramework.systemInformation.hasOwnProperty("unixMachine") )
unixName = AppFramework.systemInformation.unixMachine;
if ( typeof unixName === "undefined" )
return false
if ( unixName.match(/iPhone([1-9][0-9])/) ) {
switch ( unixName ){
case "iPhone10,1":
case "iPhone10,4":
case "iPhone10,2":
case "iPhone10,5":
case "iPhone12,8":
return false
default:
return true
}
}
return false
}
Page{
anchors.fill: parent
header: ToolBar{
id:header
width: parent.width
topPadding:app.isNotchAvailable() ? app.notchHeight : 0
height: app.isNotchAvailable() ? toolBarColumn.height + app.notchHeight : toolBarColumn.height
Material.background: "#8f499c"
Controls.HeaderBar{}
}
// sample starts here ------------------------------------------------------------------
contentItem: Rectangle{
anchors.top:header.bottom
MapView {
id:mapView
property real initialMapRotation: 0
anchors.fill:parent
rotationByPinchingEnabled: true
zoomByPinchingEnabled: true
locationDisplay {
positionSource: PositionSource {
}
}
// add a basemap
Map{
id:map
BasemapTopographic{}
initialViewpoint: ViewpointCenter {
id:initialViewpoint
center: Point {
x: -11e6
y: 6e6
spatialReference: SpatialReference {wkid: 102100}
}
targetScale: 9e7
}
}
}
}
}
Controls.DescriptionPage{
id:descPage
visible: false
}
}
This is from a personal app, not in any templates, but is a simple header bar tool bar that uses the iosnotch to offset the height of the header if the device is ios.
Use this to adjust the height of the header and there's a sample app called Status Bar that demonstrates how to change the status bar color to be consistent with the header bar color.
ToolBar {
width: parent.width
height: headerContentColumnLayout.height
Material.background: deviceManager.primaryColor
clip:true
property Item headerContent: null
ColumnLayout {
id: headerContentColumnLayout
width: parent.width
spacing: 0
// iOS status bar height offset
Item {
Layout.fillWidth: true
Layout.preferredHeight: headerContentItem.visible ? deviceManager.iOSHeightOffset : 0
}
// Header contentItem wrapper
Item {
id: headerContentItem
Layout.fillWidth: true
Layout.preferredHeight: visible ? deviceManager.headerHeight : 0
visible: headerContent
// Header contentItem [Can be replaced with any header contentItem that is passed in]
children: headerContent
}
}
Best,
Trevor
Hi @TrevorFrame , Thank you for the sample code. Do you have the code for deviceManager though?
ReferenceError: deviceManager is not defined
Edit: @TrevorFrame sorry realized that deviceManager is probably just the id of your app component.
I tested this on my iphone 12 and on an android device (Samsung Galaxy S10e).
On the iphone 12, same result as before. Header bar just displays below the notch area, also the status bar color does not change.
On the android device the status bar color does change.
Hi @JamesGough,
A couple things, can you test the Status Bar sample app to make sure the status bar coloring is working on your iPhone? If that works, try looking at how that's being implemented. Also, when testing your app with the iPhone, have you connected to the Console tool to see if any errors are output?
Best,
Trevor
Yeah I tested the Status Bar sample and I took the relevant code from there to set the StatusBar color and theme - wrapped my App component in AppLayout, added the following code into the AppLayout item
Component.onCompleted: {
StatusBar.theme = Material.Dark
StatusBar.color = Material.color(Material.Blue)
}
The weird thing is that in the StatusBar sample the status bar color does change on my iphone, but in my sample app it does not. For my android device it works in both apps.
The only errors i see in the console output is the warning about AppLayout being in beta and not officially supported.
@TrevorFrameI finally figured this out and now feel slightly silly. In appinfo.json you need to manually set the property:
"statusBar": true,
within the "display" group. I had read something about setting the statusbar property but i thought that this was set automatically by "status bar" toggle in the devices section of the settings menu in AppStudio. After setting "statusBar": true, the app displays in the status bar area around the notch and in the bottom chin area.
I'm glad you were able to figure it out. I can see how that can be missed and will relay this to the team to look into improving the feature.
I see now that it does mention that on the API documentation page for Platform.StatusBar but it's easy to miss for such an important detail! Anyway, thanks for all your help.