Flutter 未更新其动画文本小部件 (Animated_Text_kit)

Flutter not updating its animated text widget (Animated_Text_kit)

所以这是我从 json 获取数据并更新我的 UI 的主要代码。 我在与问题相关的代码所在的位置放置了“//Area of​​ Interest”注释。

 class MainScreen extends StatefulWidget {
  final curLocdata;
  MainScreen({this.curLocdata});

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  Weather weather = Weather();

  var cityName;
  int temp;
  int temp_min;
  int temp_max;
  Icon weatherIcon;
//Area of Interest 1
  RotateAnimatedTextKit textSum;//created a widget of RotateAnimatedTextKit library.
  String st;
//Area of Interest 2
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    updateUI(widget.curLocdata);//calling update function to rebuild my UI state with new data
  }

  void updateUI(data) {
    setState(() {
      if (data == null) {
        temp = 0;
        cityName = 'Error';
        weatherIcon = Icon(Icons.error);
        return;
      }
      cityName = data['name'];
      temp = data['main']['temp'].toInt();
      temp_min = data['main']['temp_min'].toInt();
      temp_max = data['main']['temp_max'].toInt();
      var condition = data['weather'][0]['id'];
      weatherIcon = weather.getIcon(condition);
      textSum = weather.getMessage(temp);//Area of Interest 3
      st = weather.subtext(condition);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: SafeArea(
          child: Column(
            children: <Widget>[
              Container(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    FlatButton(
                      onPressed: () async {
                        updateUI(await Network().getData());
                      },
                      child: Icon(
                        FontAwesomeIcons.locationArrow,
                      ),
                    ),
                    SizedBox(
                      width: 180.0,
                      child: TextLiquidFill(
                        waveDuration: Duration(seconds: 3),
                        loadDuration: Duration(seconds: 10),
                        text: 'OpenWeather',
                        waveColor: Colors.red,
                        boxBackgroundColor: Color(0xFF1B1B1D),
                        textStyle: TextStyle(
                          fontSize: 30.0,
                          fontWeight: FontWeight.bold,
                          fontFamily: 'Source Sans Pro',
                        ),
                        boxHeight: 50.0,
                      ),
                    ),
                    FlatButton(
                      onPressed: () async {
                        String SName = await Navigator.push(context,
                            MaterialPageRoute(builder: (context) {
                          return Search();
                        }));
                        if (SName != null) {
                          updateUI(await Network().getDataName(
                              SName)); 
                        }
                      },
                      child: Icon(
                        Icons.add,
                        color: Colors.white,
                        size: 40,
                      ),
                    ),
                  ],
                ),
              ),
              Padding(
                  padding: EdgeInsets.fromLTRB(50, 50, 50, 0),
                  child: Row(
                    children: <Widget>[
                      SizedBox(
//                margin: EdgeInsets.fromLTRB(0, 50, 260, 0),
                        child: TypewriterAnimatedTextKit(
                          totalRepeatCount: 200,
                          isRepeatingAnimation: true,
                          speed: Duration(milliseconds: 700),
                          text: [cityName,],
                          textAlign: TextAlign.left,
                          textStyle: TextStyle(
                            fontSize: 20,
                            fontFamily: 'Source Sans Pro',
                          ),
                        ),
                      ),
                    ],
                  )),
              Expanded(
                flex: 9,
                child: Container(
                  margin: EdgeInsets.fromLTRB(50, 30, 50, 80),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: <Widget>[
                      Expanded(
                        flex: 2,
                        child: Padding(
                          padding: EdgeInsets.only(left: 20),
                          child: Text(
                            '$temp°',
                            style: TextStyle(
                              fontSize: 80,
                              fontWeight: FontWeight.bold,
                              fontFamily: 'Source Sans Pro',
                            ),
                          ),
                        ),
                      ),
                      Expanded(
                        flex: 2,
                        child: Padding(
                          padding: EdgeInsets.only(left: 20),
                          child: Text(
                            st,
                            style: TextStyle(
                                fontSize: 30,
                                fontFamily: 'Source Sans Pro',
                                color: Colors.grey[500]),
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(20, 0, 0, 50),
                        child: Container(
                          child: textSum,//Used this textSum to show my animated text. problem
Area of Interest 4
                        ),
                      ),
                      Expanded(
                        child: SizedBox(
                          //width: double.infinity,
                          //height: 100,
                          child: Divider(
                            color: Colors.red,
                          ),
                        ),
                      ),
                      Row(
                        children: <Widget>[
                          Expanded(
                            child: Padding(
                              padding: EdgeInsets.fromLTRB(20, 0, 0, 38),
                              child: Text(
                                '$temp_min° - $temp_max°',
                                style: TextStyle(
                                  fontSize: 20,
                                  color: Colors.grey[500],
                                  fontFamily: 'Source Sans Pro',
                                ),
                              ),
                            ),
                          ),
                          Expanded(
                            child: Padding(
                              padding: EdgeInsets.fromLTRB(20, 0, 0, 20),
                              //padding: const EdgeInsets.all(8.0),
                              child: AvatarGlow(
                                endRadius: 30.0, //required
                                child: Material(
                                  //required
                                  elevation: 0.0,
                                  shape: CircleBorder(),
                                  child: CircleAvatar(
                                      //backgroundColor: Colors.grey[100],
                                      child: weatherIcon
                                      // radius: 40.0,
                                      //shape: BoxShape.circle
                                      ),
                                ),
                              ),
                            ),
                          )
                        ],
                      )`enter code here`
                    ],
                  ),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: Color(0xFF0C0C0C),
                  ),
                ),
              ),

现在 weather.dart 文件,我从中返回 RotateAnimatedTextKit 小部件,具体取决于条件

    class Weather{

//This return RotateAnimatedTextKit which is then held by textSum and is put as a child inside a container in MainScreen

  RotateAnimatedTextKit getMessage(int temp) {
    if (temp > 25) {
      return RotateAnimatedTextKit(
          isRepeatingAnimation: true,
          totalRepeatCount: 200,
          transitionHeight: 40,
          text: ['It\'s ','time and','drink plenty','of water'],
          textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
          textAlign: TextAlign.start,
          alignment: AlignmentDirectional.topStart // or Alignment.topLeft
      );

      
    } else if (temp > 20) {
      return RotateAnimatedTextKit(
          isRepeatingAnimation: true,
          totalRepeatCount: 200,
          transitionHeight: 50,
          text: ['Time for','shorts','','but keep','some warm','clothes handy'],
          textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
          textAlign: TextAlign.start,
          alignment: AlignmentDirectional.bottomStart// or Alignment.topLeft
      );
      
    } else if (temp < 10) {
      return RotateAnimatedTextKit(
          isRepeatingAnimation: true,
          totalRepeatCount: 200,
          transitionHeight: 50,
          text: ['You\'ll need','a ','and','a ','and a hot', 'soup and turkey'],
          textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
          textAlign: TextAlign.start,
          alignment: AlignmentDirectional.bottomStart // or Alignment.topLeft
      );
     
    } else {
      return RotateAnimatedTextKit(
          isRepeatingAnimation: true,
          transitionHeight: 50,
          totalRepeatCount: 200,
          text: ['Bring a','','just in case','and also avoid', 'cold breeze','and cold drinks'],
          textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
          textAlign: TextAlign.start,
          alignment: AlignmentDirectional.bottomStart // or Alignment.topLeft
      );
      
    }
  }

问题是即使条件不同,UI 也不会更新。那么为什么小部件树不更新的任何解决方案?但它只运行默认文本。此外,TextLiquidFill 下的 cityName 不会更新。

您可以使用 WidgetsBinding.instance.addPostFrameCallback
详细可以参考https://www.didierboelens.com/faq/week2/

代码片段

@override
void initState(){
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_){
    updateUI(widget.curLocdata);
  });
}

简答: 使用按键

示例:

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

class MyAnimatedText extends StatefulWidget {
  const MyAnimatedText({Key? key}) : super(key: key);
  @override
  State<MyAnimatedText> createState() => _MyAnimatedTextState();
}

class _MyAnimatedTextState extends State<MyAnimatedText> {
  bool isDarkMode = true;

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(30),
          color: isDarkMode ? Colors.grey[850] : Colors.amber[300]),
      child: Column(
        children: [
          Container(
              alignment: Alignment.topRight,
              child: IconButton(
                  onPressed: () {
                    setState(() {
                      isDarkMode = !isDarkMode;
                    });
                  },
                  icon: Icon(isDarkMode ? Icons.light_mode : Icons.dark_mode))),
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: AnimatedTextKit(
              key: ValueKey<bool>(isDarkMode),
              animatedTexts: [
                TypewriterAnimatedText(
                  isDarkMode ? 'Have a nice evening ;)' : 'Have a nice day :)',
                  cursor: isDarkMode ?'>':'<',
                  textStyle: TextStyle(
                      fontSize: 38,
                      color: isDarkMode ? Colors.amber[300] : Colors.grey[850]),
                  speed: const Duration(milliseconds: 100),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

结果:

背景资料

当我尝试实现暗/亮变化时,我遇到了同样的问题。背景颜色在另一个小部件中定义并更改,字体颜色在 TypewriterAnimatedText 小部件中定义并且仅在第二个循环中更改。 runnig 动画中颜色没有变化。

解决方法:使用Keys Animation 不会改变,因为 Flutter 试图保持 StatefulWidget 的状态,而 AnimatedTextKit 是一个 Stateful Widget。 要强制重建,您可以使用密钥。

可以在这里找到一篇不错的文章:How to force a Widget to redraw in Flutter?