1

我正在尝试在我的应用程序中实现表情符号,我应该使用短代码(如:dog:, :cat:),而不是 unicode。EditText我有两个要测试的设备和两个不同的行为ImageSpan

第一:魅族PRO 6,Android 6.0(API 23)

一切都按我的意愿工作。当您在跨区文本上点击退格键时,它会完全从 EditText 中消失,因为字符串的完整跨区部分已被删除。

例如,您的(被替换为狗的图片)中有一个“Hello :dog:” ,您按退格键,您的 EditText 现在只包含“Hello”。EditText:dog:

第二:谷歌Pixel XL,Android 9.0(API 28)

当您在跨区文本上点击退格键时,您只需删除:符号,使图片留在 EditText 中,因为它不会删除字符串的所有跨区部分。但我想删除它。

我尝试了什么

我在这里的另一个问题中找到了这段代码:

Android - 删除部分 ImageSpan 时删除整个 ImageSpan?

private val watcher = object : TextWatcher {
    private var spanLength = -1

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
        if (start == 0) return
        if (count > after) {
            val spans =
                editableText.getSpans(start + count, start + count, ImageSpan::class.java)
            if (spans == null || spans.isEmpty()) return

            for (i in spans.indices) {
                val end = editableText.getSpanEnd(spans[i])
                if (end != start + count) continue
                val text = spans[i].source
                spanLength = text!!.length - 1
                editableText.removeSpan(spans[i])
            }
        }
    }

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, after: Int) {
        if (spanLength > -1) {
            val length = spanLength
            spanLength = -1
            editableText.replace(start - length, start, "")
        }
    }

    override fun afterTextChanged(s: Editable) {}
}

它适用于 Google Pixel XL,但完全阻止魅族删除 2-3 张图片甚至不跨越文本,有时它会抛出异常,因为start - length < 0.

有没有办法解决这个问题?

4

1 回答 1

1

我最终得到了这个 TextWatcher

private val watcher = object : TextWatcher {
    private var spanLength = -1
    private var spanStart = -1

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
        if (start == 0) return
        if (count > after) {
            val spans =
                editableText.getSpans(start + count, start + count, EmojiSpan::class.java)
            if (spans == null || spans.isEmpty()) return

            for (i in spans.indices) {
                val end = editableText.getSpanEnd(spans[i])
                if (end != start + count) continue
                val text = spans[i].getSource()
                spanLength = text.length - 1
                spanStart = editableText.getSpanStart(spans[i])
                editableText.removeSpan(spans[i])
            }
        }
    }

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        if (spanLength > -1 && spanStart != -1 && count < before) {
            val startSpan = spanStart
            val endSpan = spanStart + spanLength

            if (startSpan < 0 || endSpan > editableText.length) {
                return
            }

            spanLength = -1
            spanStart = -1
            editableText.replace(startSpan, endSpan, "")
        }
    }

    override fun afterTextChanged(s: Editable) {}
}

看起来它适用于我尝试过的所有设备。

于 2019-06-14T07:22:53.653 回答