Когда пользователь взаимодействует с вашим приложением, он часто делает это, касаясь элементов на экране. Однако это не единственная форма взаимодействия. Другими формами взаимодействия могут быть следующие:
- Пользователь ChromeOS может использовать клавиши со стрелками на физической клавиатуре для навигации по экрану.
- Кто-то, играющий в игру, может использовать подключенный игровой контроллер для навигации по меню игры.
- Пользователь мобильного приложения может переключаться между элементами с помощью экранной клавиатуры .
В этих случаях важно отслеживать, какой компонент активен в тот или иной момент времени, это то, что мы называем фокусом . Элементы на экране должны располагаться в логическом порядке. Jetpack Compose имеет стандартный способ управления фокусом, который в большинстве случаев является правильным. Однако в некоторых случаях вам может потребоваться изменить это поведение по умолчанию.
На следующих страницах описано, как использовать фокус в вашем приложении:
- Изменить порядок обхода фокуса . Объясняет, как изменить порядок фокуса по умолчанию, добавить фокус-группы и отключить фокус составного объекта.
- Изменение поведения фокуса : описывает, как запрашивать, захватывать и отпускать фокус, а также как перенаправлять фокус при входе на экран.
- Реакция на фокус : объясняет, как реагировать на изменения фокуса, добавлять визуальные подсказки к элементам и понимать состояние фокуса элемента.
Порядок обхода фокуса по умолчанию
Прежде чем мы углубимся в поведение по умолчанию при поиске фокуса, важно понять концепцию уровня в иерархии: вообще говоря, мы можем сказать, что два Composables
находятся на одном уровне, когда они являются братьями и сестрами, то есть у них одни и те же родители. . Например, элементы внутри Column
находятся на одном уровне. Повышение уровня означает переход от дочернего элемента к его Composable
родительскому элементу или, сохраняя тот же пример, возврат от элемента к Column
, который его содержит. Спуск на уровень происходит наоборот: от родительского Column
к содержащимся в нем элементам. Эту концепцию можно применить к каждому Composable
, который может содержать другие Composables
.
Навигация по пользовательскому интерфейсу может осуществляться несколькими способами, некоторые из которых уже известны большинству пользователей:
- Вкладки: одномерная навигация вперед или назад . Навигация с помощью TAB переводит фокус на следующий или предыдущий элемент иерархии. По умолчанию Compose следует объявлению
Composables
. Однонаправленную навигацию можно осуществить с помощью клавишиtab
на клавиатуре или вращающегося безеля на часах, и такой вид поиска фокуса будет охватывать каждый элемент на экране. - Клавиши со стрелками: двухмерная навигация влево, вправо, вверх или вниз . Двухмерная навигация может быть достигнута с помощью D-Pad на телевизоре или клавиш со стрелками на клавиатуре, а порядок ее обхода касается только элементов на заданном уровне. Вы можете использовать центральную кнопку D-Pad и кнопку «Назад», чтобы перейти вниз и вернуться на другой уровень.
Возьмем в качестве примера снимок экрана ниже, где у вас есть четыре кнопки, одна под другой, и вы хотите просмотреть их все в порядке появления. Jetpack Compose обеспечивает такое поведение «из коробки»: набор инструментов позволяет циклически просматривать каждый компонуемый объект в вертикальном порядке сверху вниз с помощью клавиши tab
или перемещать фокус, нажимая стрелку вверх или вниз .
![Скриншот списка кнопок, расположенных вертикально одна под другой в небольшом форм-факторе.](https://developer.android.com/static/develop/ui/compose/images/touchinput/focus_compact_screen.png?authuser=6&hl=ru)
Когда вы переключаетесь на другой тип макета, все немного меняется. Если ваш макет содержит более одного столбца, как показано ниже, Jetpack Compose позволяет перемещаться по ним без необходимости добавления какого-либо кода. Если вы нажмете клавишу tab
, Jetpack Compose автоматически выделит элементы в порядке объявления, от первого до четвертого. Используя клавиши со стрелками на клавиатуре, выбор будет следовать в желаемом направлении в 2D-пространстве.
Column { Row { TextButton({ }) { Text("First field") } TextButton({ }) { Text("Second field") } } Row { TextButton({ }) { Text("Third field") } TextButton({ }) { Text("Fourth field") } } }
Composables
объявляются в двух Rows
, а элементы фокуса объявляются по порядку, с первого по четвертый. Когда вы нажимаете клавишу tab
, это приводит к следующему порядку фокусировки:
![Снимок экрана: список кнопок, размещенных в двух столбцах рядом, в увеличенном форм-факторе.](https://developer.android.com/static/develop/ui/compose/images/touchinput/focus_horizontal_navigation.gif?authuser=6&hl=ru)
В приведенном ниже фрагменте вы объявляете элементы в Columns
, а не в Rows
:
Row { Column { TextButton({ }) { Text("First field") } TextButton({ }) { Text("Second field") } } Column { TextButton({ }) { Text("Third field") } TextButton({ }) { Text("Fourth field") } } }
Этот макет перемещает элементы вертикально, сверху вниз, от начала экрана к концу:
![Снимок экрана: список кнопок, размещенных в двух столбцах рядом, в увеличенном форм-факторе.](https://developer.android.com/static/develop/ui/compose/images/touchinput/focus_vertical_navigation.gif?authuser=6&hl=ru)
Два предыдущих примера, хотя и отличаются однонаправленной навигацией, обеспечивают одинаковые возможности двумерной навигации. Обычно это происходит потому, что в обоих примерах элементы на экране имеют одинаковое географическое расположение. При перемещении вправо от первого Column
фокус перемещается ко второму, а при перемещении вниз от первой Row
фокус перемещается на строку под ней.
Рекомендуется для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Изменение поведения фокуса
- ConstraintLayout в Compose
- Макеты потоков в Compose