Удалить весь ImageSpan, когда его часть удалена

Я пытаюсь реализовать Emoji в моем приложении, и я должен использовать короткие коды (например, :dog:, :cat:), а не юникод. У меня есть два устройства для тестирования и два разных поведения EditText а также ImageSpan в этом.

Первое: Meizu PRO 6, Android 6.0 (API 23)

Все работает как я хочу. Когда вы нажимаете клавишу Backspace на растянутом тексте, он полностью исчезает из EditText, потому что полностью растянутая часть строки была удалена.

Например, у вас есть "Привет :dog:" в вашем EditText (:dog: заменяется изображением собаки), вы нажимаете клавишу Backspace, ваш EditText теперь содержит только "Hello ".

Второе: Google Pixel XL, Android 9.0 (API 28)

Когда вы нажимаете клавишу Backspace на растянутом тексте, вы просто удаляете : символ, заставляющий рисунок остаться в EditText, потому что он не удаляет всю натянутую часть вашей строки. Но я хочу удалить это.

Что я попробовал

Я нашел этот код в другом вопросе здесь:

Android - Удалить весь 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, но полностью тормозит Meizu, удаляя 2-3 картинки или даже не натянутый текст, иногда выдает исключение, потому что start - length < 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) {}
}

Похоже, это работает со всеми устройствами, которые я пробовал.

Другие вопросы по тегам