如何使用文本跨度将android textview中的一个单词移动到下一个单词上方?
我正试图在android文本视图中将一个单词移到下一个单词的上方,如附件中的图像()。我用spannablestringbuilder成功地将单词向上移动(如上标),但我找不到一种方法将文本的右侧部分向左移动以填补空白。有人知道怎么做吗 这是我到目前为止编写的函数:如何使用文本跨度将android textview中的一个单词移动到下一个单词上方?,android,kotlin,textview,spannablestringbuilder,Android,Kotlin,Textview,Spannablestringbuilder,我正试图在android文本视图中将一个单词移到下一个单词的上方,如附件中的图像()。我用spannablestringbuilder成功地将单词向上移动(如上标),但我找不到一种方法将文本的右侧部分向左移动以填补空白。有人知道怎么做吗 这是我到目前为止编写的函数: /** * Adds clickable spans for words that are contained between "[" and "]" * * @param imString The string on whi
/**
* Adds clickable spans for words that are contained between "[" and "]"
*
* @param imString The string on which to apply clickable spans
*/
private fun addClickablePart(imString: String): SpannableStringBuilder
{
var string = imString
val spannableStringBuilder = SpannableStringBuilder((string.replace("[", "")).replace("]", ""))
var startIndex = string.indexOf("[")
while (startIndex != -1)
{
string = string.replaceFirst("[", "")
val endIndex = string.indexOf("]", startIndex)
string = string.replaceFirst("]", "")
val clickString = string.substring(startIndex, endIndex)
spannableStringBuilder.setSpan(
object: ClickableSpan()
{
override fun onClick(view: View)
{
HelperFunction.showToast(this@SongActivity, clickString)
}
override fun updateDrawState(text: TextPaint)
{
super.updateDrawState(text)
text.isUnderlineText = false
text.color = ContextCompat.getColor(this@SongActivity, R.color.colorAccent)
text.textSize = HelperFunction.spToPx(this@SongActivity, 12).toFloat()
text.baselineShift += (text.ascent()).toInt() // move chord upwards
text.typeface = Typeface.create(ResourcesCompat.getFont(this@SongActivity, R.font.roboto_mono), Typeface.BOLD) // set text to bold
}
},
startIndex, endIndex, 0)
startIndex = string.indexOf("[", endIndex)
}
return spannableStringBuilder
}
您可以在TextView中使用HTML来实现这一点,例如,上标符号的HTML/CSS代码是:
<!DOCTYPE html>
<html>
<head>
<style>
sup {
vertical-align: super;
font-size: medium;
color: red;
position: relative; left: -2.5em; top: -0.5em;
}
</style>
</head>
<body>
<p>word <sup>topword</sup></p>
</body>
</html>
您可以在TextView中使用HTML来实现这一点,例如,上标符号的HTML/CSS代码是:
<!DOCTYPE html>
<html>
<head>
<style>
sup {
vertical-align: super;
font-size: medium;
color: red;
position: relative; left: -2.5em; top: -0.5em;
}
</style>
</head>
<body>
<p>word <sup>topword</sup></p>
</body>
</html>
我已经使用ReplacementSpan解决了这个问题。我把代码贴在下面 这是custom ReplacementSpan类,它在画布上的所需位置绘制单词:
inner class ChordSpan: ReplacementSpan()
{
override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: FontMetricsInt?): Int
{
val mText = text!!.subSequence(start, end).toString().replace("[", "")
var chordString = ""
var regularString = mText
if (mText.contains("]"))
{
chordString = mText.substringBefore("]")
regularString = mText.substringAfter("]")
}
val chordStringTextPaint = getChordStringTextPaint(paint)
val regularStringTextPaint = getRegularStringTextPaint(paint)
return max(chordStringTextPaint.measureText(chordString), regularStringTextPaint.measureText(regularString)).toInt()
}
private fun getChordStringTextPaint(paint: Paint): TextPaint
{
val textPaint = TextPaint(paint)
textPaint.textSize = textPaint.textSize / 1.5F
textPaint.typeface = Typeface.DEFAULT_BOLD
textPaint.color = ContextCompat.getColor(this@SongActivity, R.color.colorAccent)
return textPaint
}
private fun getRegularStringTextPaint(paint: Paint): TextPaint
{
return TextPaint(paint)
}
override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint)
{
val mText = text!!.subSequence(start, end).toString().replace("[", "")
var chordString = ""
var regularString = mText
if (mText.contains("]"))
{
chordString = mText.substringBefore("]")
regularString = mText.substringAfter("]")
}
val chordStringTextPaint = getChordStringTextPaint(paint)
val regularStringTextPaint = getRegularStringTextPaint(paint)
canvas.drawText(chordString, x, y.toFloat(), chordStringTextPaint)
canvas.drawText(regularString, x, y.toFloat() + (bottom - top) / 2.5F, regularStringTextPaint)
}
}
这是在孔文字上应用跨距的函数:
private fun formatDisplayOfLyricsWithChords(string: String): SpannableString
{
val mString = "$string\n\n"
val endOfStringIndex = mString.length
val spannableString = SpannableString(mString)
var startIndex = 0
while (startIndex != -1 && startIndex != endOfStringIndex)
{
var possibleEndIndex = mString.indexOf("[", startIndex + 1)
if (possibleEndIndex == -1)
{
possibleEndIndex = endOfStringIndex + 1
}
var endOfRowIndex = mString.indexOf("\n", startIndex + 1)
if (endOfRowIndex == -1)
{
endOfRowIndex = endOfStringIndex + 1
}
val endIndex = minOf(possibleEndIndex, endOfRowIndex, endOfStringIndex)
spannableString.setSpan(ChordSpan(), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
if (mString[startIndex] == '[')
{
val startIndexClick = startIndex
val endIndexClick = mString.indexOf("]", startIndex + 1)
val chord = mString.substring(startIndexClick + 1, endIndexClick)
spannableString.setSpan(
object: ClickableSpan()
{
override fun onClick(view: View)
{
handleClickOnChord(chord)
}
},
startIndexClick, endIndexClick, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
startIndex = endIndex
if (startIndex == endOfRowIndex)
{
startIndex++
}
}
return spannableString
}
我从一个类似的问题中得到了灵感:我已经设法用ReplacementSpan解决了这个问题。我把代码贴在下面 这是custom ReplacementSpan类,它在画布上的所需位置绘制单词:
inner class ChordSpan: ReplacementSpan()
{
override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: FontMetricsInt?): Int
{
val mText = text!!.subSequence(start, end).toString().replace("[", "")
var chordString = ""
var regularString = mText
if (mText.contains("]"))
{
chordString = mText.substringBefore("]")
regularString = mText.substringAfter("]")
}
val chordStringTextPaint = getChordStringTextPaint(paint)
val regularStringTextPaint = getRegularStringTextPaint(paint)
return max(chordStringTextPaint.measureText(chordString), regularStringTextPaint.measureText(regularString)).toInt()
}
private fun getChordStringTextPaint(paint: Paint): TextPaint
{
val textPaint = TextPaint(paint)
textPaint.textSize = textPaint.textSize / 1.5F
textPaint.typeface = Typeface.DEFAULT_BOLD
textPaint.color = ContextCompat.getColor(this@SongActivity, R.color.colorAccent)
return textPaint
}
private fun getRegularStringTextPaint(paint: Paint): TextPaint
{
return TextPaint(paint)
}
override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint)
{
val mText = text!!.subSequence(start, end).toString().replace("[", "")
var chordString = ""
var regularString = mText
if (mText.contains("]"))
{
chordString = mText.substringBefore("]")
regularString = mText.substringAfter("]")
}
val chordStringTextPaint = getChordStringTextPaint(paint)
val regularStringTextPaint = getRegularStringTextPaint(paint)
canvas.drawText(chordString, x, y.toFloat(), chordStringTextPaint)
canvas.drawText(regularString, x, y.toFloat() + (bottom - top) / 2.5F, regularStringTextPaint)
}
}
这是在孔文字上应用跨距的函数:
private fun formatDisplayOfLyricsWithChords(string: String): SpannableString
{
val mString = "$string\n\n"
val endOfStringIndex = mString.length
val spannableString = SpannableString(mString)
var startIndex = 0
while (startIndex != -1 && startIndex != endOfStringIndex)
{
var possibleEndIndex = mString.indexOf("[", startIndex + 1)
if (possibleEndIndex == -1)
{
possibleEndIndex = endOfStringIndex + 1
}
var endOfRowIndex = mString.indexOf("\n", startIndex + 1)
if (endOfRowIndex == -1)
{
endOfRowIndex = endOfStringIndex + 1
}
val endIndex = minOf(possibleEndIndex, endOfRowIndex, endOfStringIndex)
spannableString.setSpan(ChordSpan(), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
if (mString[startIndex] == '[')
{
val startIndexClick = startIndex
val endIndexClick = mString.indexOf("]", startIndex + 1)
val chord = mString.substring(startIndexClick + 1, endIndexClick)
spannableString.setSpan(
object: ClickableSpan()
{
override fun onClick(view: View)
{
handleClickOnChord(chord)
}
},
startIndexClick, endIndexClick, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
startIndex = endIndex
if (startIndex == endOfRowIndex)
{
startIndex++
}
}
return spannableString
}
我从一个类似的问题的回答中得到了灵感:屏幕截图显示了您所做的事情或您的期望?您好,欢迎来到SO,请阅读并提供come代码。否则,您的问题可能会被否决而得不到回答。您可能应该在html中定义它,然后将textview内容设置为htmlHello@VirRajpurohit截图显示了我的期望。我提供了到目前为止我编写的处理字符串的函数,并更新了图像以使其更清晰。Hello@Frieder!我已经提供了我编写的用于处理字符串的函数。屏幕截图显示了您所做的或您所期望的?您好,欢迎使用SO,请阅读并提供come代码。否则,您的问题可能会被否决而得不到回答。您可能应该在html中定义它,然后将textview内容设置为htmlHello@VirRajpurohit截图显示了我的期望。我提供了到目前为止我编写的处理字符串的函数,并更新了图像以使其更清晰。Hello@Frieder!我提供了我编写的用于处理字符串的函数。