Поделиться через


Макет для складных устройств

Важно!

В этой статье описаны функциональные возможности общедоступной ознакомительной версии, а также инструкции по ее использованию. Сведения могут быть существенно изменены, прежде чем версия станет общедоступной. Майкрософт не дает никаких гарантий, явных или подразумеваемых, в отношении предоставленной здесь информации.

Важно!

Содержимое этого представления станет доступным, только когда к окну будет присоединено корневое представление действия. Это происходит, так как реализация основана на библиотеке диспетчера окон, который работает только при присоединении представления к окну.

Компонент FoldableLayout представляет собой настраиваемый макет, который может по-разному располагать свои дочерние элементы, когда приложение работает на складных устройствах. Компонент может разбивать экран на две области в зависимости от положения и ориентации функции свертывания. Когда экран разбивается, он может содержать два дочерних контейнера: параллельно или один над другим.

Одностраничный макет Двухэкранный макет
Приложение на одном экране в горизонтальном режиме Приложение, развернутое на два экрана, в горизонтальном режиме
Приложение на одном экране в вертикальном режиме Приложение, развернутое на два экрана, в вертикальном режиме

XML-атрибуты

  • single_screen_layout_id. Позволяет получить идентификатор макета для отображения в режиме одинарного экрана.
  • dual_screen_start_layout_id. Позволяет получить идентификатор макета для отображения в начальном контейнере в режиме двойного экрана.
  • dual_screen_end_layout_id. Позволяет получить идентификатор макета для отображения в начальном контейнере в режиме двойного экрана.

FoldableLayout также может создать единый контейнер, когда приложение работает на складном устройстве.

Мы добавили четыре новых атрибута, которые помогут вам создать необходимый пользовательский интерфейс:

  • dual_portrait_single_layout_id. Позволяет получить идентификатор макета одного контейнера для двойного экрана в книжной ориентации.
  • is_dual_portrait_single_container. Позволяет создать один пустой контейнер для двойного экрана в альбомной ориентации.
  • dual_landscape_single_layout_id. Позволяет получить идентификатор макета одного контейнера для двойного экрана в альбомной ориентации.
  • is_dual_landscape_single_container. Позволяет создать один пустой контейнер для двойного экрана в альбомной ориентации.

Поддержка smallestScreenSize

Если действие переключается на новый режим экрана, но не восстанавливается, так как в файле манифеста задан флаг smallestScreenSize, макет обнаружит новую конфигурацию и автоматически изменит размер контейнеров или даже добавит или удалит второй контейнер в зависимости от конфигурации FoldableLayout.

Предварительный просмотр в Android Studio

  • tools_hinge_color — выбор цвета петли в режиме предварительного просмотра макета.
  • tools_screen_mode — выбор режима экрана в режиме предварительного просмотра макета.

Если вы добавляете фрагменты FoldableLayout в XML-файлах, для предварительного просмотра фрагмента пользовательского интерфейса потребуются следующие атрибуты:

  • 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

Идентификаторы контейнеров

Контейнеры имеют такие идентификаторы:

  • first_container_id
  • second_container_id

Если в макете будет отображаться только один контейнер, идентификатором контейнера будет first_container_id. Это не зависит от ориентации экрана или особого поведения, заданного для макета. Если в макете будет два контейнера, будет использоваться и идентификатор second_container_id.

Например:

  • Если приложение отображается в режиме одинарного экрана, идентификатором контейнера будет first_container_id.
  • Если выполнен переход в режим двойного экрана и задан атрибут dual_portrait_single_layout_id или is_dual_portrait_single_container, то в этом режиме будет только один контейнер с тем же идентификатором first_container_id.
  • Если выполнен переход в режим двойного экрана, но атрибуты dual_landscape_single_layout_id и is_dual_landscape_single_container не заданы, будут присутствовать оба контейнера с идентификаторами first_container_id и second_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()

Использование компонентов макета

Чтобы создать приложение, можно использовать действие или действие с фрагментами для работы с пользовательским интерфейсом. Фрагменты также можно объявить в файле ресурсов макета или можно создать их непосредственно в действии. О том, как компоненты ведут себя в этих ситуациях, речь пойдет позже.

схема процесса

Использование действия

Здесь мы рассмотрим работу компонентов, используя только действие для управления пользовательским интерфейсом.

  1. Сначала необходимо добавить FoldableLayout в XML-файл действия.

    <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. Свяжите макет с вашим действием.

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

Использование фрагментов, объявленных в файлах ресурсов

Здесь мы видим, как компоненты работают с фрагментами, объявленными в XML-файлах.

  1. Сначала необходимо добавить FoldableLayout в XML-файл действия.

    <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.xml, dualscreenstartlayout.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. Сначала необходимо добавить FoldableLayout в XML-файл действия.

    <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 с помощью их идентификаторов:

    • first_container_id
    • second_container_id
  3. Теперь перейдите к библиотеке обработчика состояний диспетчера фрагментов, поскольку фрагменты требуют особой осторожности при изменении режима экрана.

View Binding

Важно!

Используйте findViewById, как показано в приведенных ниже фрагментах кода. Не пытайтесь использовать Google View Binding.

Так как содержимое FoldableLayout увеличивается, если у WindowManager есть доступные сведения о макете окна, вы не сможете получить и использовать дочерний экземпляр. Чтобы привязать дочернее представление, сначала необходимо убедиться, что содержимое 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.

Важно!

Вы должны добавить этот код в методы onResume и onPause из Activity или Fragment, чтобы избежать утечек памяти.