删除整个ImageSpan的一部分时,将其删除 [英] Delete entire ImageSpan when the part of it is deleted

查看:240
本文介绍了删除整个ImageSpan的一部分时,将其删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement Emoji's in my app and I should use short codes (like :dog:, :cat:), not unicode. I have two devices to test on and two different behaviours of EditText and ImageSpan in it.

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

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

Everything works as I want. When you tap backspace on the spanned text, it disappears from EditText completely, because full spanned part of the string was removed.

例如,您在EditText中有一个"Hello :dog:"(:dog:替换为狗的图片),按Backspace键,您的EditText现在仅包含"Hello".

For example, you have a "Hello :dog:" in your EditText (:dog: is replaced with a picture of the dog), you press backspace, your EditText contains only "Hello " now.

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

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

When you tap backspace on the spanned text, you just remove the : symbol, making picture stay in EditText because it doesn't remove all spanned part of your string. But I want to remove it.

我尝试了什么

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

I found this code in the other question here:

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,但完全阻止了魅族删除2-3张图片或什至没有跨文本的内容,有时会由于start - length < 0而引发异常.

It works as intended for Google Pixel XL, but completely brakes Meizu removing 2-3 pictures or even not spanned text, sometimes it throws an Exception because start - length < 0.

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

Is there any way to solve this?

推荐答案

我最终得到了这个TextWatcher

I ended up with this 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) {}
}

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

Looks like it works with all devices I've tried.

这篇关于删除整个ImageSpan的一部分时,将其删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