gpt4 book ai didi

java - 在具有跨度的 Android TextView 中一次换行两行

转载 作者:行者123 更新时间:2023-12-02 12:37:30 27 4
gpt4 key购买 nike

总结

我有一个字符串[tab][ch]C[/ch][ch]Am[/ch]\n我听说有一个 secret 和弦[/tab]

当 TextView 大到足以容纳它而无需包装时,它应该(并且确实)看起来像这样:

  C                  Am         
I heard there was a secret chord

当行太长而无法放入 TextView 时,我希望它像这样换行:

  C                
I heard there was a
Am
secret chord

现在它像这样换行(就像你期望的那样,如果它只是文本)

  C                
Am
I heard there was a
secret chord

约束:

  • 我使用等宽文本字体来保持对齐
  • 和弦(CFAmG)是可点击的,因此如果您自定义TextView 的实现,它仍然必须能够处理 ClickableSpans 或以其他方式保持它们可点击
  • Kotlin 或 Java(或 XML)都可以

如果有帮助的话,这是我的一个开源项目,所以源代码可以在 Github 上找到。这是 fragment source (寻找 fun processTabContent(text: CharSequence) -- 这就是我现在处理文本的地方。这是 layout xml


输入格式

我的数据存储在单个字符串中(无法更改——我是从 API 获取的)。以下是上述选项卡的格式:

[Intro]\n[tab][ch]C[/ch] [ch]Am[/ch] [ch]C[/ch] [ch]Am[/ch][/tab]\n[Verse 1][tab]      [ch]C[ch]                  [ch]Am[/ch]                         I heard there was a secret chord               [/tab][tab]      [ch]C[/ch]                     [ch]Am[/ch]\nThat David played, and it pleased the Lord[/tab][tab]   [ch]C[/ch]                [ch]F[/ch]               [ch]G[/ch]\n But you don't really care for music, do you?[/tab]

请注意,和弦(吉他手会演奏的音符,如 CF)包含在 [ch] 标签中。我目前有代码可以找到这些,删除 [ch] 标签,并将每个和弦包装在 ClickableSpan 中。单击时,我的应用程序会显示另一个 fragment ,其中包含如何在吉他上弹奏和弦的说明。这一点很重要,因为这个问题的答案必须允许这些和弦仍然像这样被点击。

我现在正在做的(那是行不通的)

您现在可能已经注意到,对于这个问题,我们必须关注的是 [tab] 标记。现在,我正在检查字符串并将 [tab] 替换为换行符并删除 [/tab] 的所有实例。如果我的 TextView 的文本大小足够小以至于整行都适合设备屏幕,则此方法工作正常。但是,当自动换行出现时,我开始遇到问题。

这个:

  C                  Am         
I heard there was a secret chord

应该换成这样:

  C                
I heard there was a
Am
secret chord

而是像这样换行:

  C                
Am
I heard there was a
secret chord

最佳答案

我认为这个解决方案可能会解决问题。但是有一些假设,

  1. 每句歌词都以[tab]开始,以[/tab]结束
  2. 和弦与歌词之间总是用\n分隔

而且我相信您需要在使用数据之前清理数据。由于可能很容易处理 Intro, Verse,因此我将只关注歌词 tab

这是单句歌词的示例数据

[tab] [ch]C[/ch] [ch]F[/ch] [ch]G[/ch] \n But you don't really care for music, do you?[/tab]

首先,我们需要删除一些不需要的 block 。

val inputStr = singleLyric
.replace("[tab]", "")
.replace("[/tab]", "")
.replace("[ch]", "")
.replace("[/ch]", "")

之后,我把和弦和歌词分开了

val indexOfLineBreak = inputStr.indexOf("\n")
val chords = inputStr.substring(0, indexOfLineBreak)
val lyrics = inputStr.substring(indexOfLineBreak + 1, inputStr.length).trim()

清理完数据后,我们就可以开始设置数据了。

text_view.text = lyrics
text_view.post {
val lineCount = text_view.lineCount
var currentLine = 0
var newStr = ""

if (lineCount <= 1) {// if it's not multi line, no need to manipulate data
newStr += chords + "\n" + lyrics
} else {

val chordsCount = chords.count()
while (currentLine < lineCount) {
//get start and end index of selected line
val lineStart = text_view.layout.getLineStart(currentLine)
val lineEnd = text_view.layout.getLineEnd(currentLine)

// add chord substring
if (lineEnd <= chordsCount) //chords string can be shorter than lyric
newStr += chords.substring(lineStart, lineEnd) + "\n"
else if (lineStart < chordsCount) //it can be no more chords data to show
newStr += chords.substring(lineStart, chordsCount) + "\n"

// add lyric substring
newStr += lyrics.substring(lineStart, lineEnd) + "\n"
currentLine++
}

}
text_view.text = newStr
}

想法很简单。将歌词数据设置到textview后,我们可以获取行数。使用当前行号,我们可以获得所选行的起始索引和结束索引。有了索引,我们就可以操作字符串了。希望这可以帮助你。

关于java - 在具有跨度的 Android TextView 中一次换行两行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60794616/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com