Select to view content in your preferred language

How to get app to display in notch and "chin" area in iPhone

2261
9
Jump to solution
11-10-2022 07:04 AM
JamesGough
Occasional Contributor

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?

0 Kudos
1 Solution

Accepted Solutions
JamesGough
Occasional Contributor

@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.

 

View solution in original post

0 Kudos
9 Replies
TrevorFrame
Esri Contributor

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

0 Kudos
JamesGough
Occasional Contributor

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
    }
}
0 Kudos
TrevorFrame
Esri Contributor

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

 

0 Kudos
JamesGough
Occasional Contributor

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.

 

0 Kudos
TrevorFrame
Esri Contributor

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

0 Kudos
JamesGough
Occasional Contributor

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.

0 Kudos
JamesGough
Occasional Contributor

@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.

 

0 Kudos
TrevorFrame
Esri Contributor

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. 

0 Kudos
JamesGough
Occasional Contributor

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.

0 Kudos