使用可变文本在循环中使用Spannable。

huangapple go评论61阅读模式
英文:

Use spannable in a loop for a mutable text

问题

这是您的翻译内容:

所以我的应用程序应该将用户的输入与应用程序提供的随机引用进行比较,我希望将正确的单词着色为绿色,错误的单词着色为红色。
问题在于我不知道如何在循环中使用Spannable来实现这一点,特别是文本始终在变化。

这是代码:

if(quoteWords.length == resultWords.length){
                    
    for(int i = 0; i < quoteWords.length; i++) {
                        
        if (quoteWords[i].equals(resultWords[i])) { 
            // 将单词着色为绿色              
        } else {
            // 将单词着色为红色              
        }
    }
                    
}

以下是我尝试过的内容:

if(quoteWords.length == resultWords.length){
    SpannableStringBuilder fullStyledSentence = new SpannableStringBuilder();
    ForegroundColorSpan correctColor = new ForegroundColorSpan(Color.GREEN);
    ForegroundColorSpan wrongColor = new ForegroundColorSpan(Color.RED);
    int start;
    
    for(int i = 0; i < quoteWords.length; i++) {
        start = fullStyledSentence.length(); // 获取当前 SpannableString 的长度
        fullStyledSentence.append(quoteWords[i]);
        
        if (quoteWords[i].equals(resultWords[i])) { // 使用单词长度对每个单词着色
            fullStyledSentence.setSpan(correctColor, start, start + quoteWords[i].length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            Log.i("AzureSpeechRecognition", "第 " + i + " 个单词正确");
        } else {
            fullStyledSentence.setSpan(wrongColor, start, start + quoteWords[i].length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            Log.i("AzureSpeechRecognition", "第 " + i + " 个单词错误");
        }
        
        mQuoteBodyTextView.setText(null); // 清空重复添加的文本
        mQuoteBodyTextView.append(fullStyledSentence + " ");
    }
}

但是生成的文本没有着色,并且它们粘在一起没有空格。

英文:

So my app should compare the user's input with a random quote provided by the app, and I want to color the correct word with green and the wrong one with red.
the problem is that I don't know how to do it with Spannable in a loop, and especially that the text is always changing.

This is the code:

if(quoteWords.length == resultWords.length){
                    
     for(int i = 0; i &lt; quoteWords.length; i++) {
                        
         if (quoteWords[i].equals(resultWords[i])) { 
             //color the word with green               
         } else {
             //color the word with red               
         }
     }
                    
}

And this is what I tried:

    if(quoteWords.length == resultWords.length){
         SpannableStringBuilder fullStyledSentence = new SpannableStringBuilder();
         ForegroundColorSpan correctColor = new ForegroundColorSpan(Color.GREEN);
         ForegroundColorSpan wrongColor = new ForegroundColorSpan(Color.RED);
         int start;
    
         for(int i = 0; i &lt; quoteWords.length; i++) {
              start = fullStyledSentence.length(); //get length of current SpannableString
              fullStyledSentence.append(quoteWords[i]);
    
              if (quoteWords[i].equals(resultWords[i])) { //color each word using its length
                    fullStyledSentence.setSpan(correctColor, start, start + quoteWords[i].length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    Log.i(&quot;AzureSpeechRecognition&quot;, &quot;word number &quot; + i + &quot;is correct&quot;);
                    } else {
                       fullStyledSentence.setSpan(wrongColor, start, start + quoteWords[i].length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                       Log.i(&quot;AzureSpeechRecognition&quot;, &quot;word number &quot; + i + &quot;is wrong&quot;);
                    }
    
                       mQuoteBodyTextView.setText(null); //to delete repeatedly appended text
                       mQuoteBodyTextView.append(fullStyledSentence + &quot; &quot;);
              }
                        
     }

But the resulted text isn't colored and they are glued together with no spaces.

答案1

得分: 2

似乎 `ForegroundColorSpan`/`BackgroundColorSpan` 不可重用每次我们都需要实例化一个新的不管怎样我认为使用 `SpannableString` 更好就像下面这样

```java
public class MainActivity extends AppCompatActivity {

    // 将所有空白替换为单个空格
    private String quote = "我想要用绿色标记正确的单词".replaceAll("\\s+", " ");
    private String result = "我想要用蓝色标记正确的单词".replaceAll("\\s+", " ");

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String[] quoteWords = quote.split("\\s");
        String[] resultWords = result.split("\\s");

        SpannableString spannableQuote = new SpannableString(quote);

        if (quoteWords.length == resultWords.length) {
            int index = 0;
            for (int i = 0; i < quoteWords.length; i++) {
                spannableQuote.setSpan(
                    new BackgroundColorSpan(quoteWords[i].equals(resultWords[i]) ? Color.GREEN : Color.RED),
                    index,
                    index + quoteWords[i].length(),
                    SpannableString.SPAN_INCLUSIVE_INCLUSIVE
                );
                index += quoteWords[i].length() + 1; // 1 用于单词之间的空格
            }
        }

        ((TextView) findViewById(R.id.textView1)).setText(result);
        ((TextView) findViewById(R.id.textView2)).setText(spannableQuote);
    }
}

结果:

使用可变文本在循环中使用Spannable。

```

英文:

It seems that ForegroundColorSpan/BackgroundColorSpan are not reusable and each time we should instantiate a new one. Anyway, I think it makes sense better to write it using SpannableString like the following:

public class MainActivity extends AppCompatActivity {
// replacing all whitespaces with single space
private String quote = &quot;I want to color the correct word with green&quot;.replaceAll(&quot;\\s+&quot;, &quot; &quot;);
private String result = &quot;I want to color the right word with blue&quot;.replaceAll(&quot;\\s+&quot;, &quot; &quot;);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] quoteWords = quote.split(&quot;\\s&quot;);
String[] resultWords = result.split(&quot;\\s&quot;);
SpannableString spannableQuote = new SpannableString(quote);
if (quoteWords.length == resultWords.length) {
int index = 0;
for (int i = 0; i &lt; quoteWords.length; i++) {
spannableQuote.setSpan(
new BackgroundColorSpan(quoteWords[i].equals(resultWords[i]) ? Color.GREEN : Color.RED),
index,
index + quoteWords[i].length(),
SpannableString.SPAN_INCLUSIVE_INCLUSIVE
);
index += quoteWords[i].length() + 1; // 1 for the space between words
}
}
((TextView) findViewById(R.id.textView1)).setText(result);
((TextView) findViewById(R.id.textView2)).setText(spannableQuote);
}
}

<br/>

Result:

<tr>
<td><img src="https://i.stack.imgur.com/P0Cn0.png" width="300"/></td>
</tr>

huangapple
  • 本文由 发表于 2020年8月24日 06:40:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63552706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定