拡大クライアント領域とセーフ領域

本稿は「Expanded Client Areas and Safe Areas」の抄訳です。
 

デスクトップおよびモバイルにおける現代的なアプリケーション設計の主流は、コンテンツが前面に表示され、中心となることです。アプリケーションやシステムのUI要素がコンテンツにシームレスに融合し、邪魔にならないように表示されます。ここでは、この目的を達成するQt 6.9の2つの新機能、拡大されたクライアント領域とセーフ領域について説明します。

拡大されたクライアント領域

例えば、愛犬家のためのアプリケーションを構築し、お気に入りの写真を展示するとします。最小限のアプリケーションは、以下のようなものになるでしょう。

import QtQuick

Window {
    visible: true
    width: 800; height: 600
    Image {
    	anchors.fill: parent
        source: "https://placedog.net/800/600?r"
        fillMode: Image.PreserveAspectCrop
    }
}

これにより、macOSとiOSでは以下のように表示されます。

     

今のところは順調で、犬がほぼ正面中央に表示されています。しかし、注目を競い合うUI要素がいくつかあります。すなわち、macOSではウィンドウのタイトルバーとコントロール、iOSでは時計、Wi-Fi、バッテリーステータスです。もっとうまくできます!

Qt.ExpandedClientAreaHint ウィンドウフラグを追加することで、通常はシステム UI 要素用に確保されている領域にウィンドウのクライアント領域を拡張するように要求することができます。

Window {
    flags: Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint
    // ...
}

macOS でタイトルバーを非表示にするために、Qt.NoTitleBarBackgroundHint も追加しました。これらを組み合わせると、次のようになります。

.    .

ずいぶん良くなりました!コンテンツが画面いっぱいに広がり、愛犬の金色の毛並みに完全にフォーカスできるようになりました。

セーフエリア

クライアント領域が拡大したことで、責任も拡大しました。アプリケーションは現在、システム UI やコントロールと同じ画面領域を争っていますが、通常はシステム UI が優先されます。つまり、システム UI が重なりそうな領域に重要なコンテンツを配置しないよう注意する必要があります。そうしないと、ユーザーがコンテンツを見たり、コンテンツとやりとりしたりできなくなるからです。

例えば、外出中に犬とやりとりできる機能を導入したいとします。

Window {
    // ...
    Item {
        anchors {
            left: parent.left; right: parent.right; top: parent.top
            margins: 10
        }
        Text {
            text: "🎾 Throw Ball"; color: "white"; font.pointSize: 18
            anchors. left: parent.left
        }
        Text {
            text: "Give Bone 🦴"; color: "white"; font.pointSize: 18
            anchors. right: parent.right
        }
    }
}

しかし、これはmacOSとiOSの両方でシステムUIと衝突します。

これを処理するために、新しいSafeAreaアタッチドプロパティを使用します。このプロパティは、ウィンドウの「安全ではない」領域を避けるためにコンテンツをどれだけ内側に配置する必要があるかを示します。

anchors {
    left: parent.left; right: parent.right; top: parent.top
    topMargin: 10 + parent.SafeArea.margins.top
    leftMargin: 10 + parent.SafeArea.margins.left
    rightMargin: 10 + parent.SafeArea.margins.right
}

これにより、macOSではボタンがタイトルバーの下に安全に配置されます。 

また、iOSではステータスバーから離れた位置に配置されます。

お気づきかもしれませんが、左右のセーフエリアマージンを含めることで、ランドスケープモードにも対応しています。

Qt Quick Controls

これまでの例では、シンプルな Qt Quick Window を使用してきましたが、より現実的な例では、セーフエリアの処理にいくつかの追加機能を備えた Qt Quick Controls の ApplicationWindow を使用することになるでしょう。

Qt.ExpandedClientAreaHint ウィンドウフラグが設定されている場合、ウィンドウのbackgroundは自動的にウィンドウ全体に拡張され、その一方で、contentItem に追加されたコンテンツはウィンドウのセーフエリア内に維持されます。

ウィンドウのheaderfootermenuBar については、通常は安全領域の処理を自分で行う必要があります。しかし、ビルトインのToolBar と MenuBarタイプにいくつかのトリックを教えたので、次のコードでは、ツールバーのコンテンツを安全領域内に維持しながら、ツールバーの背景を自動的に画面の上端まで拡張します。

ApplicationWindow {
    visible: true
    width: 500; height: 700
    flags: Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint

    header: ToolBar {
        background: Rectangle {
            gradient: Gradient.PremiumDark
            opacity: 0.7
        }
        RowLayout {
            anchors.fill: parent
            Text {
                text: "🎾 Throw Ball"; color: "white"; font.pointSize: 18
                Layout.margins: 10
            }
            Text {
                text: "Give Bone 🦴"; color: "white"; font.pointSize: 18
                Layout.alignment: Qt.AlignRight; Layout.margins: 10
            }
        }
    }
    
    // ...
}

最後に、アプリケーションウィンドウに、意図的にウィンドウの非安全領域に拡張したいコンテンツがある場合、例えば、ウィンドウのpaddingプロパティをオーバーライドすることで、そのようにすることができます。

ApplicationWindow {
    // ...
    topPadding: 0

    ListView {
        id: listView
        anchors.fill: parent
        model: 10
        delegate: Image {
            required property int index
            width: listView.width; height: 250
            source: "https://placedog.net/500/250?id=" + (index + 1)
        }
        topMargin: SafeArea.margins.top

        onTopMarginChanged: {
            // Keep content position stable
            if (!dragging && atYBeginning)
                contentY = -topMargin
        }
    }
}

これは、ツールバーの下のリストビューを、セーフエリア外にまで拡張しますが、リストビューの原点をツールバーの真下に配置することで、セーフエリアのマージンを考慮します。

Simulator Screen Recording - iPhone 16 Pro - 2025-03-26 at 16.39.18-1

これは、ツールバー自体が、システムによって報告されたセーフエリアのマージンを越えて拡張するツールバーの任意の部分について、追加のセーフエリアのマージンを報告するため機能します。また、これらの追加のマージンは、ListViewがセーフエリアのマージンを照会する際に考慮されます。事実上、ListViewはセーフエリアのマージンがどこから来ているかに関係なく動作します。

このテクニックを使用して、コンテナの非セーフエリアをその子要素に反映するコンテナコンポーネントを構築することができます。子要素のレイアウトでセーフエリアマージンを尊重するかどうか、またどのように尊重するかを子要素に決定させることができます。

今後の展望

Qt 6.9の変更により、QtアプリケーションでこれらのUIパラダイムを有効にするための大きな一歩を踏み出せたことを期待しています。

これらの機能は、macOS、Windows、iOS、visionOS、Androidで利用可能であり、サポートされています。また、サポート対象のその他のプラットフォームへのサポート追加も検討しています。

.   

また、落ち着き次第、AndroidやiOSなどの一部のプラットフォームで、Qt.ExpandedClientAreaHintを自動的に有効にする予定です。

テストを行い、問題が見つかった場合は当社までお知らせください。また、既存のAPIで対応できないユースケースがある場合もお知らせください。


Blog Topics:

Comments