折りたたみ型レイアウト

重要

この記事では、パブリック プレビュー段階であり、一般公開前に大幅に変更される可能性がある機能とガイダンスについて説明します。 本書に記載された情報について、Microsoft は明示または黙示を問わずいかなる保証をするものでもありません。

重要

このビューのコンテンツは、アクティビティ ルート ビューがウィンドウにアタッチされた後にのみ使用できます。 これは、実装がウィンドウ マネージャー ライブラリに基づいており、ウィンドウ マネージャーは、ビューがウィンドウにアタッチされている場合にのみ動作しているため発生します。

コンポーネントFoldableLayout は、折りたたみ型デバイスでアプリケーションを実行するときに、子を別々に配置できるカスタム レイアウトです。 このコンポーネントでは、折りたたみ機能の位置と向きに応じて、画面を 2 つの領域に分割できます。 画面を分割すると、2 つの子コンテナーを横に並べるか上下に並べて保持できます。

シングルスクリーン レイアウト デュアルスクリーン レイアウト
ワイド モードのシングル スクリーン上のアプリ ワイド モードの 2 つの画面にスパンされたアプリ
縦長モードのシングル スクリーン上のアプリ 縦長モードの 2 つの画面にスパンされたアプリ

XML 属性

  • single_screen_layout_id - シングル スクリーン モードで表示されるレイアウト ID を受け取ります。
  • dual_screen_start_layout_id - デュアル スクリーン モードの開始コンテナーに表示されるレイアウト ID を受け取ります。
  • dual_screen_end_layout_id - デュアル スクリーン モードの開始コンテナーに表示されるレイアウト ID を受け取ります。

FoldableLayout には、折りたたみ型デバイスでアプリケーションが実行されている場合に 1 つのコンテナーを作成する機能も備わっています。

必要な UI の作成に役立つ次の 4 つの新しい属性が追加されました。

  • dual_portrait_single_layout_id - デュアル縦の単一コンテナーについてレイアウト ID を受け取ります。
  • is_dual_portrait_single_container - デュアル縦の空の単一コンテナーを作成します。
  • dual_landscape_single_layout_id - デュアル横の単一コンテナーについてレイアウト ID を受け取ります。
  • is_dual_landscape_single_container - デュアル横の空の単一コンテナーを作成します。

smallestScreenSize のサポート

アクティビティで新しい画面モードに切り替えても、マニフェスト ファイルにフラグ smallestScreenSize が設定されているために再作成されない場合、レイアウトによって新しい構成が検出され、FoldableLayout の構成に応じて自動的にコンテナーのサイズが変更されるか、2 番目のコンテナーが追加または削除されます。

Android Studio プレビュー

  • tools_hinge_color - レイアウト プレビューでのヒンジ カラーを選択します。
  • tools_screen_mode - レイアウト プレビューでの画面モードを選択します。

XML ファイル内で FoldableLayout にフラグメントを追加する場合、フラグメント UI をプレビューするには次の属性が必要です。

  • show_in_single_screen
  • show_in_dual_screen_start
  • show_in_dual_screen_end
  • show_in_dual_portrait_single_container
  • show_in_dual_landscape_single_container

コンテナー ID

コンテナーには、次の ID があります。

  • first_container_id
  • second_container_id

画面の向きや特殊な動作がレイアウトに設定されているかどうかには関わりなく、レイアウトが 1 つのコンテナーのみに表示される場合、その ID は first_container_id になります。 2 つのコンテナーが表示される場合は、second_container_id も存在します。

たとえば、次のように入力します。

  • アプリケーションがシングル スクリーン モードの場合、コンテナー ID は first_container_id になります。
  • デュアル縦でデュアル スクリーン モードへの切り替えが行われ、dual_portrait_single_layout_id または is_dual_portrait_single_container を設定している場合、デュアル スクリーン モードでコンテナーが 1 つだけ存在するため、その ID は引き続き first_container_id です。
  • デュアル縦への切り替えが行われても、属性 dual_landscape_single_layout_id および is_dual_landscape_single_container を設定していない場合は、ID first_container_idsecond_container_id を持つ両方のコンテナーが存在することになります。

コードで FoldableLayout を作成する

findViewById<FrameLayout>(R.id.parent).addView(
    FoldableLayout(this, FoldableLayout.Config().apply {
        singleScreenLayoutId = R.layout.single_screen
        dualScreenStartLayoutId = R.layout.dual_screen_start
        dualScreenEndLayoutId = R.layout.dual_screen_end
        dualLandscapeSingleLayoutId = R.layout.single_screen
    })
)

FoldableLayout 構成を置き換える

次のコードでは、古い構成を破棄し、それを新しいもので置き換えて、新しい構成でビューを生成します。

