Android 文本注释 java.lang.ClassCastException: java.lang.String 无法转换为 android.text.SpannedString

Android Text Annotations java.lang.ClassCastException: java.lang.String cannot be cast to android.text.SpannedString

我制作了一个自定义 material 文本视图 class,它使用注释来设置给定文本的样式。但我最终遇到了这个错误 java.lang.ClassCastException: java.lang.String cannot be cast to android.text.SpannedString 导致我的 android 应用崩溃。

我从 Firebase Firestore 获取文本,并且我已将下面的 class 直接实施到我的布局中。我从我的 viewholder 调用 .setText 并且只在那里使用 .setText("Text from Firebase")

import android.graphics.Color
import android.text.Annotation
import android.text.SpannableString
import android.text.Spanned
import android.text.SpannedString
import android.text.style.*
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.google.android.material.textview.MaterialTextView


class SpannedAnnotationMaterialTextView : MaterialTextView {

    private var mListener: OnItemClickListener? = null

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    override fun setText(text: CharSequence, type: BufferType) {

        super.setText(processingText(text), type)
    }

    /**
     * Beispieltext Deutsch
     * nach Anamnese, Schmerzzustand und Untersuchungsbefunden\n \n Hochrisiko-Anamnese:\n <annotation format="bulletspan">bekanntes Marfan-Syndrom oder andere Bindegewebserkrankung</annotation>\n <annotation format="bulletspan">positive Familienanamnese für Aortenerkrankungen</annotation>\n <annotation format="bulletspan">bekannte Aortenklappenerkrankung</annotation>\n <annotation format="bulletspan">bekanntes thorakales Aortenaneurysma</annotation>\n <annotation format="bulletspan">vorausgegangene(r) Manipulation Aorta <per> Herzkatheter <per> herzchirurg. Eingriff</annotation>\n \n Hochrisiko-Schmerzsymptomatik:\n <annotation format="bulletspan">Schmerzen im Brust- <per> Rücken <per> Bauchbereich (und<per>oder)</annotation>\n <annotation format="bulletspan">abrupter Beginn</annotation>\n <annotation format="bulletspan">hohe Schmerzintensität</annotation>\n <annotation format="bulletspan">reißender Schmerzcharakter</annotation>\n \n Hochrisiko-Untersuchungsbefund:\n <annotation format="bulletspan">Pulsdefizit <per> Pulsdifferenz (evtl. Blutdruckdifferenz > 20mmHg (Arme), evtl. einseitig fehlender Radialispuls oder fehlende Pulse Leiste und Beine peripher Blutdruckdifferenz (syst. Messwert, höherer Wert zählt als realer syst. Blutdruck)</annotation>\n <annotation format="bulletspan">neurologische Symptomatik in Zusammenhang mit Schmerzauftreten</annotation>\n <annotation format="bulletspan">diastolisches Geräusch bei Auskultation über Erb'schem Punkt (neu und in Zusammenhang mit dem Schmerz)</annotation>\n <annotation bulletspan>Hypotension <per> Schocksymptomatik</annotation>\n
     *
     * Exampletext English
     * according to anamnesis, pain condition and examination results \ n \ n high-risk anamnesis: \ n <annotation format = "bulletspan"> known Marfan syndrome or other connective tissue disease </annotation> \ n <annotation format = "bulletspan"> positive family history for aortic diseases < / annotation> \ n <annotation format = "bulletspan"> known aortic valve disease </annotation> \ n <annotation format = "bulletspan"> known thoracic aortic aneurysm </annotation> \ n <annotation format = "bulletspan"> previous Manipulation aorta <per> cardiac catheter <per> cardiac surgeon. Intervention </annotation> \ n \ n High-risk pain symptoms: \ n <annotation format = "bulletspan"> Pain in the chest <per> back <per> abdominal area (and <per> or) </annotation> \ n <annotation format = "bulletspan"> abrupt beginning </annotation> \ n <annotation format = "bulletspan"> high pain intensity </annotation> \ n <annotation format = "bulletspan"> tearing pain character </annotation> \ n \ n high risk Examination results: \ n <annotation format = "bulletspan"> Pulse deficit <per> Pulse difference (possibly blood pressure difference> 20mmHg (arms), possibly one-sided missing radial pulse or missing pulses Groin and legs peripheral blood pressure difference (system measured value, higher value counts as real syst. blood pressure) </annotation> \ n <annotation format = "bulletspan"> neurological symptoms in connection with the occurrence of pain </annotation> \ n <annotation format = "bulletspan"> diastolic noise during auscultation over Erb's point (new and in connection with the pain) </annotation> \ n <annotation bulletspan> Hypotensi on <per> Shock symptoms </annotation> \ n
     */

    private fun processingText(text: CharSequence): CharSequence {

        Log.e(TAG, "processing Text")

        // get the text as spannableString so we can get the spans attached to the text
        val fullText = text as SpannedString
        val spannableString = SpannableString(fullText)

        // get all the annotation spans from the text
        // make sure you import android.text.Annotation
        val annotations = fullText.getSpans(0, fullText.length, Annotation::class.java)


        Log.e(TAG, "annotations found, size = ${annotations.size}")

        // iterate through all the annotation spans
        for (annotation in annotations) {

            // look for the span with the key font
            when (annotation.key) {
                "link" -> {
                    spannableString.apply {
                        // set the span the same indices as the annotation
                        setSpan(
                            object : ClickableSpan() {
                                override fun onClick(widget: View) {
                                    mListener!!.onSpanClick(annotation.value)
                                }
                            },
                            fullText.getSpanStart(annotation),
                            fullText.getSpanEnd(annotation),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                        )
                    }
                }
                "format" -> {
                    when (annotation.value) {
                        "bulletspan" -> {
                            spannableString.apply {
                                setSpan(
                                    BulletSpan(),
                                    fullText.getSpanStart(annotation),
                                    fullText.getSpanEnd(annotation),
                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                                )
                            }
                        }
                        "bold" -> {
                            spannableString.apply {
                                setSpan(
                                    BulletSpan(12),
                                    fullText.getSpanStart(annotation),
                                    fullText.getSpanEnd(annotation),
                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                                )
                            }
                        }
                        "underline" -> {
                            // first underline then resize with x1.15

                            spannableString.apply {
                                setSpan(
                                    UnderlineSpan(),
                                    fullText.getSpanStart(annotation),
                                    fullText.getSpanEnd(annotation),
                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                                )
                                setSpan(
                                        RelativeSizeSpan(1.15f),
                                fullText.getSpanStart(annotation),
                                fullText.getSpanEnd(annotation),
                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                                )
                            }
                        }
                    }
                }
                "color" -> {
                    spannableString.apply {
                        setSpan(
                            ForegroundColorSpan(Color.parseColor(annotation.value)),
                            fullText.getSpanStart(annotation),
                            fullText.getSpanEnd(annotation),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                        )
                    }
                }
            }
        }
        return spannableString
    }

    /**
     * Method to bind the OnItemClickListener.
     *
     * @param listener see down below
     */
    fun setOnItemClickListener(listener: OnItemClickListener?) {
        mListener = listener
    }

    interface OnItemClickListener {
        fun onSpanClick(spanText: String?)
    }

    companion object {
        const val TAG = "SpannedAnnotationMaterialTextView"
    }
}

当我从 val fullText = text as SpannedString 更改为 val fullText = SpannedString(text) 时,它不会崩溃,但从未找到任何注释。

您的错误字面上告诉您,编译器无法自动将 String 转换为 SpannedString。 您应该通过调用 SpannedString 构造函数来完成。 所以你有点回答了你自己的问题:)