删除整个ImageSpan的一部分时,将其删除

时间:2018-10-23 06:39:42

标签: android android-edittext spannablestring imagespan

我正在尝试在我的应用中实现Emoji,我应该使用短代码(例如:dog::cat:),而不要使用unicode。我有两个要测试的设备以及其中的EditTextImageSpan的两种不同行为。

首先:魅族PRO 6,Android 6.0(API 23)

一切正常。在跨度文本上点击退格键时,它会从EditText中完全消失,因为已删除了字符串的全跨度部分。

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

第二个:Google Pixel XL,Android 9.0(API 28)

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

我尝试了什么

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

Android - Delete entire ImageSpan when part of it is deleted?

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而引发异常。

有什么办法解决这个问题?

1 个答案:

答案 0 :(得分:0)

我最终得到了这个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) {}
}

它似乎可以在我尝试过的所有设备上使用。