はじめに
Android 16では、従来の固定UIが廃止され、あらゆるデバイス環境において一貫したユーザー体験を提供するための「適応型UI」の実装が求められています。 それに伴い、画面周りに関する以下のプロパティが大画面デバイスにおいて無視されるようになりました。
・screenOrientation
・resizableActivity
・minAspectRatio
・maxAspectRatio
・setRequestedOrientation()
・getRequestedOrientation()
screenOrientation、setRequestedOrientation()、getRequestedOrientation() の次の値は無視されます。
・portrait
・reversePortrait
・sensorPortrait
・userPortrait
・landscape
・reverseLandscape
・sensorLandscape
・userLandscape
今回は、アプリ開発者が必要に応じて対応すべき主要な内容について書いていきます。
動作確認用の端末を用意する
まずは動作確認のために画面固定が無効になるsw600dp以上のAndroid 16ベータを入れたエミュレータまたは、Android 16ベータ登録等でAndroid 16をインストールしたPixelデバイスを用意しましょう。
手順は公式が丁寧に記載されていますので、こちらを参照してください。
AndroidDevelopers|Android 16 を入手する
もし、手持ちのPixcel端末にAndroid 16ベータ版を入れようとしても対象サイズがわからない場合は、Device ManagerのView Detailsを開くと確認できます。

個人的には今回の確認においてわざわざ物理端末を使うメリットは見つからないので、エミュレータで十分かと思います。
後述の補足で書きますが、アクティビティ単位で画面固定を行っている場合は、〜Android 11、Android 12〜15、Android 16の3種類を見ておくと良いでしょう。
また、動作確認時の注意で無効になるプロパティの例外の一つとして、アスペクト比設定でアプリのデフォルトを選択している場合があります。
Android 16 の画面の向き、サイズ変更、アスペクト比の制限は、次の状況では適用されません。
ゲーム(android:appCategory フラグに基づく)
ユーザーがデバイスのアスペクト比設定でアプリのデフォルトの動作を明示的に有効にしている
sw600dp より小さい画面
現時点では、アプリをインストール時のデフォルトは「アプリのデフォルト」になっているため、動作確認時はこの設定を全画面に変更しましょう。
アスペクト比の設定は以下のように変更できます。


