Skip to content

Commit

Permalink
Fixed appearing of text editing menu in iOS textfields by every tap (#…
Browse files Browse the repository at this point in the history
…1293)

## Proposed Changes

- Changed logic of appearing the text editing menu in iOS textfields: it
won't be opened by every tap now.

## Testing

Test: Manual. Open test app, go Components -> Textfield -> Almost
FullScreen, tap once to focus, tap again on the same position to call
the menu

## Issues Fixed

Fixes: 
-
https://youtrack.jetbrains.com/issue/COMPOSE-1189/iOS-textfield-context-menu-opens-by-every-tap
-
https://youtrack.jetbrains.com/issue/COMPOSE-1028/iOS-TextField-adjust-calling-context-menu

## Google CLA
You need to sign the Google Contributor’s License Agreement at
https://cla.developers.google.com/.
This is needed since we synchronise most of the code with Google’s AOSP
repository. Signing this agreement allows us to synchronise code from
your Pull Requests as well.
  • Loading branch information
mazunin-v-jb committed Apr 22, 2024
1 parent fb83d69 commit 94c83bf
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
)
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down

0 comments on commit 94c83bf

Please sign in to comment.