Порядок перехода фокуса

Пользователи могут перемещать фокус клавиатуры по элементам интерфейса с помощью клавиши Tab или клавиш со стрелками (D-pad):

  • Tab / Shift + Tab – перемещение фокуса вперед или назад в одномерном порядке появления.
  • Клавиши со стрелками: перемещение фокуса в двух измерениях (Вверх, Вниз, Влево и Вправо).

Одномерный переход по фокусу

При одномерном перемещении фокуса клавиша Tab перемещает фокус по интерфейсу в соответствии с порядком появления элементов на экране.

Например, если четыре кнопки расположены в ряд:

Column {
    Row {
        Button(onClick = { /* ... */ }) { Text("1st") }
        Button(onClick = { /* ... */ }) { Text("2nd") }
    }
    Row {
        Button(onClick = { /* ... */ }) { Text("3rd") }
        Button(onClick = { /* ... */ }) { Text("4th") }
    }
}

Нажатие клавиши Tab последовательно перемещает фокус по кнопкам в следующем порядке:

  1. Первая кнопка (вверху слева)
  2. Вторая кнопка (вверху)
  3. Третья кнопка (внизу слева)
  4. Четвертая кнопка (нижняя)

Если нажать Tab на последнем элементе, фокус вернется к первому. Чтобы переместить фокус в обратном порядке, нажмите Shift + Tab.

Двумерный обход фокуса

Нажатие клавиш со стрелками на клавиатуре или использование D-pad запускает двумерный обход фокуса.

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

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

Сбросить обход фокуса с помощью кликов указателя

При переключении между физической клавиатурой и мышью или сенсорной панелью на настольных компьютерах или устройствах с большим экраном:

  • Снимать фокус при нажатии. Нажатие на неинтерактивную область с помощью мыши или сенсорной панели снимает фокус с активного элемента.
  • Перезапуск обхода. После очистки фокуса следующее нажатие клавиши Tab перезапускает одномерный обход с первой цели фокусировки в порядке визуального отображения, а не возобновляет его с ранее активного элемента. Это то же самое, что и двумерный обход фокуса. Клавиши со стрелками перемещают фокус клавиатуры на ближайший объект в выбранном направлении.

Подробную информацию о программном снятии фокуса можно найти в разделе Перемещение и снятие фокуса.

Как настроить порядок обхода фокуса

Вы можете настроить поведение обхода с помощью модификатора focusProperties.

Как настроить одномерный порядок обхода

Чтобы переопределить одномерный обход, укажите свойство next или previous со значением FocusRequester:

  1. Создайте объект FocusRequester с помощью remember { FocusRequester() }.
  2. Прикрепите FocusRequester к целевой composable-функции с помощью модификатора focusRequester.
  3. Примените модификатор focusProperties к исходной composable-функции и назначьте FocusRequester для next (для Tab) или previous (для Shift + Tab).

val (first, second, third) = remember { FocusRequester.createRefs() }

Column {
    Button(
        onClick = { /* ... */ },
        modifier = Modifier
            .focusRequester(first)
            .focusProperties { next = third }
    ) {
        Text("First (Tab jumps to Third)")
    }
    Button(
        onClick = { /* ... */ },
        modifier = Modifier.focusRequester(second)
    ) {
        Text("Second")
    }
    Button(
        onClick = { /* ... */ },
        modifier = Modifier.focusRequester(third)
    ) {
        Text("Third")
    }
}

Как настроить двумерный порядок обхода

Аналогичным образом можно переопределить двумерный обход фокуса, назначив экземпляры FocusRequester для up, down, start, end, left или right в focusProperties:

val (topButton, bottomButton) = remember { FocusRequester.createRefs() }

Button(
    onClick = { /* ... */ },
    modifier = Modifier
        .focusRequester(topButton)
        .focusProperties {
            down = bottomButton
            right = bottomButton
        }
) {
    Text("Top button")
}
Button(
    onClick = { /* ... */ },
    modifier = Modifier.focusRequester(bottomButton)
) {
    Text("Bottom button")
}

Чтобы заблокировать навигацию с фокусом в определенном направлении (например, на границах макета), присвойте этому свойству значение FocusRequester.Cancel (например, down = FocusRequester.Cancel). Чтобы явно сохранить системный алгоритм обхода по умолчанию для заданного направления, присвойте значение FocusRequester.Default.