余談ですが、このアスペクト比変更の機能はAndroid 14から存在していたようで、Android 16でなくてもこの設定を変更するとアプリ設定の画面設定が無視されます。
AndroidDevelopers|ユーザーによるアプリごとのオーバーライド
つまり実質的にはAndroid 14から大画面でのアプリの画面設定は意味をなさなくなってなっているようなものなのに、Android 16で画面の向き、サイズ変更、アスペクト比の制限を無視することを大きな変更のようなセクションで掲載しているのが個人的に少し違和感を感じてきました。
ちなみにAndroid 14の変更では特に触れていなかったようです。どうしてでしょうか……。
AndroidDevelopers|動作の変更点: Android 14 以上をターゲットとするアプリ
【補足】タブレット・折りたたみデバイスの画面回転について
一般的なサイズのスマートフォンでの利用を想定しているアプリケーションですと見落としがちですが、Android 12以降ではドキュメントの通り、マニフェスト記載の画面固定を無視することがあります。
Android 12(API レベル 31)以降では、デバイス メーカーはアプリが指定した画面の向きの制限を無視し、代わりに互換モードを適用できるようになりました。たとえば、折りたたみ式デバイスは、デバイスの横向きのタブレット サイズの内部画面でアクティビティが表示される場合、アクティビティの android:screenOrientation=”portrait” 設定を無視することがあります。
アプリの向きの制限が無視される場合、アプリは Activity#setRequestedOrientation() を呼び出して画面の向きをプログラムで設定できます。アプリが構成の変更を処理していない場合、この呼び出しによりアプリの再起動がトリガーされます(構成の変更を処理するをご覧ください)。
AndroidDevelopers|互換性に関する一般的な問題
このように公式のドキュメントにはlandscapeやActivity#setRequestedOrientationで固定した場合は画面回転されないようにも見える記述でしたが、
試しにAndroid 15(API35)pixelタブレットのエミュレータで動作確認をしたところ、マニフェストとアクティビティどちらで画面固定の記述をしても回転した向きで画面の再生成が行われてました。
ただし、再生成される画面はアスペクト比を維持したレターボックス表示となります。
一時的に回避する・部分的に無効化するケース
Android 16の正式リリースまでに対応する工数が確保できない等で難しい場合は、部分的に無効化することも可能です。
(非推奨)一時的に回避する
特定のアクティビティをオプトアウトするには、PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY等のプロパティを宣言します。
<activity>
<property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
android:value="false" />
...
</activity>
こちらはドキュメントにも記載がある通り、APIレベル37では無効となるオプションなので対応する時間がない場合の一時的な対応となります。
……と、公式には記載があるのですが現時点のAndroid 16ベータを入れたタブレットのエミュレータで試す限り、動作確認セクションで触れたAndroid 14以降で設定できるアスペクト比設定の影響は受けるのでこちらで解決となるのか疑問なところです。 プロパティ設定によるオプトアウトには、アスペクト比の設定から特定のモードを除外するようなオプションもありましたのでこちらも検討してみてはいかがでしょうか。
<application>
<property
android:name="android.window.
PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"
android:value="false" />
</application>
AndroidDevelopers|ユーザーによるアプリごとのオーバーライド
PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDEを設定するとアプリの設定画面からアスペクト比(試験運用版)が消えます。
PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDEを設定するとアスペクト比の選択から全画面表示が消えます。
動作確認した感じですとアスペクト比設定を無効にした場合はデフォルト固定というわけではなく、最後のユーザー設定値が反映されているようなので注意して下さい。
部分的に無効化する
画面回転に伴うアクティビティの再生成を無効化するには、AndroidManifest.xmlファイルのactivityタグまたはappタグにandroid:configChanges属性を使用して、特定の構成変更をアクティビティが自分で処理するように指定できます。
これにより、指定された構成変更が発生したときにアクティビティが再生成されるのを防ぐことができます。
<activity>
android:name=".YourActivity"
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout">
</activity>
AndroidDeveloppers|サイズベースの構成変更に関するアクティビティの再作成を制限する
この設定により、以下の構成変更が発生したときにアクティビティが再生成されるのを防ぎます。
screenSize: 画面サイズの変更
smallestScreenSize: 最小画面サイズの変更
orientation: 画面の向きの変更
screenLayout: 画面レイアウトの変更
また、このタグを使用した場合はアクティビティはこれらの変更を自分で処理する必要があります。
画面回転での再生成の無効化がしたいという目的ですと基本的には不要かと思うのですが、無効化している場合は以下の対応が必要になることもあると覚えておいてください。
例えば、画面の向きが変更されたときに更新するには、onConfigurationChangedメソッドをオーバーライドして処理を追加します。
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
// 横向きのレイアウトに変更
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
// 縦向きのレイアウトに変更
}
}
画面サイズ変更によるレイアウト
Viewレイアウトでの画面サイズ対応
XMLレイアウトでは、res/layout-sw600dpのようなディレクトリを使用して、画面サイズに応じたレイアウトを切り替えることができます。これにより、異なる画面サイズに対して適切なレイアウトを提供できます。
Jetpack Composeでの画面サイズ対応
Jetpack Composeでは、XMLレイアウトのような切り替えはできないので、コード内で画面サイズに応じたレイアウトの切り替えを行います。
以下のようにBoxWithConstraintsやLocalConfigurationを使用して、画面サイズに応じたレイアウトを実現することができます。
@Composable
fun ResponsiveLayout() {
BoxWithConstraints {
if (maxWidth < 600.dp) {
PhoneLayout()
} else {
TabletLayout()
}
}
}
画面回転に伴うアクティビティの再生成
アクティビティの再生成が行われると、Activityや子のFragment内においていたり、Composeレイアウト内にrememberで置いているようなデータは揮発してしまいます。
データ消え得るタイミングとしては、画面回転によるアクティビティの再生成以外でも、バックグラウンドからの復帰のタイミングによるAndroid側のメモリ管理に伴う揮発や、RecyclerViewのようなビューでの破棄などでも起こり得るのである程度はすでに対策している場合もあるかと思いますが、
前者に関しては通常の利用では再現させにくいこともあり、部分的に漏れているなんてこともあるので注意が必要そうです。
アクティビティの再生成に対応するための状態保存については過去に
【Android】JetpackComposeでUIの状態保存を使い分ける
という記事を記載しておりますので是非確認してみて下さい。
JetpackComposeと書いていますが、SavedStateHandleを利用した状態保存については既存のレイアウトXMLで実装しているプロジェクトでも使えるので、FragmentのonSaveInstanceStateを利用した実装をしている場合でも今回の変更を機に乗り換えてみるのもいかがでしょうか。
おわりに
以上、固定UI廃止とアプリ開発者が対応すべきポイントについてでした。
タブレット(大画面デバイス)を意識してなかった開発者としては、実はAndroid 16以前から注意する必要があった事実に驚いた方もいるかもしれません。
Foldable端末もタブレットモードでは対象になり得るのでこれを機に見直してみてはいかがでしょうか。








