ウィンドウ管理

ChromeOS は複数のウィンドウで Android アプリをサポートします。図 1 に示すように、システムはアプリをウィンドウ コンテナにレンダリングします。そのサイズはデバイスのフォーム ファクタによって決まります。

図 1. さまざまなデバイスのアプリ ウィンドウ。

さまざまな画面サイズで動作するレイアウトを設計することが重要です。また、Android のガイドラインに沿って各種の画面サイズをサポートしていれば、ChromeOS でもアプリが適切に動作します。

このページでは、アプリのウィンドウが正常に起動し、スムーズにサイズ変更され、サイズが変更されたときにすべてのコンテンツが表示されることを確認する方法について説明します。

初期起動サイズ

アプリは次の方法で初回起動サイズをリクエストできます。

  • パソコン環境でのみ起動サイズを使用する。これにより、ウィンドウ マネージャから適切な表示範囲と向きが示されます。デスクトップ モード用のカスタマイズ設定を指定するには、<activity> 内に次のメタタグを追加します。
<meta-data android:name="WindowManagerPreference:FreeformWindowSize"
           android:value="[phone|tablet|maximize]" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation"
           android:value="[portrait|landscape]" />
  • 静的な起動サイズを使用する。アクティビティのマニフェスト エントリ内で <layout> を使用して、次の例のように「固定」の開始サイズを指定します。
<layout android:defaultHeight="500dp"
            android:defaultWidth="600dp"
            android:gravity="top|end"
            android:minHeight="450dp"
            android:minWidth="300dp" />
  • 動的な起動サイズを使用する。新しいアクティビティの作成時に、ActivityOptions.setLaunchBounds(Rect) を作成して使用します。空の四角形を指定すると、アプリを最大化できます。

ウィンドウのサイズを変更

ChromeOS では、ユーザーは通常どおり、図 2 に示すように右下隅をドラッグしてアプリのウィンドウのサイズを変更できます。

図 2. サイズ変更可能なアプリ ウィンドウ。

View クラスを使用する際、ウィンドウのサイズ変更を処理するには、次の 2 つの方法があります。

  • onConfigurationChanged(..) を呼び出すことで、構成の変更に動的に対応できます。たとえば、アクティビティのマニフェストに android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" を追加できます。構成変更の処理について詳しくは、構成の変更の処理をご覧ください。
  • システムにアクティビティを再起動させる。この場合は、onSaveInstanceState を実装し、ViewModel アーキテクチャ コンポーネントを使用して、以前に保存した状態を復元します。

Jetpack Compose を使用する場合、サイズ変更の動作はアクティビティの構成方法によって異なります。変更を動的に処理する場合は、ウィンドウ サイズが変更されたときに再コンポーズがトリガーされます。アクティビティがシステムによって再起動された場合、再起動後に初回合成が行われます。いずれにしても、ウィンドウ サイズの変化に適応する Compose レイアウトを作成することが重要です。固定サイズを想定しないでください。

ウィンドウのサイズ

アクティビティを開始するたびに、現在の構成に沿ってコンテンツを配置するウィンドウの寸法を読み取ります。

現在の構成を確認するには、現在のアクティビティで getResources().getConfiguration() を呼び出します。バックグラウンド アクティビティやシステム リソースの構成は使用しないでください。バックグラウンド アクティビティにはサイズがなく、システム構成にはサイズと向きが競合する複数のウィンドウが含まれている可能性があるため、使用可能なデータを抽出できません。

ウィンドウのサイズと画面のサイズは同じではないことにご注意ください。DP 単位のウィンドウ サイズを取得するには、Activity.getResources().getConfiguration().screenWidthActivity.getResources().getConfiguration().screenHeight を使用します。画面サイズを使用する必要はおそらくありません。

コンテンツ境界

ウィンドウのコンテンツ境界は、サイズ変更後に変更される可能性があります。たとえば、ウィンドウが大きくなりすぎて画面に収まらない場合、アプリが使用するウィンドウ内の領域が変更されます。次のガイドラインに従ってください。

  • Android のレイアウト プロセスを使用するアプリは、使用可能なスペースに自動的に配置されます。
  • ネイティブ アプリは、アクセスできない UI 要素を避けるために、利用可能な領域を読み取り、サイズ変更をモニタリングする必要があります。以下のメソッドを呼び出して、このサーフェスの使用可能な初期サイズを決定します。

    • NativeActivity.mLastContent[X/Y/Width/Height]()
    • findViewById(android.R.id.content).get[Width/Height]()

    継続的なモニタリングはオブザーバーを使用して実行できます。

    • NativeActivity.onContentRectChangedNative()
    • NativeActivity.onGlobalLayout()
    • view.addOnLayoutChangeListener(findViewById(android.R.id.content)) にリスナーを追加する

    アプリがアートワークを事前スケーリングしている場合は、解像度が変わるたびに調整します。

フリーフォームのサイズ変更

