FocusOrderModifier.kt
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.ui.focus
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.platform.InspectorValueInfo
import androidx.compose.ui.platform.debugInspectorInfo
/**
* A [modifier][Modifier.Element] that can be used to set a custom focus traversal order.
*
* @see Modifier.focusOrder
*/
interface FocusOrderModifier : Modifier.Element {
/**
* Populates the [next][FocusOrder.next] / [left][FocusOrder.left] /
* [right][FocusOrder.right] / [up][FocusOrder.up] / [down][FocusOrder.down] items if
* you don't want to use the default focus traversal order.
*/
fun populateFocusOrder(focusOrder: FocusOrder)
}
/**
* Specifies custom focus destinations that are used instead of the default focus traversal order.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
class FocusOrder {
/**
* A custom item to be used when the user requests a focus moves to the "next" item.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var next: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user requests a focus moves to the "previous" item.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var previous: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user moves focus "up".
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var up: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user moves focus "down".
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var down: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user requests a focus moves to the "left" item.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var left: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user requests a focus moves to the "right" item.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var right: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user requests a focus moves to the "left" in LTR mode and
* "right" in RTL mode.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var start: FocusRequester = FocusRequester.Default
/**
* A custom item to be used when the user requests a focus moves to the "right" in LTR mode
* and "left" in RTL mode.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
var end: FocusRequester = FocusRequester.Default
}
internal class FocusOrderModifierImpl(
val focusOrderReceiver: FocusOrder.() -> Unit,
inspectorInfo: InspectorInfo.() -> Unit
) : FocusOrderModifier, InspectorValueInfo(inspectorInfo) {
override fun populateFocusOrder(focusOrder: FocusOrder) {
focusOrderReceiver(focusOrder)
}
}
/**
* Use this modifier to specify a custom focus traversal order.
*
* @param focusOrderReceiver Specifies [FocusRequester]s that are used when the user wants
* to move the current focus to the [next][FocusOrder.next] item, or wants to move
* focus [left][FocusOrder.left], [right][FocusOrder.right], [up][FocusOrder.up] or
* [down][FocusOrder.down].
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
fun Modifier.focusOrder(focusOrderReceiver: FocusOrder.() -> Unit): Modifier {
return this.then(
FocusOrderModifierImpl(
focusOrderReceiver = focusOrderReceiver,
inspectorInfo = debugInspectorInfo {
name = "focusOrder"
properties["focusOrderReceiver"] = focusOrderReceiver
}
)
)
}
/**
* A modifier that lets you specify a [FocusRequester] for the current composable so that this
* [focusRequester] can be used by another composable to specify a custom focus order.
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
fun Modifier.focusOrder(focusRequester: FocusRequester): Modifier = focusRequester(focusRequester)
/**
* A modifier that lets you specify a [FocusRequester] for the current composable along with
* [focusOrder].
*
* @sample androidx.compose.ui.samples.CustomFocusOrderSample
*/
fun Modifier.focusOrder(
focusRequester: FocusRequester,
focusOrderReceiver: FocusOrder.() -> Unit
): Modifier = this
.focusRequester(focusRequester)
.focusOrder(focusOrderReceiver)