admin管理员组文章数量:1296914
I'm using InputTransformation
in Jetpack Compose to filter user input in a BasicTextField
. The transformation works correctly, but the cursor remains in the same position after entering text instead of moving backward.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activitypose.setContent
import androidx.activity.enableEdgeToEdge
import androidxpose.foundation.interaction.MutableInteractionSource
import androidxpose.foundation.layout.Column
import androidxpose.foundation.layout.fillMaxSize
import androidxpose.foundation.layout.fillMaxWidth
import androidxpose.foundation.layout.height
import androidxpose.foundation.layout.padding
import androidxpose.foundation.text.BasicTextField
import androidxpose.foundation.text.KeyboardOptions
import androidxpose.foundation.text.input.InputTransformation
import androidxpose.foundation.text.input.TextFieldBuffer
import androidxpose.foundation.text.input.TextFieldLineLimits
import androidxpose.foundation.text.input.TextFieldState
import androidxpose.foundation.text.input.maxLength
import androidxpose.foundation.text.input.rememberTextFieldState
import androidxpose.foundation.text.input.then
import androidxpose.material3.ExperimentalMaterial3Api
import androidxpose.material3.Text
import androidxpose.material3.TextFieldDefaults
import androidxpose.runtime.Composable
import androidxpose.runtime.remember
import androidxpose.ui.Modifier
import androidxpose.ui.text.input.KeyboardType
import androidxpose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val stateOne = rememberTextFieldState(initialText = "Hellow")
val stateTwo = rememberTextFieldState()
BasicTextFieldExamples(
stateTwo,
remember { MutableInteractionSource() },
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BasicTextFieldExamples(
stateOTwo: TextFieldState,
secondInteractionSource: MutableInteractionSource,
) {
Column(
Modifier
.fillMaxSize()
.padding(50.dp)
) {
BasicTextField(
state = stateOTwo,
modifier = Modifier
.padding(top = 100.dp)
.fillMaxWidth()
.height(56.dp),
inputTransformation = InputTransformation.maxLength(6)
.then(LetterOnlyTransformation()),
interactionSource = secondInteractionSource,
decorator = TextFieldDefaults.decorator(
state = stateOTwo,
enabled = true,
label = {
Text("Last Name")
},
placeholder = {
Text("Example 2")
},
lineLimits = TextFieldLineLimits.Default,
interactionSource = secondInteractionSource,
outputTransformation = null
)
)
}
}
}
class LetterOnlyTransformation : InputTransformation {
override val keyboardOptions: KeyboardOptions?
get() = KeyboardOptions(keyboardType = KeyboardType.Text)
override fun TextFieldBuffer.transformInput() {
val filteredValue = asCharSequence().filter { it.isLetter() }
if (filteredValue != asCharSequence()) {
replace(0, length, filteredValue)
}
}
}
Question:
How can I ensure that the cursor moves correctly after filtering input in InputTransformation
? Is there a better way to handle this scenario in Jetpack Compose?
Any help is appreciated!
See the problem in here
I'm using InputTransformation
in Jetpack Compose to filter user input in a BasicTextField
. The transformation works correctly, but the cursor remains in the same position after entering text instead of moving backward.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activitypose.setContent
import androidx.activity.enableEdgeToEdge
import androidxpose.foundation.interaction.MutableInteractionSource
import androidxpose.foundation.layout.Column
import androidxpose.foundation.layout.fillMaxSize
import androidxpose.foundation.layout.fillMaxWidth
import androidxpose.foundation.layout.height
import androidxpose.foundation.layout.padding
import androidxpose.foundation.text.BasicTextField
import androidxpose.foundation.text.KeyboardOptions
import androidxpose.foundation.text.input.InputTransformation
import androidxpose.foundation.text.input.TextFieldBuffer
import androidxpose.foundation.text.input.TextFieldLineLimits
import androidxpose.foundation.text.input.TextFieldState
import androidxpose.foundation.text.input.maxLength
import androidxpose.foundation.text.input.rememberTextFieldState
import androidxpose.foundation.text.input.then
import androidxpose.material3.ExperimentalMaterial3Api
import androidxpose.material3.Text
import androidxpose.material3.TextFieldDefaults
import androidxpose.runtime.Composable
import androidxpose.runtime.remember
import androidxpose.ui.Modifier
import androidxpose.ui.text.input.KeyboardType
import androidxpose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val stateOne = rememberTextFieldState(initialText = "Hellow")
val stateTwo = rememberTextFieldState()
BasicTextFieldExamples(
stateTwo,
remember { MutableInteractionSource() },
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BasicTextFieldExamples(
stateOTwo: TextFieldState,
secondInteractionSource: MutableInteractionSource,
) {
Column(
Modifier
.fillMaxSize()
.padding(50.dp)
) {
BasicTextField(
state = stateOTwo,
modifier = Modifier
.padding(top = 100.dp)
.fillMaxWidth()
.height(56.dp),
inputTransformation = InputTransformation.maxLength(6)
.then(LetterOnlyTransformation()),
interactionSource = secondInteractionSource,
decorator = TextFieldDefaults.decorator(
state = stateOTwo,
enabled = true,
label = {
Text("Last Name")
},
placeholder = {
Text("Example 2")
},
lineLimits = TextFieldLineLimits.Default,
interactionSource = secondInteractionSource,
outputTransformation = null
)
)
}
}
}
class LetterOnlyTransformation : InputTransformation {
override val keyboardOptions: KeyboardOptions?
get() = KeyboardOptions(keyboardType = KeyboardType.Text)
override fun TextFieldBuffer.transformInput() {
val filteredValue = asCharSequence().filter { it.isLetter() }
if (filteredValue != asCharSequence()) {
replace(0, length, filteredValue)
}
}
}
Question:
How can I ensure that the cursor moves correctly after filtering input in InputTransformation
? Is there a better way to handle this scenario in Jetpack Compose?
Any help is appreciated!
See the problem in here
Share Improve this question edited Feb 11 at 17:55 Vivek Modi asked Feb 11 at 17:39 Vivek ModiVivek Modi 7,30120 gold badges101 silver badges229 bronze badges1 Answer
Reset to default 0This issue occurs because TextFieldBuffer.transformInput()
is called even during selection or cursor position changes, and the condition if (filteredValue != asCharSequence())
always returns true
(this comparison would work as expected if they were String
objects where the equals
method is overridden).
As a result, replace(0, length, filteredValue)
is called every time you move the cursor, and this method reverts cursor position changes.
You can use revertAllChanges()
instead – it handles this under the hood.
Additionally, you can track the changes.changeCount
value to return from transformInput()
when changeCount
is 0 (which occurs when the input text itself is not changing – e.g., during cursor position changes).
Here's how the transformInput()
method may look:
@OptIn(ExperimentalFoundationApi::class)
override fun TextFieldBuffer.transformInput() {
if (changes.changeCount == 0) return
val currentInput = asCharSequence().toString()
val filteredValue = currentInput.filter { it.isLetter() }
if (filteredValue != currentInput) {
revertAllChanges()
}
}
本文标签: androidCursor doesn39t move after filtering text Jetpack ComposeStack Overflow
版权声明:本文标题:android - Cursor doesn't move after filtering text Jetpack Compose - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741643953a2390077.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论