撰写视觉转换

问题描述 投票:0回答:1

我有一个将文本转换为电话掩码的类,PHONE_MASK 是

const val PHONE_MASK = "+7 (7__) ___-__-__"
当我在文本字段中输入第一个字符时,我的文本光标位置不正确(光标没有移动到文本末尾) 我认为问题出在这里
override fun originalToTransformed(offset: Int): Int
因为当我输入第一个字符时,偏移量仍然为零值

import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import kotlin.math.absoluteValue

class PhoneMaskVisualTransformation(val mask: String, val maskedSymbol: Char = MASKED_SYMBOL) :
    VisualTransformation {
    companion object {
        const val MASKED_SYMBOL = '_'
    }

    private val specialSymbolsIndices = mask.indices.filter { mask[it] != maskedSymbol }

    override fun filter(text: AnnotatedString): TransformedText {
        var out = ""
        var maskIndex = 0
        text.forEach { char ->
            while (specialSymbolsIndices.contains(maskIndex)) {
                out += mask[maskIndex]
                maskIndex++
            }
            out += char
            maskIndex++
        }
        return TransformedText(AnnotatedString(out), offsetTranslator())
    }

    private fun offsetTranslator() = object : OffsetMapping {
        override fun originalToTransformed(offset: Int): Int {
            val offsetValue = offset.absoluteValue
            if (offsetValue == 0) return 0
            var numberOfHashtags = 0
            val masked = mask.takeWhile {
                if (it == maskedSymbol) numberOfHashtags++
                numberOfHashtags < offsetValue
            }
            return masked.length + 1
        }

        override fun transformedToOriginal(offset: Int): Int {
            return mask.take(offset.absoluteValue).count { it == maskedSymbol }
        }
    }
} 
android android-jetpack-compose
1个回答
0
投票

我建议您查看 decoro 库,这是一个用于自定义手机面罩的简单实用的解决方案。

开箱即有口罩:

PredefinedSlots.SINGLE_SLOT                   // Any character
PredefinedSlots.RUS_PHONE_NUMBER              // Russian phone number formatted as +7 (___) ___-__-__ (digits only)
PredefinedSlots.RUS_PASSPORT                  // Series and number of russian passport formatted as ____ ______  (digits only)
PredefinedSlots.CARD_NUMBER_STANDARD          // Credit card number formatted as ____ ____ ____ ____ (digits only)
PredefinedSlots.CARD_NUMBER_STANDARD_MASKABLE // Credit card number formatted as ____ ____ ____ ____ (digits and chars 'X', 'x', '*')
PredefinedSlots.CARD_NUMBER_MAESTRO           // Credit card number formatted as ________ ____ (digits only)
PredefinedSlots.CARD_NUMBER_MAESTRO_MASKABLE  // Credit card number formatted as ________ ____ (digits and chars 'X', 'x', '*')

创建自己的能力也是如此:

Slot[] slots = new UnderscoreDigitSlotsParser().parseSlots("___ ___ ___");
FormatWatcher formatWatcher = new MaskFormatWatcher(MaskImpl.createTerminated(slots));
formatWatcher.installOn(editText); // install on any TextView
© www.soinside.com 2019 - 2024. All rights reserved.