【发布时间】:2021-07-17 15:08:59
【问题描述】:
我创建了一个自定义的 MaterialTextView 类,我想在其中通过android.text.annotations 格式化给定的文本。该类直接实现到我的 android 应用程序布局中,我通过从 firebase firestore 获取数据的 viewholder 分配文本。
在课堂上,我直接从数据库中给出了一个示例文本。
该代码不会产生任何错误,但它根本不会在给定文本中找到任何注释。我试图从各种来源实现代码,例如
https://gist.github.com/florina-muntenescu/08d751d843d55b75061039fee4e97931
https://medium.com/androiddevelopers/styling-internationalized-text-in-android-f99759fb7b8f
https://developer.android.com/guide/topics/resources/string-resource#StylingWithAnnotations
但我还没有找到解决问题的方法。
我唯一改变的是转换为 SpannedString,因为它会产生 CastException,请参见我的另一个问题Android Text Annotations java.lang.ClassCastException: java.lang.String cannot be cast to android.text.SpannedString
这是我的课
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 /* not working causes exception */
val fullText = SpannedString(text)
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"
}
}
【问题讨论】:
-
使用
<annotation>这样的标签仅适用于从资源加载的字符串。也就是说,这些标签只会在从资源加载字符串时自动转换为Annotation跨度。如果您只是设置任意外部文本,则不会像这些示例所示那样工作,因为它们专门涉及资源字符串。 -
那么通过外部导入有什么好的替代注释吗?
-
嗯,你已经拥有的一半——创建和设置各种
*Spans——适用于任何地方;你只需要弄清楚你想如何替换Annotation功能,它基本上只是为你解析了那些<annotation>标签。不幸的是,平台执行它的机制是不可公开访问的,但您可以自己处理。或者,如果您的设置可能更简单,可能会设计一些其他方式来标记跨度类型和位置,具体取决于您首先构建标记字符串的方式。
标签: android kotlin text annotations