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
构造函数来完成。
所以你有点回答了你自己的问题:)
我制作了一个自定义 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
构造函数来完成。
所以你有点回答了你自己的问题:)