Screen Continuity — Androidのメカニズムで、折り畳み端末の折り畳み状態と展開状態の間でアプリケーションのシームレスな移行を保証します。展開時に画面の物理的寸法が変化し、システムは新しい設定でActivityを再起動します。Google Developer, 2025によると、継続性の適切な処理はユーザー体験を40%向上させ、状態損失の苦情を減少させます。ScreenContinuity APIはJetpack WindowManagerのバージョン1.1から含まれており、デバイスの姿勢変更時に開発者がライフサイクルを管理できるようにします。
重要なポイント
Screen ContinuityはAndroidのメカニズムで、折り畳み端末における画面の物理的構成変更時にActivity状態を保持します。ユーザーが電話を展開または折り畳むと、システムは新しいウィンドウ寸法でActivityを再起動する場合があります。継続性は、入力データ、スクロール位置、現在の画面の損失を防ぎます。
Androidが単に新しい向きでActivityを再作成するだけの単純な画面回転とは異なり、折り畳み端末は根本的に新しいシナリオを導入します。HALF_OPENED姿勢はアプリが半画面で動作することを可能にし、FLATは完全に展開されたタブレットモードで動作します。Screen Continuityのサポートがない場合、姿勢が変わるたびにインターフェースが初期状態にリセットされます。
Google I/O 2024によると、62%以上の折り畳み端末ユーザーが状態切り替えを誤って処理するアプリに遭遇しています。Screen ContinuityはAPIレベルでこの問題を解決し、開発者にUIの保存と復元のための既製ツールを提供します。
Jetpack WindowManagerはFoldingFeatureクラスを通じて折り畳み端末の3つの基本姿勢を定義します。各姿勢はヒンジの特定の物理的位置に対応し、特別なインターフェース処理を必要とします。
デバイスは30〜160度の角度にあります。画面は2つの論理領域に分割されます。アプリは上半分にコンテンツ、下半分にコントロールを表示できます。ビデオ通話やメディアプレーヤーのテーブルトップモードはこの姿勢を使用します。
デバイスは180度開き、1つの大きな画面を形成します。アプリは拡張された作業領域を持つタブレットモード
デバイスは約120度の角度で表面に立てかけられます。画面の下半分はタッチパネルまたはキーボードとして機能します。この姿勢のタッチパッドモードでは、画面下部でトラックパッドをエミュレートできます。
Androidはconfiguration changesメカニズムを通じて折り畳み端末の構成変更を処理します。ユーザーが電話を展開すると、システムはウィンドウサイズの変更を検出し、標準のActivity再作成サイクルを開始します。Screen Continuityはこのプロセスをインターセプトし、重要なデータを保存します。
状態保存の主要メソッドはonRetainNonConfigurationInstanceで、Activityが破棄される前に呼び出されます。開発者はこれにデータモデル、リスト位置、現在のナビゲーション画面を保存します。再作成後、ActivityはgetLastNonConfigurationInstanceを介してこのデータを受け取り、折り畳み前とまったく同じUIを復元します。
Fragmentsの場合、メカニズムはsetRetainInstance(true)を通じて実装され、構成変更時にフラグメントが破棄されるのを防ぎます。Jetpack ComposeではrememberSaveableが使用され、Window Metricsの変更時に自動的に状態を保存します。
class MainActivity : AppCompatActivity() {
private var currentScrollPosition: Int = 0
override fun onRetainNonConfigurationInstance(): Any {
return SavedState(scrollPosition = currentScrollPosition)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val saved = lastNonConfigurationInstance as? SavedState
saved?.let { currentScrollPosition = it.scrollPosition }
}
}
Jetpack WindowManagerバージョン1.1+にはScreenContinuityControllerクラスが含まれており、画面継続性を管理するための既製メカニズムを提供します。APIは自動的に姿勢変更を処理し、コールバックインターフェースを通じてアプリに通知します。
姿勢変更リスナーを登録する中央クラス。registerContinuityListenerは、折り畳み端末の状態間の各遷移で発動するコールバックを受け入れます。コントローラーはgetCurrentFoldingFeatureメソッドを通じて現在の姿勢に関する情報も提供します。
FoldingFeatureデータをアプリが読み取り可能な状態に変換するユーティリティクラス。FoldingFeatureAdapterはヒンジ座標を正規化し、現在の姿勢がHALF_OPENED、FLAT、TABLE_TOPのいずれかを判断します。これにより、開発者は手動での角度としきい値の計算から解放されます。
Composeアプリの場合、WindowManagerは折り目を考慮したWindowSizeClassとモディファイアを提供します。BoxWithConstraintsコンポーネントはActivityの再作成なしでリアルタイムに画面サイズの変更に適応します。ComposeはWindowMetricsの変更時に自動的に再コンポジションをトリガーします。
val windowManager = WindowManager(context)
val controller = windowManager.screenContinuityController
controller.registerContinuityListener { feature: FoldingFeature ->
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> enterTabletopMode()
FoldingFeature.State.FLAT -> expandToTablet()
}
}
Screen Continuityをサポートする完全なActivityの例を見てみましょう。MainActivityは折り畳み、展開、半折り畳み状態の3つのシナリオを処理します。データはonRetainNonConfigurationInstanceを介して保存され、再作成時に復元されます。
class ContinuityActivity : AppCompatActivity() {
private lateinit var binding: ActivityContinuityBinding
private var itemList = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityContinuityBinding.inflate(layoutInflater)
setContentView(binding.root)
val savedState = lastNonConfigurationInstance as? ContinuityState
if (savedState != null) {
itemList.addAll(savedState.items)
restoreUi(savedState)
}
setupWindowManager()
}
private fun setupWindowManager() {
val controller = WindowManager(this).screenContinuityController
controller.registerContinuityListener { feature ->
updateLayoutForFeature(feature)
}
}
private fun updateLayoutForFeature(feature: FoldingFeature) {
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> binding.root.enableTabletopMode()
FoldingFeature.State.FLAT -> binding.root.enableTabletMode()
FoldingFeature.State.TABLE_TOP -> binding.root.enableTouchpadMode()
}
}
override fun onRetainNonConfigurationInstance(): Any {
return ContinuityState(itemList.toList(), binding.listView.firstVisiblePosition)
}
}
data class ContinuityState(
val items: List<String>,
val scrollPosition: Int
)
主要な要素はContinuityStateクラスで、アイテムリストとスクロール位置を保存します。Activityは再作成前にこれを保存し、onCreateを呼び出した直後に復元します。WindowManagerコントローラーは姿勢変更をサブスクライブし、モード間でレイアウトを切り替えます。
Android Studioは3つすべての姿勢をサポートする折り畳み端末エミュレーターを提供します。Screen Continuityをテストするには、Pixel FoldまたはSamsung Galaxy Z Foldタイプの仮想デバイスを作成し、エミュレーターのコントロールパネルを使用して姿勢を切り替えます。
FoldableカテゴリでAVDを作成し、7.6インチの画面解像度を選択します。エミュレーターの拡張コントロールでFolding Posturesタブを開き、姿勢を切り替えます。各切り替えはconfiguration changeをトリガーし、アプリが正しく処理する必要があります。
実際のデバイス(Galaxy Z Fold 5、Pixel Fold)では、物理的に折り畳んだり展開したりしてテストします。Samsung DeXおよびMulti-Windowモードでも継続性が有効になります。デバッグにはADBコマンドadb shell dumpsys window policyを使用し、現在の折り畳み状態を表示します。
主なエラーには、RecyclerViewの状態損失、テキストフィールドの内容リセット、ダイアログウィンドウの終了が含まれます。ViewModelはActivityのライフサイクルとは独立してメモリ内にデータを保持することでこれらの問題を解決します。アプリが手動で変更を処理する場合は、マニフェストでActivityにandroid:configChangesパラメーターをアノテーションすることも重要です。
<!-- AndroidManifest.xml -->
@android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
よくある質問
Screen Continuityは回転時だけでなく、画面サイズの物理的変化時に状態を保存します。通常のonSaveInstanceStateは折り畳み端末の姿勢切り替え時に状態保持を保証しませんが、ScreenContinuityControllerはこの特定のシナリオを処理します。
Android 10+およびGoogle Play Servicesを搭載したすべての折り畳み端末。サポートはPixel Fold、Galaxy Z Foldシリーズ、Huawei Mate X、Oppo Find N、OnePlus Openに含まれています。Jetpack WindowManagerバージョン1.1以上が必要です。
Jetpack ComposeはrememberSaveableとWindowSizeClassを通じてScreen Continuityをサポートします。コンポジションは自動的にWindowMetricsの変更に応答し、rememberSaveableは再コンポジション間で状態を保持します。onSizeChangedモディファイアはリアルタイムでサイズ変更を追跡できます。
デバイスを展開または折り畳むと、Activityは状態を保存せずに再作成されます。ユーザーは入力データを失い、スクロールはリセットされ、開いていたダイアログは閉じられます。これにより、Google Playでの否定的なレビューとアプリ評価の低下につながります。
Android Emulatorは折り畳み端末のシミュレーションをサポートしています。Pixel FoldタイプのAVDを作成し、Extended Controlsを開いてFolding Posturesタブを選択します。姿勢を切り替えるとconfiguration changeがトリガーされ、物理デバイスなしで状態保持をテストできます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。