I'm using `OutputTransformation` in a `TextField` ...
# compose
l
I'm using
OutputTransformation
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?
d
placeCursor functions only work in
InputTransformation
, 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:
Copy code
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.
l
thanks for your reply, however I don't think you encountered my problem in your instance. I need to move the cursor past the suffix, which is not possible even from
InputTransformation
, as there are no characters in the buffer to move past. E.g. in
12 st
the input buffer is just
12
h
This is a current limitation of the OutputTransformation API. To explain it in technical terms let me define a wedge. It means a changed region by the OutputTransformation. When you add
st
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.
👍 1
l
thank you Halil for the lengthy reply, I'm glad it is being considered. Are there any known solutions in the meantime for this use case?