| page.title=Поддержка многооконного режима |
| page.metaDescription=Новые возможности в Android N для одновременного отображения нескольких приложений. |
| page.keywords="multi-window", "android N", "split screen", "free-form" |
| |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>Содержание документа</h2> |
| <ol> |
| <li><a href="#overview">Обзор</a></li> |
| <li><a href="#lifecycle">Жизненный цикл многооконного режима</a></li> |
| <li><a href="#configuring">Настройка приложения для многооконного |
| режима</a></li> |
| <li><a href="#running">Запуск приложения в многооконном режиме</a></li> |
| <li><a href="#testing">Тестирование приложения в многооконном режиме</a></li> |
| </ol> |
| <h2>См. также:</h2> |
| <ol> |
| <li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Пример |
| многооконного демонстрационного приложения</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p> |
| В Android N добавлена поддержка отображения нескольких приложений |
| одновременно. На мобильных устройствах два приложения могут быть запущены рядом |
| или друг над другом в режиме <em>разделения экрана</em>. На телевизорах приложения могут |
| использовать режим <em>"картинка в картинке"</em>, чтобы воспроизводить видео, |
| пока пользователи работают с другим приложением. |
| </p> |
| |
| <p> |
| Если вы создаете приложение с использованием N Preview SDK, вы можете указать, как оно |
| будет действовать в многооконном режиме. Например, можно задать минимальные |
| допустимые размеры окна приложения. Также можно отключить многооконный режим для приложения, |
| чтобы оно отображалось только в полноэкранном |
| режиме. |
| </p> |
| |
| <h2 id="overview">Обзор</h2> |
| |
| <p> |
| В Android N несколько приложений могут одновременно находиться на экране. Например, |
| пользователь может разделить экран, чтобы просматривать веб-страницу |
| слева и писать сообщение электронной почты справа. Возможности пользователя зависят от |
| устройства. |
| </p> |
| |
| <ul> |
| <li>На мобильных устройствах с Android N доступен режим |
| разделения экрана. В этом режиме два приложения отображаются рядом |
| или друг над другом. Пользователь может перетащить |
| линию разделения, чтобы увеличить окно одного приложения и уменьшить окно другого. |
| </li> |
| |
| <li>На устройствах Nexus Player с Android N для приложений |
| будет доступен <a href="picture-in-picture.html">режим "картинка в картинке"</a>, который |
| позволит приложению отображать контент, пока пользователь просматривает |
| другие приложения или взаимодействует с ними. |
| </li> |
| |
| <li>Производители более крупных устройств могут активировать |
| режим произвольной формы, где пользователь может любым образом изменять размер каждого окна. В этом случае |
| помимо режима разделения экрана |
| на устройстве будет доступен и этот режим. |
| </li> |
| </ul> |
| |
| <img src="{@docRoot}preview/images/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}preview/images/mw-splitscreen.png 1x, |
| {@docRoot}preview/images/mw-splitscreen_2x.png 2x," id="img-split-screen" /> |
| <p class="img-caption"> |
| <strong>Рис. 1.</strong> Два приложения отображаются рядом в режиме разделения экрана. |
| </p> |
| |
| <p> |
| Пользователь может перейти в многооконный режим следующими способами. |
| </p> |
| |
| <ul> |
| <li>Если пользователь откроет <a href="{@docRoot}guide/components/recents.html">экран |
| обзора</a> и длительно нажмет |
| название операции, ее можно будет перетащить в выделенную часть |
| экрана и переключить в многооконный режим. |
| </li> |
| |
| <li>Если пользователь длительно нажмет кнопку "Обзор", устройство |
| переключит текущую операцию в многооконный режим и откроет экран обзора, |
| где пользователь сможет выбрать другую операцию для совместного отображения. |
| </li> |
| </ul> |
| |
| <p> |
| Пользователи могут <a href="{@docRoot}guide/topics/ui/drag-drop.html">перетаскивать</a> |
| данные между окнами операций в режиме |
| совместного отображения. (Ранее перетаскивать данные можно было только в рамках |
| одной операции). |
| </p> |
| |
| <h2 id="lifecycle">Жизненный цикл многооконного режима</h2> |
| |
| <p> |
| Многооконный режим не меняет <a href="{@docRoot}training/basics/activity-lifecycle/index.html">жизненный |
| цикл операции</a>. |
| </p> |
| |
| <p> |
| В этом режиме в каждый момент времени активной |
| является только последняя операция, с которой взаимодействовал пользователь. Такая операция считается <em>самой верхней</em>. |
| Все другие операции приостановлены, даже если они отображаются. |
| Однако система отдает приостановленным, но видимым операциям более |
| высокий приоритет, чем невидимым. Если пользователь взаимодействует с |
| одной из приостановленных операций, она возобновляется, а прежняя самая верхняя |
| операция приостанавливается. |
| </p> |
| |
| <p class="note"> |
| <strong>Примечание.</strong> В многооконном режиме приложение может быть приостановлено |
| и по-прежнему видимо для пользователя. Приложению может потребоваться |
| продолжать свои операции, даже если оно приостановлено. Например, видимое приостановленное приложение, |
| воспроизводящее видео, будет по-прежнему показывать видео. Поэтому |
| мы <em>не</em> рекомендуем приостанавливать воспроизведение |
| в обработчиках {@link android.app.Activity#onPause onPause()} таких приложений. |
| Вместо этого следует приостановить видео в {@link android.app.Activity#onStop |
| onStop()} и возобновить воспроизведение в {@link android.app.Activity#onStart |
| onStart()}. |
| </p> |
| |
| <p> |
| Если пользователь переводит приложение в многооконный режим, система |
| уведомляет операцию об изменении конфигурации, как указано в документе <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Обработка изменений |
| во время выполнения</a>. По сути это изменение так же действует |
| на жизненный цикл операции, как уведомление приложения системой |
| о переходе устройства из вертикальной ориентации в |
| горизонтальную, только изменяются размеры экрана, а не ориентация. Как описано в документе <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Обработка изменений |
| во время выполнения</a>, операция может обработать изменение |
| конфигурации самостоятельно или может позволить системе |
| удалить окно операции и создать его заново с новыми размерами. |
| </p> |
| |
| <p> |
| Если пользователь увеличивает одну из сторон окна, система меняет |
| размер окна операции в соответствии с действием пользователя и применяет <a href="{@docRoot}guide/topics/resources/runtime-changes.html">изменения в режиме выполнения</a> |
| по мере необходимости. Если приложение не успевает отрисовать новые области, система |
| временно заполняет их цветом, заданным атрибутом {@link |
| android.R.attr#windowBackground windowBackground} или атрибутом стиля |
| <code>windowBackgroundFallback</code> по умолчанию. |
| </p> |
| |
| <h2 id="configuring">Настройка приложения для многооконного режима</h2> |
| |
| <p> |
| Если ваше приложение предназначено для Android N, вы |
| можете указать, каким образом поддерживают (и поддерживают ли) операции вашего приложения многооконный режим. Атрибуты управления размером и макетом устанавливаются |
| в манифесте. |
| Настройки атрибутов корневой операции применяются |
| ко всем операциям в ее стеке задач. |
| </p> |
| |
| <p class="note"> |
| <strong>Примечание.</strong> Если приложение с поддержкой различной |
| ориентации было создано с версией SDK, |
| более ранней, чем Android N, и пользователь запустит это приложение в многооконном режиме, система принудительно изменит размер приложения. Система отображает диалоговое окно |
| с предупреждением о том, что приложение может работать непредвиденным образом. Система |
| <em>не</em> меняет размер окна для приложений с |
| фиксированной ориентацией. Если пользователь попытается открыть такое приложение |
| в многооконном режиме, оно займет весь экран. |
| </p> |
| |
| <h4 id="resizeableActivity">android:resizeableActivity</h4> |
| <p> |
| Установите этот атрибут в узле <code><activity></code> или |
| <code><application></code> манифеста, чтобы включить или отключить многооконный |
| режим: |
| </p> |
| |
| <pre> |
| android:resizeableActivity=["true" | "false"] |
| </pre> |
| |
| <p> |
| Если для этого атрибута задано значение true, операцию можно запускать |
| в режимах разделения экрана и произвольной формы. Если для атрибута задано значение false, |
| операция не поддерживает многооконный режим. Если значение равно false и |
| пользователь пытается запустить операцию в многооконном режиме, она |
| занимает весь экран. |
| </p> |
| |
| <p> |
| Если приложение предназначено для Android N, но |
| значение для этого атрибута не было указано, то по умолчанию используется значение true. |
| </p> |
| |
| <h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4> |
| |
| <p> |
| Установите этот атрибут в узле <code><activity></code> манифеста, |
| чтобы указать, поддерживает ли операция режим "картинка в картинке". Этот |
| атрибут не принимается во внимание, если для <code>android:resizeableActivity</code> установлено значение false. |
| </p> |
| |
| <pre> |
| android:supportsPictureInPicture=["true" | "false"] |
| </pre> |
| |
| <h3 id="layout">Атрибуты макета</h3> |
| |
| <p> |
| В Android N элемент манифеста <code><layout></code> поддерживает |
| несколько атрибутов, которые определяют поведение |
| операции в многооконном режиме. |
| </p> |
| |
| <dl> |
| <dt> |
| <code>android:defaultWidth</code> |
| </dt> |
| |
| <dd> |
| Ширина окна операции по умолчанию в режиме произвольной формы. |
| </dd> |
| |
| <dt> |
| <code>android:defaultHeight</code> |
| </dt> |
| |
| <dd> |
| Высота окна операции по умолчанию в режиме произвольной формы. |
| </dd> |
| |
| <dt> |
| <code>android:gravity</code> |
| </dt> |
| |
| <dd> |
| Начальная позиция окна операции в режиме произвольной формы. Допустимые значения |
| см. в описании класса {@link android.view.Gravity}. |
| </dd> |
| |
| <dt> |
| <code>android:minimalSize</code> |
| </dt> |
| |
| <dd> |
| Минимальные значения высоты и ширины окна операции в режимах разделения экрана |
| и произвольной формы. Если пользователь перемещает разделительную линию |
| в режиме разделения экрана, чтобы сделать размер окна операции |
| меньше указанного минимума, система обрезает его до запрошенного пользователем размера. |
| </dd> |
| </dl> |
| |
| <p> |
| В следующем примере кода показано, как задать размер и |
| позицию окна операции по умолчанию, а также ее минимальный размер в |
| режиме произвольной формы: |
| </p> |
| |
| <pre> |
| <activity android:name=".MyActivity"> |
| <layout android:defaultHeight="500dp" |
| android:defaultWidth="600dp" |
| android:gravity="top|end" |
| android:minimalSize="450dp" /> |
| </activity> |
| </pre> |
| |
| <h2 id="running">Запуск приложения в многооконном режиме</h2> |
| |
| <p> |
| Android N предоставляет новые возможности для поддержки |
| приложений в многооконном режиме. |
| </p> |
| |
| <h3 id="disabled-features">Недоступные возможности в многооконном режиме</h3> |
| |
| <p> |
| Некоторые возможности отключены или игнорируются в многооконном |
| режиме, потому что они не имеют смысла для операции, которая отображается |
| на экране устройства одновременно с другими операциями или приложениями. Ниже приведены примеры таких возможностей. |
| |
| <ul> |
| <li>Отключены некоторые параметры настройки <a href="{@docRoot}training/system-ui/index.html">системного интерфейса</a>. |
| Например, приложения не могут |
| скрыть строку состояния, если они не работают в полноэкранном режиме. |
| </li> |
| |
| <li>Система не учитывает изменения атрибута <code><a href= |
| "{@docRoot}guide/topics/manifest/activity-element.html#screen" |
| >android:screenOrientation</a></code>. |
| </li> |
| </ul> |
| |
| <h3 id="change-notification">Уведомления об изменениях и запросы в многооконном режиме</h3> |
| |
| <p> |
| Для поддержки многооконного режима в класс {@link android.app.Activity} |
| были добавлены следующие методы. Подробнее о каждом из них см. в |
| <a href="{@docRoot}preview/setup-sdk.html#docs-dl">справочнике по N Preview SDK</a>. |
| </p> |
| |
| <dl> |
| <dt> |
| <code>Activity.inMultiWindow()</code> |
| </dt> |
| |
| <dd> |
| Вызовите этот метод, чтобы узнать, находится ли операция в многооконном режиме. |
| </dd> |
| |
| <dt> |
| <code>Activity.inPictureInPicture()</code> |
| </dt> |
| |
| <dd> |
| Вызовите этот метод, чтобы узнать, находится ли операция в режиме "картинка в картинке". |
| |
| <p class="note"> |
| <strong>Примечание.</strong> Режим "картинка в картинке" — это частный |
| случай многооконного режима. Если метод <code>myActivity.inPictureInPicture()</code> |
| возвращает значение true, <code>myActivity.inMultiWindow()</code> также возвращает |
| true. |
| </p> |
| </dd> |
| |
| <dt> |
| <code>Activity.onMultiWindowChanged()</code> |
| </dt> |
| |
| <dd> |
| Система вызывает этот метод, когда операция переходит в многооконный |
| режим или выходит из него. Система передает методу значение true, если |
| операция входит в многооконный режим, и значение false, если |
| она выходит из него. |
| </dd> |
| |
| <dt> |
| <code>Activity.onPictureInPictureChanged()</code> |
| </dt> |
| |
| <dd> |
| Система вызывает этот метод, когда операция переходит в режим |
| "картинка в картинке". Система передает методу значение true, |
| если операция входит в режим "картинка в картинке", и значение false, |
| если она выходит из него. |
| </dd> |
| </dl> |
| |
| <p> |
| Также существуют версии {@link android.app.Fragment} для этих методов, |
| например, <code>Fragment.inMultiWindow()</code>. |
| </p> |
| |
| <h3 id="entering-pip">Переход в режим "картинка в картинке"</h3> |
| |
| <p> |
| Чтобы перевести операцию в режим "картинка в картинке", |
| вызовите новый метод <code>Activity.enterPictureInPicture()</code>. Этот метод игнорируется, если |
| устройство не поддерживает режим "картинка в картинке". Дополнительная информация содержится в документации |
| <a href="picture-in-picture.html">Режим "картинка в картинке"</a>. |
| </p> |
| |
| <h3 id="launch">Запуск новых операций в многооконном режиме</h3> |
| |
| <p> |
| При запуске новой операции можно сообщить системе, что окно новой |
| операции следует показать рядом с текущим, если это возможно. Для этого |
| используйте флаг |
| <code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Этот |
| флаг запрашивает следующее поведение. |
| </p> |
| |
| <ul> |
| <li>Если устройство находится в режиме разделения экрана, система пытается |
| создать окно новой операции рядом с окном запустившей ее операции, |
| чтобы разместить две операции на экране. Не гарантируется, что система сможет это сделать, но если |
| это возможно, операции отображаются рядом друг с другом. |
| </li> |
| |
| <li>Если устройство не находится в режиме разделения экрана, этот флаг не учитывается. |
| </li> |
| </ul> |
| |
| <p> |
| Если при запуске |
| новой операции устройство находится в режиме произвольной формы, вы можете задать размеры и позицию окна новой операции, |
| вызвав метод <code>ActivityOptions.setLaunchBounds()</code>. Этот метод игнорируется, если |
| устройство не находится в многооконном режиме. |
| </p> |
| |
| <p class="note"> |
| <strong>Примечание.</strong> Если запустить операцию в стеке задач, |
| она заменит операцию на экране, унаследовав все ее |
| свойства многооконного режима. Чтобы запустить новую операцию в отдельном |
| окне в многооконном режиме, ее следует запустить в новом стеке задач. |
| </p> |
| |
| <h3 id="dnd">Поддержка перетаскивания</h3> |
| |
| <p> |
| Пользователи могут <a href="{@docRoot}guide/topics/ui/drag-drop.html">перетаскивать</a> данные |
| между окнами операций в режиме |
| совместного отображения. (Ранее перетаскивать данные можно было только в рамках |
| одной операции). Поэтому вы можете реализовать функции перетаскивания |
| в своем приложении, если оно еще их не поддерживает. |
| </p> |
| |
| <p> |
| В N Preview SDK пакет <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a> |
| расширен для поддержки перетаскивания между приложениями. Дополнительная информация о нижеприведенных классах |
| и методах содержится в <a href="{@docRoot}preview/setup-sdk.html#docs-dl">справочнике по N |
| Preview SDK</a>. |
| </p> |
| |
| <dl> |
| <dt> |
| <code>android.view.DropPermissions</code> |
| </dt> |
| |
| <dd> |
| Объект токена для указания разрешений |
| приложению, в которое перетаскиваются данные. |
| </dd> |
| |
| <dt> |
| <code>View.startDragAndDrop()</code> |
| </dt> |
| |
| <dd> |
| Новый псевдоним для {@link android.view.View#startDrag View.startDrag()}. Чтобы |
| разрешить перетаскивание между операциями, передайте |
| новый флаг <code>View.DRAG_FLAG_GLOBAL</code>. Если вам нужно предоставить принимающей операции разрешения на чтение или запись URI, |
| передайте новый флаг |
| <code>View.DRAG_FLAG_GLOBAL_URI_READ</code> или |
| <code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code> соответственно. |
| </dd> |
| |
| <dt> |
| <code>View.cancelDragAndDrop()</code> |
| </dt> |
| |
| <dd> |
| Отменяет текущую операцию перетаскивания. Этот метод может вызвать только |
| приложение, в котором была инициирована операция перетаскивания. |
| </dd> |
| |
| <dt> |
| <code>View.updateDragShadow()</code> |
| </dt> |
| |
| <dd> |
| Заменяет тень текущей операции перетаскивания. Этот метод может вызвать только приложение, |
| в котором была инициирована операция перетаскивания. |
| </dd> |
| |
| <dt> |
| <code>Activity.requestDropPermissions()</code> |
| </dt> |
| |
| <dd> |
| Запрашивает разрешения для URI контента, переданных в объекте {@link |
| android.content.ClipData} в {@link android.view.DragEvent}. |
| </dd> |
| </dl> |
| |
| <h2 id="testing">Тестирование приложения в многооконном режиме</h2> |
| |
| <p> |
| Независимо от того, обновляете ли вы свое приложение для Android N, вам необходимо |
| подтвердить его поведение в многооконном |
| режиме на тот случай, если пользователь попытается запустить его в этом режиме на устройстве с Android N. |
| </p> |
| |
| <h3 id="configuring">Настройка тестового устройства</h3> |
| |
| <p> |
| Если установить Android N на устройстве, режим разделения |
| экрана будет поддерживаться автоматически. |
| </p> |
| |
| <h3 id="test-non-n">Если приложение было создано без использования N Preview SDK</h3> |
| |
| <p> |
| Если вы не применяли N Preview SDK для создания приложения и пользователь |
| попытается запустить его в многооконном режиме, система принудительно |
| изменит размер окна приложения, если его ориентация не зафиксирована. |
| </p> |
| |
| <p> |
| Если для приложения не задана фиксированная ориентация, вам |
| следует запустить его на устройстве с Android N и попытаться |
| перевести его в режим разделения экрана. Убедитесь, что приложение |
| работает нормально после принудительного изменения размера. |
| </p> |
| |
| <p> |
| Если для приложения задана фиксированная ориентация, попытайтесь |
| перевести его в многооконный режим. Убедитесь, что при этом |
| приложение остается в полноэкранном режиме. |
| </p> |
| |
| <h3 id="test-mw">Если приложение поддерживает многооконный режим</h3> |
| |
| <p> |
| Если вы использовали N Preview SDK для создания приложения и не |
| отключили поддержку многооконного режима, проверьте работу |
| приложения, как описано далее, в режимах разделения экрана и произвольной формы. |
| </p> |
| |
| <ul> |
| <li>Запустите приложение в полноэкранном режиме, а затем переключитесь |
| в многооконный режим долгим нажатием кнопки "Обзор". Убедитесь, что приложение корректно переключается между режимами. |
| </li> |
| |
| <li>Запустите приложение непосредственно в многооконном режиме |
| и убедитесь, что оно работает нормально. Вы можете запустить приложение в многооконном режиме, нажав |
| кнопку "Обзор", затем длительно нажав строку заголовка приложения и |
| перетащив ее в одну из выделенных областей на экране. |
| </li> |
| |
| <li>Измените размер окна приложения в режиме разделения экрана, перетащив линию разделения. |
| Убедитесь, что изменение размера не приводит к сбою и что необходимые |
| элементы интерфейса остаются видимыми. |
| </li> |
| |
| <li>Если вы указали минимальные размеры окна приложения, попытайтесь |
| установить размер меньше минимального. Убедитесь в невозможности установить размер |
| меньше указанного минимума. |
| </li> |
| |
| <li>Во время всех тестов следите за производительностью приложения — она должна быть приемлемой. Например, |
| убедитесь, что после изменения размера окна приложения не возникает большой |
| задержки обновления интерфейса. |
| </li> |
| </ul> |
| |
| <h4 id="test-checklist">Контрольный список тестирования</h4> |
| |
| <p> |
| Для проверки производительности приложения в многооконном режиме |
| выполните следующие операции. Попытайтесь выполнить их в режиме разделения экрана и |
| в многооконном режиме, если не указано иное. |
| </p> |
| |
| <ul> |
| <li>Перейдите в многооконный режим и выйдите из него. |
| </li> |
| |
| <li>Переключитесь из своего приложения в другое приложение и убедитесь, |
| что приложение работает нормально, если оно видимо, но не активно. Например, если приложение |
| показывает видео, оно должно продолжать воспроизведение, когда |
| пользователь работает с другим приложением. |
| </li> |
| |
| <li>В режиме разделения экрана попробуйте перемещать линию |
| разделения, увеличивая и уменьшая окно приложения. Попробуйте выполнить эти операции, когда окна двух |
| приложений находятся рядом и друг над другом. Убедитесь, что приложение не завершается с ошибкой, |
| необходимые элементы видны и изменение размера не занимает |
| слишком много времени. |
| </li> |
| |
| <li>Быстро измените размер окна приложения несколько раз подряд. Убедитесь, что |
| приложение не зависает и не вызывает утечку памяти. Информация о проверке использования памяти |
| приложением содержится в документе <a href="{@docRoot}tools/debugging/debugging-memory.html"> |
| Анализ использования оперативной памяти</a>. |
| </li> |
| |
| <li>Поработайте с приложением в различных оконных конфигурациях и |
| убедитесь, что оно ведет себя должным образом. Текст должен легко читаться, а |
| элементы интерфейса не должны быть слишком маленькими. |
| </li> |
| </ul> |
| |
| <h3 id="test-disabled-mw">Если вы отключили поддержку многооконного режима</h3> |
| |
| <p> |
| Если вы отключили поддержку многооконного режима, |
| установив атрибут <code>android:resizableActivity="false"</code>, запустите |
| приложение на устройстве с Android N и |
| попытайтесь перевести его в режимы произвольной формы и разделения экрана. Убедитесь, что при этом |
| приложение остается в полноэкранном режиме. |
| </p> |