Android は 5 つ星の大画面アプリに必要な材料をすべて提供しています。このクックブックのレシピでは、開発における特定の問題を解決するために、最適な材料を選択して組み合わせています。各レシピには、おすすめの方法、質の高いコードサンプル、詳細な手順が含まれているので、大画面に対応する際にお役立てください。
星による評価
レシピは、大画面のアプリの品質に関するガイドラインにどの程度準拠しているかに基づいて評価されます。
レベル 1(大画面によって差別化)の条件を満たしている | |
レベル 2(大画面向けに最適化)の条件を満たしている | |
レベル 3(大画面に対応)の条件を満たしている | |
大画面向けの機能をいくつか提供しているが、大画面のアプリの品質に関するガイドラインの条件は満たしていない | |
特定のユースケースのニーズは満たしているが、大画面を適切にサポートしていない |
Chromebook カメラのサポート
Google Play で Chromebook ユーザーにも興味を持ってもらいましょう。
御社のカメラアプリがカメラの基本機能のみで動作できるなら、Chromebook も対象になります。ハイエンド スマートフォンに搭載されるカメラの高度な機能をうっかり指定すると、アプリストアによって Chromebook ユーザーへのインストールが阻止されるので、指定しないようにしましょう。
Chromebook には、前面(ユーザーの方を向いた)カメラが搭載されており、ビデオ会議、スナップショットなどの用途に適しています。ただし、Chromebook には背面(外向き)カメラは搭載されていないものがあります。また、Chromebook の前面カメラは通常、オートフォーカスやフラッシュをサポートしていません。
ベスト プラクティス
多用途のカメラアプリの場合は、カメラの構成(前面カメラ、背面カメラ、USB で接続された外部カメラがあるかどうか)によらず、すべてのデバイスをサポートします。
できるだけ多くのデバイスに対してアプリがアプリストアで表示されるようにするには、アプリが使用するすべてのカメラ機能を必ず宣言し、それらの機能が必須かどうかを明示してください。
要素
CAMERA
権限: アプリにデバイスのカメラへのアクセスを許可します。<uses-feature>
マニフェスト要素: アプリで使用する機能をアプリストアに通知します。required
属性: アプリが特定の機能なしで動作できるかどうかをアプリストアに指定します。
手順
概要
CAMERA
権限を宣言します。カメラの基本サポートを提供するカメラ機能を宣言します。機能ごとに必須かどうかを指定します。
1. CAMERA
権限を宣言する
アプリ マニフェストに次の権限を追加します。
<uses-permission android:name="android.permission.CAMERA" />
2. カメラの基本機能を宣言する
アプリ マニフェストに以下の機能を追加します。
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
3. 各機能が必須かどうかを指定する
android.hardware.camera.any
機能に android:required="false"
を設定すると、あらゆる種類の内蔵カメラや外部カメラが搭載されたデバイスだけでなく、カメラが搭載されていないデバイスからもアプリにアクセスできるようになります。
その他の機能については、android:required="false"
を設定することで、背面カメラ、オートフォーカス、またはフラッシュを備えていない Chromebook のようなデバイスがアプリストアでアプリにアクセスできるようにします。
結果
Chromebook ユーザーも、Google Play などのアプリストアからアプリをダウンロードしてインストールできます。また、フル機能のカメラをサポートしているデバイス(スマートフォンなど)で、カメラの機能の制限はなくなります。
アプリでサポートされているカメラ機能を明示的に設定し、アプリに必須の機能を指定することで、できるだけ多くのデバイスでアプリが使用できるようになりました。
参考情報
詳しくは、<uses-feature>
ドキュメントのカメラのハードウェア機能をご覧ください。
スマートフォンではアプリの向きが制限されるが、大画面デバイスでは制限されない
御社のアプリは縦向きのスマートフォンで最適に動作するため、アプリを縦向きのみに制限しているとします。しかし、横向きの大画面ではより多くの操作を行える可能性があります。
両方に対応するには、つまり、小さい画面ではアプリを縦向きに制限し、大画面では横向きを可能にするには、どうすればよいでしょうか。
ベスト プラクティス
優れたアプリは、ユーザーの好み(デバイスの向きなど)を尊重してくれます。
大画面のアプリの品質に関するガイドラインでは、アプリですべてのデバイス設定(縦向きと横向き、マルチ ウィンドウ モード、折りたたみ式デバイスの折りたたみ / 展開状態など)をサポートすることを推奨しています。アプリはさまざまな設定に対してレイアウトとユーザー インターフェースを最適化する必要があります。また、設定の変更時に状態を保存して復元する必要があります。
このレシピは、大画面をサポートするための一時的な手段です。アプリを改善してあらゆるデバイス設定を完全にサポートできるようになるまで、このレシピをご利用ください。
要素
screenOrientation
: デバイスの向きの変化にアプリがどう反応するかを指定できるアプリ マニフェストの設定- Jetpack WindowManager: アプリ ウィンドウのサイズとアスペクト比を決定できるライブラリのセット。API レベル 14 との下位互換性
Activity#setRequestedOrientation()
: 実行時にアプリの向きを変更できるメソッド
手順
概要
デフォルトでは、アプリがアプリ マニフェストで向きの変更を扱えるようにします。実行時にアプリのウィンドウ サイズを判別します。アプリ ウィンドウが小さい場合は、マニフェストの向きの設定をオーバーライドして、アプリの向きを制限します。
1. アプリ マニフェストで向きの設定を指定する
アプリ マニフェストの screenOrientation
要素を宣言しないか(この場合、画面の向きはデフォルトで unspecified
になります)、画面の向きを fullUser
に設定できます。ユーザーがセンサーベースの回転をロックしていない場合、アプリはすべてのデバイスの向きをサポートします。
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
unspecified
と fullUser
の違いはわずかながらも重要です。screenOrientation
の値を宣言しない場合、システムによって画面の向きが選択されます。画面の向きの定義に使用されるポリシーはデバイスによって異なる場合があります。一方、fullUser
を指定すると、ユーザーがデバイスに定義した動作により近くなります。ユーザーがセンサーベースの回転をロックしている場合、アプリはユーザーの設定に従います。それ以外の場合は、4 種類の画面の向き(縦向き、横向き、逆の縦向き、逆の横向き)のいずれかが可能です。android:screenOrientation
をご覧ください。
2. 画面サイズを判別する
ユーザーが許可したすべての向きサポートするようにマニフェストが設定されている場合、画面サイズに基づいてアプリの向きをプログラムで指定することができます。
Jetpack WindowManager ライブラリをモジュールの build.gradle
ファイルまたは build.gradle.kts
ファイルに追加します。
Kotlin
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Groovy
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
Jetpack WindowManager の WindowMetricsCalculator#computeMaximumWindowMetrics()
メソッドを使用して、デバイスの画面サイズを WindowMetrics
オブジェクトとして取得します。このウィンドウ指標をウィンドウ サイズクラスと比較すると、画面の向きを制限するタイミングを判断できます。
ウィンドウ サイズクラスは、小さい画面と大画面の間のブレークポイントを提供します。
WindowWidthSizeClass#COMPACT
ブレークポイントと WindowHeightSizeClass#COMPACT
ブレークポイントを使用して、画面サイズを決定します。
Kotlin
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Java
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- 注:
- 上記の例は、アクティビティのメソッドとして実装されています。そのため、アクティビティは
computeMaximumWindowMetrics()
の引数でthis
として逆参照されています。 - アプリがマルチ ウィンドウ モードで起動される可能性があるため、
computeCurrentWindowMetrics()
の代わりにcomputeMaximumWindowMetrics()
メソッドが使用されています。マルチ ウィンドウ モードの場合、画面の向きの設定は無視されます。アプリ ウィンドウがデバイスの画面全体になっていない限り、アプリ ウィンドウのサイズを判別して向きの設定をオーバーライドしても意味がありません。
アプリ内で computeMaximumWindowMetrics()
メソッドを使用できるように依存関係を宣言する手順については、WindowManager をご覧ください。
3. アプリ マニフェストの設定をオーバーライドする
デバイスの画面サイズが小さいと判断した場合は、Activity#setRequestedOrientation()
を呼び出してマニフェストの screenOrientation
設定をオーバーライドできます。
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Java
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
onCreate()
メソッドと View.onConfigurationChanged()
メソッドにロジックを追加することで、アクティビティがサイズ変更されたりディスプレイ間を移動されたりするたびに(デバイスの回転後、折りたたみ式デバイスが折りたたまれたとき / 広げられたとき、など)、最大ウィンドウ指標を取得して向きの設定をオーバーライドできるようになります。構成の変更が発生するタイミングや、その変更によってアクティビティの再作成が発生するタイミングについて詳しくは、構成の変更に対処するをご覧ください。
結果
アプリは、デバイスの回転に関係なく、小さい画面では縦向きのままになります。大画面では横向きと縦向きをサポートします。
参考情報
常にすべてのデバイス設定をサポートするようアプリをアップグレードする方法については、以下をご覧ください。
外部キーボードの Space キーによるメディア再生の一時停止と再開
大画面向けの最適化には、外部キーボード入力を処理する機能が含まれています。たとえば、Space キーが押された場合には、動画などのメディアの再生が一時停止または再開されます。外部キーボードに接続されることが多いタブレットや、通常は外部キーボードが付属しておりタブレット モードでも使用できる Chromebook で特に便利な機能です。
メディアがウィンドウの唯一の要素(フルスクリーン動画再生など)である場合、アクティビティ レベルで、または Jetpack Compose では画面レベルで、キー操作イベントに対応します。
ベスト プラクティス
アプリでメディア ファイルを再生する場合は、物理キーボードの Space キーを押すと、再生を一時停止または再開できるようにします。
要素
KEYCODE_SPACE
: Space キーのキーコード定数。
Compose
onPreviewKeyEvent
: コンポーネント(またはその子の一つ)がフォーカスされたときにコンポーネントがハードウェア キーイベントをインターセプトできるようにするModifier
。onKeyEvent
:onPreviewKeyEvent
と同様に、コンポーネント(またはその子の一つ)がフォーカスされたときにコンポーネントがハードウェア キーイベントをインターセプトできるようにするModifier
。
View
onKeyUp()
: キーが離され、アクティビティ内のビューで処理されないときに呼び出される。
手順
概要
ビューベースのアプリと Jetpack Compose ベースのアプリは、キーボードのキーが押された場合に同様の方法で対応します。アプリはキー操作イベントをリッスンして、イベントをフィルタし、Space キーなどの選択したキー操作に応答する必要があります。
1. キーボードのイベントをリッスンする
View
アプリのアクティビティで、onKeyUp()
メソッドをオーバーライドします。
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { ... }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { ... }
このメソッドは、押されたキーが離されると呼び出されるため、キー入力ごとに 1 回呼び出されます。
Compose
Jetpack Compose では、キー入力を管理する画面上の onPreviewKeyEvent
修飾子または onKeyEvent
修飾子を利用できます。
Column(modifier = Modifier.onPreviewKeyEvent { event ->
if (event.type == KeyEventType.KeyUp) {
...
}
...
})
または
Column(modifier = Modifier.onKeyEvent { event ->
if (event.type == KeyEventType.KeyUp) {
...
}
...
})
2. Space キーの押下をフィルタする
onKeyUp()
メソッド、または Compose onPreviewKeyEvent
および onKeyEvent
修飾子メソッド内で、KeyEvent.KEYCODE_SPACE
をフィルタしてメディア コンポーネントに正しいイベントを送信します。
View
Kotlin
if (keyCode == KeyEvent.KEYCODE_SPACE) { togglePlayback() return true } return false
Java
if (keyCode == KeyEvent.KEYCODE_SPACE) { togglePlayback(); return true; } return false;
Compose
Column(modifier = Modifier.onPreviewKeyEvent { event ->
if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
...
}
...
})
または
Column(modifier = Modifier.onKeyEvent { event ->
if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
...
}
...
})
結果
これでアプリは Space キーが押された場合に対応して、動画などのメディアを一時停止したり再開したりできるようになります。
参考情報
キーボード イベントとその管理方法について詳しくは、キーボード入力を処理するをご覧ください。
タッチペンのパーム リジェクション
大画面でのタッチペンは、生産性と創造性に優れたツールです。しかし、ユーザーがタッチペンを使用して描画、書き込み、またはアプリの操作を行うと、手のひらが画面に触れることがあります。このタッチイベントが、手のひらでの偶発的なタッチとして認識されて無視される前に、アプリに報告される場合があります。
ベスト プラクティス
アプリは、不要なタッチイベントを識別して無視する必要があります。Android は、MotionEvent
オブジェクトをディスパッチすることにより、手のひらでのタッチをキャンセルします。オブジェクトの ACTION_CANCEL
または ACTION_POINTER_UP
と FLAG_CANCELED
を確認して、手のひらによる操作を拒否するかどうかを決定します。
要素
MotionEvent
: タッチイベントと移動イベントを表します。イベントを無視するかどうかを決定するために必要な情報が含まれています。OnTouchListener#onTouch()
:MotionEvent
オブジェクトを受け取ります。MotionEvent#getActionMasked()
: モーション イベントに関連付けられたアクションを返します。ACTION_CANCEL
: 操作を元に戻す必要があることを示すMotionEvent
定数。ACTION_POINTER_UP
: 最初のポインタ以外のポインタが上に移動した(つまり、デバイス画面との接続が喪失した)ことを示すMotionEvent
定数。FLAG_CANCELED
: ポインタの上移動により意図しないタップイベントが発生したことを示すMotionEvent
定数。Android 13(API レベル 33)以降のACTION_POINTER_UP
およびACTION_CANCEL
イベントに追加されました。
手順
概要
アプリにディスパッチされた MotionEvent
オブジェクトを調べます。MotionEvent
API を使用してイベントの特性を判別します。
- シングル ポインタ イベント -
ACTION_CANCEL
を確認します。Android 13 以降では、FLAG_CANCELED
についても確認します。 - マルチポインタ イベント - Android 13 以降では、
ACTION_POINTER_UP
とFLAG_CANCELED
を確認します。
ACTION_CANCEL
イベントと ACTION_POINTER_UP
/FLAG_CANCELED
イベントに応答します。
1. モーション イベント オブジェクトを取得する
アプリに OnTouchListener
を追加します。
Kotlin
val myView = findViewById<View>(R.id.myView).apply { setOnTouchListener { view, event -> // Process motion event. } }
Java
View myView = findViewById(R.id.myView); myView.setOnTouchListener( (view, event) -> { // Process motion event. });
2. イベント アクションとフラグを決定する
ACTION_CANCEL
を確認します。これは、すべての API レベルでのシングル ポインタ イベントを表します。Android 13 以降では、ACTION_POINTER_UP
で FLAG_CANCELED.
を確認します。
Kotlin
val myView = findViewById<View>(R.id.myView).apply { setOnTouchListener { view, event -> when (event.actionMasked) { MotionEvent.ACTION_CANCEL -> { //Process canceled single-pointer motion event for all SDK versions. } MotionEvent.ACTION_POINTER_UP -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && (event.flags and MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) { //Process canceled multi-pointer motion event for Android 13 and higher. } } } true } }
Java
View myView = findViewById(R.id.myView); myView.setOnTouchListener( (view, event) -> { switch (event.getActionMasked()) { case MotionEvent.ACTION_CANCEL: // Process canceled single-pointer motion event for all SDK versions. case MotionEvent.ACTION_UP: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && (event.getFlags() & MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) { //Process canceled multi-pointer motion event for Android 13 and higher. } } return true; });
3. 操作を元に戻す
手のひらでのタップを識別した場合、操作による画面上の効果を元に戻すことができます。
手のひらでのタップなどの意図しない入力を元に戻すには、アプリでユーザー操作の履歴を保持する必要があります。Codelab の Android アプリでのタッチペン サポートの強化の基本的な描画アプリを実装するで例を紹介しています。
結果
アプリは、Android 13 以降の API レベルにおけるマルチポインタ イベントと、すべての API レベルにおけるシングルポインタ イベントで、手のひらでのタップを識別、拒否できるようになりました。
参考情報
詳しくは次の記事をご覧ください。
- Android 13 の機能と API - パーム リジェクションを改善する
- デベロッパー ガイド
- Codelab - Android アプリでのタッチペン サポートの強化
WebView の状態管理
WebView
は、状態管理の高度なシステムを提供する、よく使われるコンポーネントです。WebView
は、構成の変更後も状態とスクロール位置を維持する必要があります。WebView
は、ユーザーがデバイスを回転させるか折りたたみ式スマートフォンを開くと、スクロール位置を喪失することがあります。そのため、ユーザーは WebView
の最上部から前のスクロール位置まで再びスクロールする必要があります。
ベスト プラクティス
WebView
の再作成回数を最小限に抑えます。WebView
は状態を管理しやすく、構成変更をできるだけ多く管理することでこの品質を利用できます。Activity
の再作成(システムによる構成変更の処理方法)でも WebView
が再作成され、WebView
の状態が喪失するため、アプリが構成の変更を処理する必要があります。
要素
android:configChanges
: マニフェストの<activity>
要素の属性。アクティビティによって処理される構成変更をリストします。View#invalidate()
: ビューを再描画させるメソッド。WebView
によって継承されます。
手順
概要
WebView
状態を保存するには、Activity
の再作成をできるだけ回避してから、WebView
を無効にして、状態を保持したままサイズ変更できるようにします。
1. アプリの AndroidManifest.xml
ファイルに構成変更を追加する
(システムではなく)アプリで処理する構成変更を指定して、アクティビティの再作成を回避します。
<activity
android:name=".MyActivity"
android:configChanges="screenLayout|orientation|screenSize
|keyboard|keyboardHidden|smallestScreenSize" />
2. アプリが構成の変更を受け取るたびに WebView
を無効にする
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) webView.invalidate() }
Java
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); webview.invalidate(); }
このステップはビューシステムにのみ適用されます。Composable
要素を正しくサイズ変更するために Jetpack Compose が無効にする必要があるものは何もないためです。ただし、正しく管理されていない場合、Compose は WebView
を頻繁に再作成します。Accompanist WebView ラッパーを使用して、Compose アプリの WebView
の状態を保存および復元します。
結果
アプリの WebView
コンポーネントは、サイズ変更から向きの変更、開閉まで、複数の構成変更の後も状態とスクロール位置を保持するようになりました。
参考情報
構成変更とその管理方法について詳しくは、構成の変更に対処するをご覧ください。
RecyclerView の状態管理
RecyclerView
では、最小限のグラフィック リソースを使用して大量のデータを表示できます。RecyclerView
がアイテムのリスト内でスクロールすると、RecyclerView
は画面外にスクロールしたアイテムの View
インスタンスを再使用し、画面上でのスクロール時に新しいアイテムを作成します。しかし、デバイスの回転などの構成変更により、RecyclerView
の状態がリセットされ、ユーザーが RecyclerView
アイテムのリストの以前の位置に再びスクロールしなければならない場合があります。
ベスト プラクティス
RecyclerView
は、すべての構成変更において、状態(特にスクロール位置)とリスト要素の状態を維持する必要があります。
要素
RecyclerView.Adapter#setStateRestorationPolicy()
: 構成変更後にRecyclerView.Adapter
が状態を復元する方法を指定します。ViewModel
: アクティビティまたはフラグメントの状態を保持します。
手順
概要
RecyclerView
のスクロール位置を保存するように RecyclerView.Adapter
の状態復元ポリシーを設定します。RecyclerView
のリストアイテムの状態を保存します。RecyclerView
アダプターにリストアイテムの状態を追加し、ViewHolder
にバインドされたときにリストアイテムの状態を復元します。
1. Adapter
の状態復元ポリシーを有効にする
RecyclerView
アダプターの状態復元ポリシーを有効にして、構成変更後も RecyclerView
のスクロール位置が維持されるようにします。ポリシー仕様をアダプター コンストラクタに追加します。
Kotlin
class MyAdapter() : RecyclerView.Adapter() { init { stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY } ... }
Java
class MyAdapter extends RecyclerView.Adapter{ public Adapter() { setStateRestorationPolicy(StateRestorationPolicy.PREVENT_WHEN_EMPTY); } ... }
2. ステートフルなリストアイテムの状態を保存する
EditText
要素を含むアイテムなど、複雑な RecyclerView
リストアイテムの状態を保存します。たとえば、EditText
の状態を保存するには、テキストの変更をキャプチャする onClick
ハンドラと同様のコールバックを追加します。コールバック内で、保存するデータを定義します。
Kotlin
input.addTextChangedListener( afterTextChanged = { text -> text?.let { // Save state here. } } )
Java
input.addTextChangedListener(new TextWatcher() { ... @Override public void afterTextChanged(Editable s) { // Save state here. } });
Activity
または Fragment
でコールバックを宣言します。ViewModel
を使用して状態を保存します。
3. Adapter
にリストアイテムの状態を追加する
リストアイテムの状態を RecyclerView.Adapter
に追加します。ホスト Activity
または Fragment
が作成されたときに、アイテムの状態をアダプター コンストラクタに渡します。
Kotlin
val adapter = MyAdapter(items, viewModel.retrieveState())
Java
MyAdapter adapter = new MyAdapter(items, viewModel.retrieveState());
4. アダプターの ViewHolder
でリストアイテムの状態を復元する
RecyclerView.Adapter
で ViewHolder
をアイテムにバインドする際に、アイテムの状態を復元します。
Kotlin
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { ... val item = items[position] val state = states.firstOrNull { it.item == item } if (state != null) { holder.restore(state) } }
Java
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { ... Item item = items[position]; Arrays.stream(states).filter(state -> state.item == item) .findFirst() .ifPresent(state -> holder.restore(state)); }
結果
RecyclerView
は、スクロール位置と RecyclerView
リスト内のすべてのアイテムの状態を復元できるようになりました。
参考情報
取り外し可能なキーボードの管理
取り外し可能なキーボードのサポートにより、大型デバイスのユーザーの生産性を最大化
。Android は、キーボードが入力されるたびに構成変更をトリガーします。
接続解除されると、UI の状態が失われる可能性があります。お客様の
アプリは状態を保存および復元して、システムが
キーボードの構成変更に対するアクティビティの再作成を制限することもできます。
いずれの場合も、キーボードに関連するすべてのデータは
Configuration
オブジェクト。keyboard
と
構成オブジェクトの keyboardHidden
フィールドには、タイプに関する情報が格納される
キーボードを利用できるかどうかです
おすすめの方法
大画面向けに最適化されたアプリは、 タッチペン、マウス、トラックパッド、その他の周辺機器 できます。
外部キーボードをサポートするには構成の変更が必要です。 次の 2 つの方法のいずれかで管理できます。
- 現在実行中のアクティビティをシステムに再作成させ、アプリの状態を管理します。
- 構成の変更を自分で管理します(アクティビティは再作成されません)。
<ph type="x-smartling-placeholder">
- </ph>
- キーボード関連の設定値をすべて宣言する
- 構成変更ハンドラを作成する
生産性向上アプリ。多くの場合、テキスト入力や 他の入力に対しても、DIY アプローチでデータの処理に 自動的に適用されます。
特殊なケースとして、ハードウェア ハードウェアやソフトウェアが たとえば、キーボードを取り付けたり、取り外したりして、ツールなどを 確認します。
構成の変更をリッスンする唯一の確実な方法は、
ビューの onConfigurationChanged()
メソッドを使用すると、新しいビューを追加して、
インスタンスをアプリ アクティビティに追加し、ビューの onConfigurationChanged()
で応答します。
キーボードのアタッチや構成変更に起因する構成変更に対する
接続解除します
要素
android:configChanges
: アプリ マニフェストの<activity>
要素の属性。アプリが管理する構成変更をシステムに通知します。View#onConfigurationChanged()
: 新しい関数の伝播に反応するメソッド できます。
手順
概要
configChanges
属性を宣言し、キーボード関連の値を追加します。追加
View
をアクティビティのビュー階層に追加し、構成の変更をリッスンします。
1. configChanges
属性を宣言する
すでに管理している構成変更のリストに keyboard|keyboardHidden
の値を追加して、アプリ マニフェストの <activity>
要素を更新します。
<activity
…
android:configChanges="...|keyboard|keyboardHidden">
2. ビュー階層に空のビューを追加する
新しいビューを宣言し、ビューの onConfigurationChanged()
メソッド内にハンドラコードを追加します。
Kotlin
val v = object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) // Handler code here. } }
Java
View v = new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Handler code here. } };
結果
アプリは、外部キーボードの取り付けや取り外しに対して、現在実行中のアクティビティを再作成せずに応答するようになりました。
参考情報
キーボードの取り付けや取り外しなどの構成変更時にアプリの UI の状態を保存する方法については、UI の状態を保存するをご覧ください。
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- 構成の変更を処理する