Flutter循环生成TextSpan时重复最后句子的问题求助
Flutter嵌套TextSpan重复显示最后一句的问题解决
问题描述
我是Flutter新手,想要开发一款语言学习APP,实现文本中每个单词可点击并高亮,同时包含该单词的句子也能以不同样式高亮。采用嵌套TextSpan设置样式时,遇到了生成内容全部为文本最后一个句子的问题。
预期结果应该是“句子一 句子二 … 最后一句”,但实际结果却是“最后一句 最后一句 … 最后一句”。推测问题出在将listOfWords添加到listOfTextSpans时,存储的是指向listOfWords的引用而非内容副本,导致每次循环更新内容时所有元素随之改变。
问题代码
List<TextSpan> TextSpanSentences(List sentences) { List<Sentence> listOfSentences = []; List<TextSpan> listOfWords = []; List<TextSpan> listOfTextSpans = []; for (String sentence in sentences) { listOfSentences.add(Sentence(sentence: sentence)); } for (Sentence sentence in listOfSentences) { listOfWords.clear(); for (String word in sentence.words) { listOfWords.add( TextSpan( text: '$word ', style: TextStyle(color: Colors.black, fontSize: 20, height: 1.8), recognizer: wordTapRecognizer(word), ), ); } listOfTextSpans.add(TextSpan( children: listOfWords, )); } return listOfTextSpans; }
(Sentence是一个存储完整句子及其拆分后单词的简单类)
解决方案
你的推测完全正确——Dart中列表属于引用类型,listOfWords.clear()只是清空原有列表的内容,而非创建新的列表实例。这导致所有添加到listOfTextSpans的TextSpan,其children属性都指向同一个listOfWords列表,最终所有元素都会显示最后一次循环的内容。
修改核心是避免复用同一个列表实例,每次循环时创建新的listOfWords即可:
修正后的代码
List<TextSpan> TextSpanSentences(List sentences) { List<Sentence> listOfSentences = []; List<TextSpan> listOfTextSpans = []; for (String sentence in sentences) { listOfSentences.add(Sentence(sentence: sentence)); } for (Sentence sentence in listOfSentences) { // 每次循环创建新的列表实例,不再复用旧列表 List<TextSpan> listOfWords = []; for (String word in sentence.words) { listOfWords.add( TextSpan( text: '$word ', style: TextStyle(color: Colors.black, fontSize: 20, height: 1.8), recognizer: wordTapRecognizer(word), ), ); } listOfTextSpans.add(TextSpan( children: listOfWords, )); } return listOfTextSpans; }
简化版代码
可以去掉中间的listOfSentences变量,直接遍历原句子列表,让代码更简洁:
List<TextSpan> TextSpanSentences(List<String> sentences) { final listOfTextSpans = <TextSpan>[]; for (final sentenceStr in sentences) { final sentence = Sentence(sentence: sentenceStr); final listOfWords = <TextSpan>[]; for (final word in sentence.words) { listOfWords.add( TextSpan( text: '$word ', style: const TextStyle(color: Colors.black, fontSize: 20, height: 1.8), recognizer: wordTapRecognizer(word), ), ); } listOfTextSpans.add(TextSpan(children: listOfWords)); } return listOfTextSpans; }
这样每个TextSpan的children都会指向独立的列表实例,不会互相干扰,就能正确显示每一句的内容了。
内容的提问来源于stack exchange,提问作者biodegradablePotatoChip
相关产品推荐
相关产品推荐

