最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - Prevent BasicTextField from being focused on longpress - Stack Overflow

programmeradmin0浏览0评论

How can I prevent a Jetpack Compose BasicTextField to get focused on long press? I want it to get focused on a normal tap. But not by a long press or a swipe gesture, for example. I am using the newest version of BasicTextField.

                    BasicTextField(
                        value = TextFieldValue(
                            text = "TEST TEST",
                            selection = TextRange("TEST TEST".length)
                        ),
                        onValueChange = { newText ->  },
                        singleLine = true,
                        textStyle = MaterialTheme.typography.body1
                    )

To give some context on why I need this: The BasicTextField is part of a lazylist item. Each item can be reordered by longpressing it. Each item can also be deleted by a swipe to dismiss gesture. So I don't want these user inputs to trigger the edit mode of the text field.

I already tried all the answers from ChatGPT, Claude and so on. Trying to ignore the longpress with emtpy pointerInput modifiers does not work. I also played around with pointerInteropFilter and focusRequester, but to no avail.

How can I prevent a Jetpack Compose BasicTextField to get focused on long press? I want it to get focused on a normal tap. But not by a long press or a swipe gesture, for example. I am using the newest version of BasicTextField.

                    BasicTextField(
                        value = TextFieldValue(
                            text = "TEST TEST",
                            selection = TextRange("TEST TEST".length)
                        ),
                        onValueChange = { newText ->  },
                        singleLine = true,
                        textStyle = MaterialTheme.typography.body1
                    )

To give some context on why I need this: The BasicTextField is part of a lazylist item. Each item can be reordered by longpressing it. Each item can also be deleted by a swipe to dismiss gesture. So I don't want these user inputs to trigger the edit mode of the text field.

I already tried all the answers from ChatGPT, Claude and so on. Trying to ignore the longpress with emtpy pointerInput modifiers does not work. I also played around with pointerInteropFilter and focusRequester, but to no avail.

Share Improve this question edited Jan 22 at 8:09 muetzenflo asked Jan 19 at 10:34 muetzenflomuetzenflo 5,6824 gold badges44 silver badges87 bronze badges 2
  • Have you tried this solution? stackoverflow.com/a/69551654/11512499 – Adnan Habib Commented Jan 28 at 1:11
  • Although you claim to use the newest version of BasicTextField you are still using the old one with a TextFieldValue instead of a TextFieldState. Have you tried out the new version? Does it behave the same? Regardless, it would help if you added a little bit more context, like the LazyList and how your handle the item's longpress and swipe gestures so we can reproduce the issue. – tyg Commented Jan 28 at 1:40
Add a comment  | 

2 Answers 2

Reset to default 0

i think there is no direct way to do it so this might be helpful if it fits your usecase.

@Composable
fun DraggableTextField(
    initialText: String = "Custom text",
    longPressDurationMs: Long = 300,
) {
    var textFieldValue by remember { mutableStateOf(TextFieldValue(initialText)) }
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed by interactionSource.collectIsPressedAsState()
    var canFocus by remember { mutableStateOf(true) }
    var pressStartTime by remember { mutableStateOf<Long?>(null) }
    var position by remember { mutableStateOf(Offset.Zero) }

   // Handle press duration logic
   LaunchedEffect(isPressed) {
        if (isPressed) {
            pressStartTime = System.currentTimeMillis()
        } else {
            pressStartTime?.let { startTime ->
                val duration = System.currentTimeMillis() - startTime
                if (duration > longPressDurationMs) {
                    canFocus = false
                } else {
                    canFocus = true
                }
            }
            pressStartTime = null
        }
    }

    // making text selection appears transparent 
    val customTextSelectionColors = remember {
        TextSelectionColors(
            handleColor = Color.Transparent,
            backgroundColor = Color.Transparent
        )
    }

    CompositionLocalProvider(
        LocalTextSelectionColors provides customTextSelectionColors,
        LocalTextToolbar provides EmptyTextToolbar
    ) {
        BasicTextField(
            value = textFieldValue,
            onValueChange = { textFieldValue = it },
            interactionSource = interactionSource,
            modifier = Modifier
                .graphicsLayer(
                    translationX = position.x,
                    translationY = position.y
                )
                .fillMaxWidth()
                .background(Color.Cyan)
                .padding(vertical = 5.dp)
                .focusProperties { this.canFocus = canFocus },
                //decoration box needs to be used in order to be able to detect drag gesture
                decorationBox = { innerTextField ->
                Row(
                    Modifier
                        .pointerInput(Unit) {
                            detectDragGestures { change, dragAmount ->
                                change.consume()
                                position += dragAmount
                        }
                        }
                        .border(1.dp, Color.Gray, shape = RectangleShape)
                        .padding(16.dp)
                        .fillMaxWidth().
                ) {
                    innerTextField()
                }
            }
        )
    }
}

//to remove copy/paste toolbar that appears on long press
object EmptyTextToolbar: TextToolbar {
   override val status: TextToolbarStatus = TextToolbarStatus.Hidden

   override fun hide() {  }

   override fun showMenu(
       rect: Rect,
       onCopyRequested: (() -> Unit)?,
       onPasteRequested: (() -> Unit)?,
       onCutRequested: (() -> Unit)?,
      onSelectAllRequested: (() -> Unit)?,
   ) {
   }
}

Since your BasicTextField is inside a LazyList item that supports drag reordering and swipe to dismiss, it is preventing the textfield from getting focus due to long press, but still allow normal taps to focus

发布评论

评论列表(0)

  1. 暂无评论