取り外し可能なキーボードの管理

3 つ星の評価アイコン

着脱式キーボードをサポートすることで、大画面デバイスでのユーザーの生産性を最大限に高めることができます。キーボードがデバイスに着脱されるたびに Android は構成の変更をトリガーするため、UI の状態が失われる可能性があります。アプリは、状態を保存して復元し、アクティビティの再作成をシステムに処理させることも、キーボード構成の変更に対するアクティビティの再作成を制限することもできます。

いずれの場合も、キーボードに関連するすべてのデータは Configuration オブジェクトに保存されます。構成 オブジェクトの keyboard フィールドと keyboardHidden フィールドには、キーボードの種類とその可用性に関する情報が含まれています。

ベスト プラクティス

大画面向けに最適化されたアプリは、ソフトウェア キーボードやハードウェア キーボードから、スタイラス、マウス、トラックパッド、その他の周辺機器まで、あらゆる種類の入力デバイスをサポートしています。

外部キーボードのサポートには構成の変更が伴いますが、これは次の 2 つの方法で管理できます。

  1. 実行中のアクティビティをシステムに再作成させ、アプリの状態の管理はユーザーが行います。
  2. 構成の変更を自分で管理します(アクティビティは再作成されません)。
    • キーボード関連の構成値をすべて宣言する
    • 構成変更ハンドラを作成する

テキスト入力やその他の入力で UI の細かい制御が必要になることが多い生産性向上アプリでは、構成の変更を自分で処理する方法が役立ちます。

特別なケースでは、ハードウェア キーボードが着脱されたときにアプリのレイアウトを変更することがあります。たとえば、ツールや編集ウィンドウのためのスペースを増やす場合などです。

Jetpack Compose では、キーボード構成の変更に次の 2 つの方法で対応できます。

  1. リアクティブ UI: LocalConfiguration.current を使用して、コンポーザブルで現在の構成状態を直接読み取ります。キーボードが着脱されると、UI は自動的に再コンポーズされ、新しい状態に適応します。
  2. 副作用コールバック: ライフサイクル対応の DisposableEffect を使用して、ホスト アクティビティに構成変更リスナーを登録します。これにより、アクティビティを再作成したり、ダミーのビュー要素をインスタンス化したりすることなく、UI 以外のイベント(ロギングや分析など)をトリガーできます。

材料

  • android:configChanges: アプリ マニフェストの <activity> 要素の属性。アプリが管理する構成の変更をシステムに通知します。
  • LocalConfiguration: 現在の デバイス Configuration を公開するコンポーザブル ローカル プロバイダ。
  • DisposableEffect: コンポーザブルがコンポジションに入るときにコードブロックを実行し、離れるときにクリーンアップする Compose 副作用 API。

手順

configChanges 属性を宣言し、キーボード関連の値を追加してアクティビティの再作成を防ぎます。次に、LocalConfiguration.current を使用してコンポーザブル レイアウトを動的に適応させるか、DisposableEffect を使用して構成リスナーを登録します。

1. configChanges 属性を宣言する

すでに管理されている構成の変更のリストに keyboard|keyboardHidden 値を追加して、アプリ マニフェストの <activity> 要素を更新します。

<activity
            android:configChanges="...|keyboard|keyboardHidden">

2. キーボード構成の変更に対応する

Jetpack Compose で構成の変更を処理するには、UI を更新するか、副作用コールバックを実行するかに応じて、次のいずれかのオプションを使用します。

  • オプション A: リアクティブ UI(推奨)

    キーボードの種類を LocalConfiguration.current から直接読み取ります。ハードウェア キーボードが着脱されると、この値が変更され、Compose が UI を自動的に再コンポーズします。

    val configuration = LocalConfiguration.current
    val isPhysicalKeyboardAttached = configuration.keyboard == Configuration.KEYBOARD_QWERTY
    
    if (isPhysicalKeyboardAttached) {
        // Render layout optimized for physical keyboard
    } else {
        // Render default layout
    }

  • オプション B: 副作用リスナー

    構成が変更されたときに副作用(ロギング、ローカル データベースの更新、分析のトリガーなど)を実行する必要がある場合は、DisposableEffect を使用して、ホスト ComponentActivity に構成変更リスナーを登録します。

    val context = LocalActivity.current
    DisposableEffect(context) {
        val activity = context as? ComponentActivity
        val listener = Consumer<Configuration> { newConfig ->
            val hasKeyboard = newConfig.keyboard == Configuration.KEYBOARD_QWERTY
            // Trigger non-UI actions, analytics, etc.
        }
        activity?.addOnConfigurationChangedListener(listener)
        onDispose {
            activity?.removeOnConfigurationChangedListener(listener)
        }
    }

結果

実行中のアクティビティを再作成することなく、外部キーボードの着脱に対応できるようになります。

参考情報

キーボードの着脱などの構成変更時にアプリの UI の状態を保存する方法については、UI の状態を保存するをご覧ください。