Flutter:使用 TapGestureRecognizer 更改 TextSpan 的文本样式

Flutter: Changing textstyle of TextSpan with TapGestureRecognizer

我想让文本中的每个词都可以点击。然后,当点击一个特定的词时,它的文本颜色应该改变。

让每个词都可以点击就可以了。但是,不知何故,当我点击一个词时,文本颜色不会改变。这是我走了多远:

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';

 class MakeStringClickable extends StatefulWidget{
 @override
 State<StatefulWidget> createState() {
 // TODO: implement createState
 return _MakeStringClickableState();
 }
 }

class _MakeStringClickableState extends State<MakeStringClickable>{

String textToSplit = 'I would like to make each word clickable. On click of a particular word it's color should change.';

@override
Widget build(BuildContext context) {
return Scaffold(
  body: Container(
      alignment: Alignment.center,
      child: _buildTextSpanWithSplittedText(textToSplit, context)
  ),
);
}

RichText _buildTextSpanWithSplittedText(String textToSplit, BuildContext context) {
bool isPressed = false;
final splittedText = textToSplit.split(" ");
final spans = new List<TextSpan>();

  for(int i = 0; i <= splittedText.length - 1; i++ ){
    spans.add(TextSpan(
      text: splittedText[i].toString() + " ",
      style: TextStyle(color: isPressed ? Colors.black : Colors.red),
      recognizer: new TapGestureRecognizer()..onTap = () {
      setState(() {isPressed = !isPressed;});
      }
    ));
  }
  return RichText(text: TextSpan(children: spans));
}
}

我希望当我点击任何单词时它的颜色会变成黑色,但不知何故改变样式并没有按预期工作。我希望有人能够帮助我。

第一个问题是 _buildTextSpanWithSplittedText 方法中有 isPressed,每次重新绘制时都会被覆盖。如果您将该变量保持在 class 级别,它将应用于所有 TextSpans。
所以一个可能的解决方案是使用 List,这里有一个例子:

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';

class MakeStringClickable extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MakeStringClickableState();
  }
}

class _MakeStringClickableState extends State<MakeStringClickable> {
  List<TapSection> sections;
  String textToSplit =
      'FirstWord would like to make each word clickable. On click of a particular word it\'s color should change.';
  TapGestureRecognizer r1;
  @override
  void initState() {
    sections = List<TapSection>();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        alignment: Alignment.center,
        child: _buildTextSpanWithSplittedText(textToSplit, context));
  }

  RichText _buildTextSpanWithSplittedText(
      String textToSplit, BuildContext context) {
    final splittedText = textToSplit.split(" ");
    final spans = List<TextSpan>();
    for (int i = 0; i <= splittedText.length - 1; i++) {
      var tapSection = TapSection(callBack: () {
        setState(() {});
      });
      sections.add(tapSection);
      spans.add(TextSpan(
          text: splittedText[i].toString() + " ",
          style: TextStyle(
              color: sections[i].isPressed ? Colors.black : Colors.red),
          recognizer: sections[i].recognizer));
    }
    return RichText(text: TextSpan(children: spans));
  }
}

class TapSection {
  TapGestureRecognizer recognizer;
  bool isPressed = false;
  final Function callBack;

  TapSection({this.callBack}) {
    recognizer = TapGestureRecognizer();
    recognizer.onTap = () {
      this.isPressed = !this.isPressed;
      this.callBack();
    };
  }
}

请注意,我们需要调用 setState 作为此解决方案的回调。
希望对您有所帮助。