findViewById<FoldableLayout>(R.id.surface_duo_layout)
    .newConfigCreator()
    .singleScreenLayoutId(R.layout.single_screen)
    .dualScreenStartLayoutId(R.layout.dual_screen_start)
    .dualScreenEndLayoutId(R.layout.dual_screen_end)
    .reInflate()

FoldableLayout 構成を更新する

次のコードでは、選択した属性を使用して現在の構成を更新し、ビューを生成します。

findViewById<FoldableLayout>(R.id.surface_duo_layout)
    .updateConfigCreator()
    .dualScreenStartLayoutId(R.layout.dual_screen_start)
    .reInflate()

レイアウト コンポーネントの使用方法

アプリケーションを作成するために、アクティビティまたはフラグメントを含むアクティビティを使用して、UI を処理することができます。 フラグメントは、レイアウト リソースファイルで宣言することも、アクティビティで直接作成することもできます。 これらのケースがコンポーネントによってどのように処理されるかについては、後で説明します。

プロセス図

アクティビティの使用

ここでは、UI を処理するアクティビティだけを使用して、コンポーネントがどのように動作するかを見ていきます。

  1. まず、アクティビティの *.xml ファイルに FoldableLayout を追加する必要があります。

    <com.microsoft.device.dualscreen.layouts.FoldableLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/enlightened_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        app:single_screen_layout_id="@layout/single_screen_layout"
        app:dual_screen_start_layout_id="@layout/single_screen_layout"
        app:dual_screen_end_layout_id="@layout/dual_screen_end_layout"/>
    
  2. 次に、さまざまな画面モード用に 3 つのレイアウトを作成します。

  3. レイアウトをアクティビティにリンクします。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    }
    

リソース ファイルで宣言されたフラグメントを使用する

ここでは、*.xml ファイルで宣言されているフラグメントによるコンポーネントの動作について説明します。

  1. まず、アクティビティの *.xml ファイルに FoldableLayout を追加する必要があります。

    <com.microsoft.device.dualscreen.layouts.FoldableLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:single_screen_layout_id="@layout/single_screen_layout"
        app:dual_screen_start_layout_id="@layout/dual_screen_start_layout"
        app:dual_screen_end_layout_id="@layout/dual_screen_end_layout" />
    
  2. 次に、フラグメントを singlescreenlayout.xmldualscreenstartlayout.xml、および dualscreenendlayout.xml ファイルに宣言します。

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/single_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.microsoft.device.display.samples.contentcontext.MapPointListFragment" />
    
  3. レイアウトをアクティビティにリンクします。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    }
    

アクティビティで作成されたフラグメントの使用

最後に、getSupportFragmentManager().beginTransaction() を使用して追加されたフラグメントによりコンポーネントがどのように動作するかを説明します。

  1. まず、アクティビティの *.xml ファイルに FoldableLayout を追加する必要があります。

    <com.microsoft.device.dualscreen.layouts.FoldableLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    これにより、ビューのコンテナーが作成されますが、それらには何も設定されません。

  2. FoldableLayout のコンテナーには、その ID を使用してアクセスできます。

    • first_container_id
    • second_container_id
  3. 次に、フラグメント マネージャーの状態ハンドラー ライブラリをご覧ください。画面モードの切り替えを処理する際には、フラグメントに特別な注意が必要です。

ビュー バインディング

重要

下のコード スニペットに示すように findViewById を使用してください。 Google ビュー バインディングは使用しないでください。

WindowManager にウィンドウ レイアウトに関する利用可能な情報がある場合、FoldableLayout コンテンツは拡張されるため、子インスタンスを取得して使用することはできません。 子ビューをバインドするには、まず FoldableLayout コンテンツが使用可能な状態であることを確認する必要があります。 このためには、次のメソッドを用いる必要があります。

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    private val contentChangedListener = object : FoldableLayout.ContentChangedListener {
        override fun contentChanged(screenMode: ScreenMode?) {
            // Here, you can retrieve the child instance
            val child = binding.foldableLayout.findViewById<View>(R.id.child_view)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    override fun onResume() {
        super.onResume()
        binding.foldableLayout.addContentChangedListener(contentChangedListener)
    }

    override fun onPause() {
        super.onPause()
        binding.foldableLayout.removeContentChangedListener(contentChangedListener)
    }
}

ここで、

  • FoldableLayout.ContentChangedListener は、FoldableLayout コンテンツが拡張された後に呼び出されるコールバックです。

  • FoldableLayout.addContentChangedListener は、指定された FoldableLayout.ContentChangedListener コールバックを登録します。

  • foldableLayout.removeContentChangedListener は、指定された FoldableLayout.ContentChangedListener コールバックの登録を解除します。

重要

メモリ リークを防ぐため、Activity または FragmentonResume および onPause メソッドの内部にこのコードを追加する必要があります。