1 /* <lambda>null2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.foundation.interaction 18 19 import androidx.compose.runtime.Composable 20 import androidx.compose.runtime.LaunchedEffect 21 import androidx.compose.runtime.State 22 import androidx.compose.runtime.mutableStateOf 23 import androidx.compose.runtime.remember 24 import kotlinx.coroutines.flow.collect 25 26 // An interface, not a sealed class, to allow adding new types here in a safe way (and not break 27 // exhaustive when clauses) 28 /** 29 * An interaction related to focus events. 30 * 31 * @see androidx.compose.foundation.focusable 32 * @see Focus 33 * @see Unfocus 34 */ 35 interface FocusInteraction : Interaction { 36 /** 37 * An interaction representing a focus event on a component. 38 * 39 * @see androidx.compose.foundation.focusable 40 * @see Unfocus 41 */ 42 class Focus : FocusInteraction 43 44 /** 45 * An interaction representing a [Focus] event being released on a component. 46 * 47 * @property focus the source [Focus] interaction that is being released 48 * @see androidx.compose.foundation.focusable 49 * @see Focus 50 */ 51 class Unfocus(val focus: Focus) : FocusInteraction 52 } 53 54 /** 55 * Subscribes to this [MutableInteractionSource] and returns a [State] representing whether this 56 * component is focused or not. 57 * 58 * [FocusInteraction] is typically set by [androidx.compose.foundation.focusable] and focusable 59 * components, such as [androidx.compose.foundation.text.BasicTextField]. 60 * 61 * @return [State] representing whether this component is being focused or not 62 */ 63 @Composable collectIsFocusedAsStatenull64fun InteractionSource.collectIsFocusedAsState(): State<Boolean> { 65 val isFocused = remember { mutableStateOf(false) } 66 LaunchedEffect(this) { 67 val focusInteractions = mutableListOf<FocusInteraction.Focus>() 68 interactions.collect { interaction -> 69 when (interaction) { 70 is FocusInteraction.Focus -> focusInteractions.add(interaction) 71 is FocusInteraction.Unfocus -> focusInteractions.remove(interaction.focus) 72 } 73 isFocused.value = focusInteractions.isNotEmpty() 74 } 75 } 76 return isFocused 77 } 78