Fix: Selection toolbar may disappear in LazyColumn
Make sure that only the SelecitonContainer that is focused can show/hide/update the selection toolbar.
Bug: 178121997
Test: ./gradlew test
Change-Id: I7a38a016502720ed746f4d5321175ac9edc1a64e
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
index d630533..6448b20 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
@@ -18,7 +18,6 @@
package androidx.compose.foundation.text.selection
-import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.focusable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
@@ -95,9 +94,9 @@
var focusRequester: FocusRequester = FocusRequester()
/**
- * MutableInteractionSource for the selection container, containing focus interactions.
+ * Return true if the corresponding SelectionContainer is focused.
*/
- val interactionSource: MutableInteractionSource = MutableInteractionSource()
+ var hasFocus: Boolean by mutableStateOf(false)
/**
* Modifier for selection container.
@@ -106,11 +105,12 @@
.onGloballyPositioned { containerLayoutCoordinates = it }
.focusRequester(focusRequester)
.onFocusChanged { focusState ->
- if (!focusState.isFocused) {
+ if (!focusState.isFocused && hasFocus) {
onRelease()
}
+ hasFocus = focusState.isFocused
}
- .focusable(interactionSource = interactionSource)
+ .focusable()
.onKeyEvent {
if (isCopyKeyEvent(it)) {
copy()
@@ -126,8 +126,10 @@
var containerLayoutCoordinates: LayoutCoordinates? = null
set(value) {
field = value
- updateHandleOffsets()
- updateSelectionToolbarPosition()
+ if (hasFocus) {
+ updateHandleOffsets()
+ updateSelectionToolbarPosition()
+ }
}
/**
@@ -179,8 +181,8 @@
isStartHandle = true,
longPress = touchMode
)
- hideSelectionToolbar()
focusRequester.requestFocus()
+ hideSelectionToolbar()
}
selectionRegistrar.>
@@ -334,25 +336,27 @@
* the copy method as a callback when "copy" is clicked.
*/
internal fun showSelectionToolbar() {
- selection?.let {
- textToolbar?.showMenu(
- getContentRect(),
- >
- copy()
- onRelease()
- }
- )
+ if (hasFocus) {
+ selection?.let {
+ textToolbar?.showMenu(
+ getContentRect(),
+ >
+ copy()
+ onRelease()
+ }
+ )
+ }
}
}
internal fun hideSelectionToolbar() {
- if (textToolbar?.status == TextToolbarStatus.Shown) {
+ if (hasFocus && textToolbar?.status == TextToolbarStatus.Shown) {
textToolbar?.hide()
}
}
private fun updateSelectionToolbarPosition() {
- if (textToolbar?.status == TextToolbarStatus.Shown) {
+ if (hasFocus && textToolbar?.status == TextToolbarStatus.Shown) {
showSelectionToolbar()
}
}