Lukáš Kúšik
02/17/2025, 2:37 PMOutputTransformation
in a TextField
to mask a weight input in stones and pounds.
After the user inputs the "stone" part, I add a "st" suffix (e.g. 12 st
and finally 12 st 5 lb
)
I would like the cursor to move past the unit like this -> 12 st |
, instead of it staying before the unit -> 12| st
Using placeCursorAtEnd()
does not seem to work in OutputTransformation
. But at the same time, the TextFields lets me manually tap at the end of the text to place the cursor there. Does anyone have any solution to this?Dovydas
02/17/2025, 2:53 PMInputTransformation
, so you'll have to also create a seperate InputTransformation
just for that. For reference, this is what I do to add an email suffix:
class EmailSuffixInputTransformation(private val suffix: String): InputTransformation {
override fun TextFieldBuffer.transformInput() {
// Do not allow selecting the suffix
if (originalText.contains(suffix) && (selection.start > originalText.indexOf(suffix))) {
placeCursorBeforeCharAt(originalText.indexOf(suffix))
}
}
}
class EmailSuffixOutputTransformation(private val suffix: String): OutputTransformation {
override fun TextFieldBuffer.transformOutput() {
val firstCharOfSuffix = suffix[0]
when {
// Add the suffix if not present and there is text entered
originalText.isNotBlank() && !originalText.contains(firstCharOfSuffix) -> {
append(suffix)
}
// Remove the suffix if user start entering their own email suffix
originalText.count { it == firstCharOfSuffix } > 1 -> {
delete(originalText.lastIndexOf(firstCharOfSuffix), originalText.length)
}
// Remove the suffix if user removes their entered text
originalText.isNotBlank() && originalText[0] == '@' -> {
delete(0, originalText.length)
}
}
}
}
The OutputTransformation
is reponsible for the actual transformation, while the InputTransformation
only places the cursor when necessary.Lukáš Kúšik
02/17/2025, 3:19 PMInputTransformation
, as there are no characters in the buffer to move past. E.g. in 12 st
the input buffer is just 12
Halil Ozercan
02/17/2025, 5:26 PMst
or lb
, it is considered a wedge. Right now TextField itself manages how the cursor position in TextFieldState translates to the transformed text. This of course includes disambiguation around the wedges.
For example your TextFieldState might have 12
as its content. It will also have a selection value, probably TextRange(2)
. But OutputTransformation
changes it to 12 st
before rendering. Now TextField has to figure out how to convert TextRange(2)
to transformed space. It could fall anywhere between 2 and 5.
This is where heuristics come into play. Right now TextField algorithm is favouring keeping the cursor close to its original place, rather than carrying it to the end of the wedge. A user tap can achieve this but there is no API to control it programmatically.
Ideally we want to provide such an API. We have been mostly gathering feedback since the initial release of the new TextField. This particular feedback has been popular so it will be prioritized.Lukáš Kúšik
02/17/2025, 6:07 PM