如何处理字数中的新行?

how to handle new line in word count?

我指的是这个答案

基本上我的目标是处理 100 个单词的字数 以上解决方案适用于键入 100 个单词,甚至可以很好地处理复制粘贴

但它不处理新行的情况 假设输入的单词或复制粘贴的单词包含新行,则返回的字数不正确

代码如下,请大家帮忙

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, 
       count: Int) {
    val wordsLength: Int = countWords(s.toString()) // words.length;
    limitmoderator.text = "$wordsLength/$MAX_WORDS"
    val yourText: String =
        moderator_intro.getText().toString().replace(160.toChar().toString(), " ")
    if (yourText.split("\s+".toRegex()).size > MAX_WORDS) {
        var space = 0
        var length = 0
        for (i in 0 until yourText.length) {
            if (yourText[i] == ' ') {
                space++
                if (space >= MAX_WORDS) {
                    length = i
                    break
                }
            }
        }
        if (length > 1) {
            moderator_intro.getText()
                .delete(length, yourText.length) // deleting last exceeded words
            setCharLimit(moderator_intro, length - 1) //limit edit text
        }
    } else {
        removeFilter(moderator_intro)
    }}


 private fun countWords(s: String): Int {
 val trim = s.trim()
 return if (trim.isEmpty()) 0 else trim.split("\s+".toRegex()).size
 // separate string around spaces
    }

    private var filter: InputFilter? = null

    private fun setCharLimit(et: EditText, max: Int) {
filter = LengthFilter(max)
et.filters = arrayOf<InputFilter>(filter as LengthFilter)
     }

    private fun removeFilter(et: EditText) {
    if (filter != null) {
    et.filters = arrayOfNulls(0)
     filter = null
      }
    }
       

所以我尝试在文本中放置“\n”,但它似乎没有正确处理这种情况

任何帮助将不胜感激

提前致谢

您可以编写一个正则表达式来匹配您要保留的文本并删除其余部分。在这种情况下,您需要匹配 (non-whitespace+)(whitespace*) 最多 100 次。

override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
  val input = moderator_intro.getText().toString()
  val maxWords = 100
  val whiteSpace = "\p{javaWhitespace}\u00A0\u2007\u202F" //All white space characters
  val keepRegex = Regex("[$whiteSpace]*([^$whiteSpace]+[$whiteSpace]*){1,${maxWords.toString()}}")
  val allowedText = keepRegex.find(input)?.value ?: ""
  val wordAmount = allowedText.split(Regex("[$whiteSpace]+")).filter { it.isNotBlank() }.size
  
  val trailingWhiteSpace = Regex("[$whiteSpace]+$")
  if(wordAmount == maxWords && allowedText.contains(trailingWhiteSpace)) {
    val newText = allowedText.replace(trailingWhiteSpace, "")
    moderator_intro.getText().delete(allowedText.length, input.length)
    setCharLimit(moderator_intro, newText.length)
  } else {
    removeFilter(moderator_intro)
  }
}

这里的策略与您链接的问题中的策略不同。请注意,我使用的是 afterTextChanged 而不是 onTextChanged!

我正在手动计算单词数以获取最后一个允许单词之后的第一个空格的字符索引。这样我就不必 trim 然后使用正则表达式,然后尝试找出该正则表达式的索引偏移量。然后我没有应用临时过滤器,而是直接将 Editable 的末尾剪掉。

editText.setSelection是为了防止光标跳到开头

override fun afterTextChanged(s: Editable) {
    var previousWasWhitespace = true
    var i = 0
    var wordCount = 0
    for (c in s) {
        val whitespace = c.isWhitespace()
        if (whitespace && !previousWasWhitespace && ++wordCount == MAX_WORDS) {
            break
        }
        previousWasWhitespace = whitespace
        i++
    }

    if (i < s.length) {
        s.delete(i, s.length)
        editText.setSelection(i)
    }
}