From 3e3285e4cc43ddeeab3d8e432df27554b22fe43e Mon Sep 17 00:00:00 2001 From: Vladimir Mazunin Date: Fri, 19 Apr 2024 17:08:14 +0400 Subject: [PATCH] fixed appearing text editing menu in textfields by every tap --- ...CupertinoTextFieldPointerModifier.skiko.kt | 6 +++--- .../text/TextFieldDelegate.skiko.kt | 19 ++++++++----------- .../text/CupertinoTextFieldDelegateTest.kt | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/CupertinoTextFieldPointerModifier.skiko.kt b/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/CupertinoTextFieldPointerModifier.skiko.kt index 32ff114ff5da8..031d497722efd 100644 --- a/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/CupertinoTextFieldPointerModifier.skiko.kt +++ b/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/CupertinoTextFieldPointerModifier.skiko.kt @@ -124,9 +124,9 @@ private fun getTapHandlerModifier( textLayoutResult = layoutResult, editProcessor = currentState.processor, offsetMapping = currentOffsetMapping, - showContextMenu = { - // it shouldn't be selection, but this is a way to call context menu in BasicTextField - currentManager.enterSelectionMode(true) + showContextMenu = { show -> + // it shouldn't be selection, but this is a way to call a context menu in BasicTextField + if (show) { currentManager.enterSelectionMode() } else { currentManager.exitSelectionMode() } }, onValueChange = currentState.onValueChange ) diff --git a/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.skiko.kt b/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.skiko.kt index fb7f11c67796b..bdcb09ef2d0f7 100644 --- a/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.skiko.kt +++ b/compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.skiko.kt @@ -17,7 +17,6 @@ package androidx.compose.foundation.text import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.EditProcessor import androidx.compose.ui.text.input.OffsetMapping @@ -40,24 +39,23 @@ internal fun TextFieldDelegate.Companion.cupertinoSetCursorOffsetFocused( textLayoutResult: TextLayoutResultProxy, editProcessor: EditProcessor, offsetMapping: OffsetMapping, - showContextMenu: (Rect) -> Unit, + showContextMenu: (Boolean) -> Unit, onValueChange: (TextFieldValue) -> Unit ) { val offset = offsetMapping.transformedToOriginal(textLayoutResult.getOffsetForPosition(position)) val currentValue = editProcessor.toTextFieldValue() val currentText = textLayoutResult.value.layoutInput.text.toString() + val previousOffset = currentValue.selection.start val cursorDesiredOffset = determineCursorDesiredOffset( offset, - currentValue, + previousOffset, textLayoutResult, currentText ) - if (cursorDesiredOffset == offset) { - showContextMenu(textLayoutResult.value.getCursorRect(offset)) - } + showContextMenu(cursorDesiredOffset == offset && cursorDesiredOffset == previousOffset) onValueChange( editProcessor.toTextFieldValue().copy(selection = TextRange(cursorDesiredOffset)) ) @@ -73,22 +71,21 @@ internal fun TextFieldDelegate.Companion.cupertinoSetCursorOffsetFocused( * - If there’s a punctuation mark before the word, the caret is between the punctuation mark and the word. * - When you make a single tap on the first half of the word, the caret is placed before this word. * - If you tap on the left edge of the TextField, the caret is placed before the first word on this line. The same is for the right edge. - * - If you tap at the caret, that is placed in the middle of the word, it will jump to the end of the word. + * - If you tap at the caret placed in the middle of the word, it will jump to the end of the word. * @param offset The current offset position. - * @param currentValue The current TextFieldValue. + * @param previousOffset The previous offset position (where caret was before incoming tap). * @param textLayoutResult The TextLayoutResultProxy representing the layout of the text. * @param currentText The current text in the TextField. * @return The desired cursor position after evaluating the given parameters. */ internal fun determineCursorDesiredOffset( offset: Int, - currentValue: TextFieldValue, + previousOffset: Int, textLayoutResult: TextLayoutResultProxy, currentText: String ): Int { - val previousCaretPosition = currentValue.selection.start val caretOffsetPosition = when { - offset == previousCaretPosition -> offset + offset == previousOffset -> offset textLayoutResult.isLeftEdgeTapped(offset) -> { val lineNumber = textLayoutResult.value.getLineForOffset(offset) textLayoutResult.value.getLineStart(lineNumber) diff --git a/compose/foundation/foundation/src/skikoTest/kotlin/androidx/compose/foundation/text/CupertinoTextFieldDelegateTest.kt b/compose/foundation/foundation/src/skikoTest/kotlin/androidx/compose/foundation/text/CupertinoTextFieldDelegateTest.kt index 3aa084b4c6703..dc8db12b48823 100644 --- a/compose/foundation/foundation/src/skikoTest/kotlin/androidx/compose/foundation/text/CupertinoTextFieldDelegateTest.kt +++ b/compose/foundation/foundation/src/skikoTest/kotlin/androidx/compose/foundation/text/CupertinoTextFieldDelegateTest.kt @@ -51,7 +51,7 @@ class CupertinoTextFieldDelegateTest { ) { val actual = determineCursorDesiredOffset( offset = givenOffset, - createSimpleTextFieldValue(text = sampleText, cursorOffset = cursorOffset), + createSimpleTextFieldValue(text = sampleText, cursorOffset = cursorOffset).selection.start, textLayoutResult = createSimpleTextLayoutResultProxy(sampleText), currentText = sampleText )