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

时间:2019-04-24 22:12:42

标签: split dart flutter styles uitapgesturerecognizer

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

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

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));
}
}

我希望任何单词的颜色在单击时都会变为黑色,但是以某种方式更改样式无法按预期进行。我希望有人能够帮助我。

1 个答案:

答案 0 :(得分:1)

第一个问题是您在_buildTextSpanWithSplittedText方法中具有 isPressed ,该方法将在每次重新绘制时被覆盖。而且,如果将该变量保留在类级别,则它将应用于所有TextSpans。
因此,可能的解决方案是使用列表,下面是一个示例:

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 作为此解决方案的回调。
希望有帮助。