スマートフォンではアプリの向きを制限するが、大画面では制限しない

2 つ星評価アイコン

御社のアプリは縦向きのスマートフォンで最適に動作するため、アプリを縦向きのみに制限しているとします。しかし、横向きの大画面ではより多くの操作を行える可能性があります。

両方に対応するには、つまり、小さい画面ではアプリを縦向きに制限し、大画面では横向きを可能にするには、どうすればよいでしょうか。

ベスト プラクティス

優れたアプリは、ユーザーの好み(デバイスの向きなど)を尊重してくれます。

アダプティブ アプリの品質に関するガイドラインでは、アプリですべてのデバイス設定(縦向きと横向き、マルチ ウィンドウ モード、折りたたみ式デバイスの折りたたみ / 展開状態など)をサポートすることを推奨しています。アプリはさまざまな設定に対してレイアウトとユーザー インターフェースを最適化する必要があります。また、設定の変更時に状態を保存して復元する必要があります。

このレシピは、大画面をサポートするための一時的な手段です。アプリを改善してあらゆるデバイス設定を完全にサポートできるようになるまで、このレシピをご利用ください。

材料

  • screenOrientation: デバイスの向きの変化にアプリがどう反応するかを指定できるアプリ マニフェストの設定
  • Activity#setRequestedOrientation(): 実行時にアプリの向きを変更できるメソッド
  • LocalConfiguration: 現在のデバイスの Configuration を公開するコンポーザブル ローカル プロバイダ。DP で画面の寸法を読み取ることができます。
  • LaunchedEffect: キーが変更されたとき(この場合は構成が変更されたとき)にコードブロックを実行する Compose サイドエフェクト API。

手順

デフォルトでは、アプリがアプリ マニフェストで向きの変更を扱えるようにします。次に、実行時に Jetpack Compose を使用して、コンパクトな画面(スマートフォン)では向きを縦向きに動的に制限し、大画面ではすべての向きを許可します。

1. アプリ マニフェストで向きの設定を指定する

アプリ マニフェストの screenOrientation 要素を宣言しないか(この場合、画面の向きはデフォルトで unspecified になります)、画面の向きを fullUser に設定できます。ユーザーがセンサーベースの回転をロックしていない場合、アプリはすべてのデバイスの向きをサポートします。

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

unspecifiedfullUser の違いはわずかながらも重要です。screenOrientation の値を宣言しない場合、システムによって画面の向きが選択されます。画面の向きの定義に使用されるポリシーはデバイスによって異なる場合があります。一方、fullUser を指定すると、ユーザーがデバイスに定義した動作により近い動作になります。ユーザーがセンサーベースの回転をロックしている場合は、アプリはユーザーの設定に従います。それ以外の場合は、システムは 4 つある画面の向き(縦向き、横向き、縦向き(逆)、横向き(逆))のいずれかを許可します。android:screenOrientation をご覧ください。

2. Compose で向きを動的に制限する

Jetpack Compose では、LocalConfiguration.current から現在の画面の寸法を DP でリアクティブに読み取り、LaunchedEffect を使用して、構成が変更されるたびにアクティビティの向きを更新できます。

画面の幅または高さが 600dp(スマートフォンのコンパクト ブレークポイントに対応)未満の場合、向きを縦向きに制限します。それ以外の場合は、ユーザーの設定(unspecified または fullUser)に基づいてシステムがアプリを回転できるようにします。

コンパイル可能な完全な実装は次のとおりです。

val configuration = LocalConfiguration.current
val context = LocalActivity.current

LaunchedEffect(configuration) {
    val activity = context ?: return@LaunchedEffect
    // Determine if screen is compact (phone-sized) in either width or height
    val isCompact = configuration.screenWidthDp < 600 || configuration.screenHeightDp < 600
    activity.requestedOrientation = if (isCompact) {
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    } else {
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    }
}

LaunchedEffect(configuration) ブロック内にロジックを追加することで、アクティビティのサイズ変更、ディスプレイ間の移動、折りたたみ式デバイスの折りたたみ / 広げなど、アプリの設定が変更されるたびに、向きの設定をリアクティブにオーバーライドできるようになります。

構成の変更が発生するタイミングや、その変更によってアクティビティの再作成が発生するタイミングについて詳しくは、構成の変更に対処するをご覧ください。

結果

アプリは、デバイスの回転に関係なく、小さい画面では縦向きのままになります。大画面では横向きと縦向きをサポートします。

参考情報

常にすべてのデバイス設定をサポートするようアプリをアップグレードする方法については、以下をご覧ください。