ChromeOS では、任意のウィンドウのサイズを自由に変更できます。ユーザーはウィンドウの幅、高さ、画面上の位置を変更できます。多くの Android アプリは、フリーフォームのサイズ変更を意識せずに作成されています。以下の問題を考慮してください。

  • 画面の位置が変わることがあります。ウィンドウから画面への座標変換と画面からウィンドウへの座標変換は、常にシステムによって行われます。
  • Android のビューシステムを使用している場合、ウィンドウのサイズが変更されるとウィンドウ レイアウトが自動的に変更されます。
  • ビューシステムを使用せずにサーフェスを引き継ぐ場合は、アプリが独自にサイズ変更を処理する必要があります。
  • ネイティブ アプリの場合は、mLastContent メンバーを使用するか、コンテンツ ビューを使用して初期サイズを決定します。
  • アプリの実行中に onContentRectChangedNative イベントまたは onGlobalLayout イベントをリッスンしてサイズ変更に対応します。
  • アプリのサイズが変更されたら、レイアウトとアートワークを再スケーリングまたは再読み込みして、入力領域を更新します。

全画面モード

全画面モードは、ストックの Android と同じように動作します。 ウィンドウが全画面表示を覆っていない場合、全画面(すべてのシステム UI 要素を非表示にする)のリクエストは無視されます。アプリを最大化すると、通常の全画面表示のメソッド、レイアウト、関数が実行されます。これにより、システム UI 要素(ウィンドウ コントロール バーとシェルフ)が非表示になります。

画面の向き

Android アプリの最も一般的な向きは、スマートフォンの通常の持ち方に合わせて、縦向きです。縦向きはスマートフォンには適していますが、横向きが通常であるノートパソコンとタブレットには適していません。アプリに最適な結果を得るには、両方の向きをサポートすることを検討してください。

一部の Android アプリでは、デバイスがポートレート モードになっているとき、回転値が Surface.ROTATION_0 であると想定されます。これは、ほとんどの Android デバイスに当てはまります。ただし、アプリが特定の ARC モードの場合、縦向きの回転値が Surface.ROTATION_0 にならないことがあります。

加速度計などのセンサーを読み取りながら正確な回転値を取得するには、Display.getRotation() メソッドを使用し、それに応じて軸を入れ替えます。

ルート アクティビティと向き

Chromebook のウィンドウは、アクティビティ ウィンドウのスタックで構成されます。スタック内の各ウィンドウは、同じサイズと向きを持ちます。

パソコン環境では、向きとサイズが突然変わるとユーザーは混乱します。Chromebook ウィンドウ マネージャーは、Android の横並びモードと同様に、このような状況を回避します。つまり、スタックの一番下にあるアクティビティが、その上にあるすべてのアクティビティの属性を制御します。これにより、新たに開始された縦向きでサイズ変更不可のアクティビティが横向きでサイズ変更可能になるという、予期しない状況が発生する可能性があります。

ここでデバイスモードが効果を発揮します。タブレット モードでは画面の向きはロックされず、Android の通常のように各ウィンドウがそれぞれの向きを保持します。

向きに関するガイドライン

向きを処理する際のガイドラインは次のとおりです。

  • 1 つの向きだけをサポートする場合は、そのことがアプリの起動前にウィンドウ マネージャによって認識されるように、マニフェストに情報を追加します。向きを指定する場合は、可能な限りセンサーの向きも指定します。Chromebook はコンバーチブル型であることが多く、アプリが逆さまだとユーザー エクスペリエンスが低下します。
  • 選択された 1 つの向きを維持するようにします。マニフェストで 1 つの向きをリクエストした後、プログラムで別の向きを設定することは避けてください。
  • ウィンドウのサイズに基づいて向きを変更する際には注意が必要です。ユーザーは小さな縦向きのウィンドウに行き詰まり、大きな横向きのウィンドウに戻れなくなる可能性があります。
  • Chrome には、すべての使用可能なレイアウトを切り替えられるウィンドウ コントロールがあります。正しい向きのオプションを選択すると、アプリを起動した後でも適切なレイアウトになります。アプリを縦向きと横向きで利用できる場合は、可能であれば、デフォルトで横向きにします。このオプションの設定は、アプリごとに保存されます。
  • 向きの変更はできるだけ避けるようにします。たとえば、アクティビティの向きが縦向きで、アプリが実行時に setRequestedOrientation(LANDSCAPE) を呼び出した場合、不必要なウィンドウ サイズ変更が発生します。これはユーザーにとって煩わしく、アプリが処理できないアプリを再起動する可能性があります。向きはマニフェストなどで一度だけ設定し、必要な場合にのみ変更することをおすすめします。

その他の考慮事項

ChromeOS で Android アプリを使用する際は、次の点にも注意してください。

  • アクティビティの onDestroy メソッドで finish() を呼び出さないでください。これにより、サイズ変更時にアプリは閉じられますが、再起動はされません。
  • TYPE_KEYGUARDTYPE_APPLICATION_MEDIA など、互換性のないウィンドウ タイプは使用しないでください。
  • 以前に割り当てられたオブジェクトをキャッシュに保存することで、アクティビティを迅速に再起動します。
  • ユーザーにアプリのサイズ変更を許可しない場合は、マニフェスト ファイルで android:resizeableActivity=false を指定します。
  • アプリをテストして、ウィンドウのサイズ変更が適切に処理されることを確認してください。