如何在 Flutter 中动态更新列表中元素的样式?

Posted

技术标签:

【中文标题】如何在 Flutter 中动态更新列表中元素的样式?【英文标题】:How can I update the style of an element inside a list dynamically in Flutter? 【发布时间】:2021-12-12 05:50:19 【问题描述】:

我正在用颤振制作一个快速阅读练习应用程序。我尝试在我的列表上运行 foreach 循环来更新 TextSpans 不透明度,但它没有用。之后,我尝试用新的 TextSpan 和新的不透明度替换元素,元素在列表中发生了变化,但它没有呈现在屏幕上。这是我的代码。

  var textList = <TextSpan>[];
  @override
  void initState() 
    super.initState();            
    text.split(' ').forEach((element) 
      textList.add(TextSpan(text:element));                     
    );
  
    Widget _textArea() 
      return FractionallySizedBox(
          widthFactor: 0.9,
          heightFactor: 0.9,
          child: DecoratedBox(
              decoration: BoxDecoration(
                border: Border.all(
                  color: Colors.grey,
                  width: 1,
                ),
              ),
              child: RichText(
                  text: TextSpan(
                    children: textList
                  ),
                ) 
              ));
    

我需要每秒更新textList 中每个元素的不透明度,并且更新函数必须以 ``ònPress```事件开始。 我被这个问题困住了。

完整代码

import 'package:flutter/material.dart';

class HomePeageReaderWidget extends StatefulWidget 
  const HomePeageReaderWidget(Key? key) : super(key: key);

  @override
  _HomePageReaderWidgetState createState() => _HomePageReaderWidgetState();


class _HomePageReaderWidgetState extends State<HomePeageReaderWidget> 
  var text =
      """Gaziantep şehri Türkiye'nin güneydoğusundadır. Çok güzel bir şehirdir. Belki İstanbul ve Ankara kadar büyük değildir, ama yine de burada bir milyonun üstünde insan yaşıyor. Gaziantep'te iş alanları çok geniştir, herkes çalışıyor. Birçok fabrikalar ve atölyeler vardır. Ayrıca bir de Gaziantep Üniversitesi vardır. Üniversite şehirden biraz uzak, ama yurt da üniversitenin yanında. Bunun için ulaşım sorunu yok.Gaziantep'te yazın hava çok sıcak oluyor, insanlar evlerinden ve iş yerlerinden dışarıya çıkmıyorlar. Gece balkonlarda yatıyorlar. Kışın ise havalar sert, sokaklar ise her zaman ıslaktır.""";

  var textList = <TextSpan>[];
  @override
  void initState() 
    super.initState();
    text.split(' ').forEach((element)       
      textList.add(TextSpan(text: element));
    );
  

  @override
  Widget build(BuildContext context) 
    Widget _controlRow() 
      return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Column(
            children: [
              IconButton(
                onPressed: () ,
                icon: const Icon(Icons.skip_previous),
                iconSize: 50,
                color: const Color(0xFFffcd05),
              )
            ],
          ),
          Column(
            children: [
              IconButton(
                onPressed: () ,
                icon: const Icon(Icons.pause_circle),
                iconSize: 50,
                color: const Color(0xFF91268e),
              )
            ],
          ),
          Column(
            children: [
              IconButton(
                onPressed: () ,
                icon: const Icon(Icons.skip_next),
                iconSize: 50,
                color: const Color(0xFFffcd05),
              )
            ],
          ),
        ],
      );
    

    Widget _textArea() 
      return FractionallySizedBox(
          widthFactor: 0.9,
          heightFactor: 0.9,
          child: DecoratedBox(
              decoration: BoxDecoration(
                border: Border.all(
                  color: Colors.grey,
                  width: 1,
                ),
              ),
              child: RichText(
                text: TextSpan(children: textList),
              )));
    

    return Column(
      children: [
        Expanded(
          flex: 6,
          child: _textArea(),
        ),
        Expanded(
          child: _controlRow(),
        ),
        Container(
          width: 300,
          child: ElevatedButton.icon(
            onPressed: () 
              // Respond to button press
            ,
            icon: Icon(Icons.play_arrow, size: 18),
            label: Text("Hızlı Egzersiz"),
            style: ButtonStyle(
              backgroundColor:
                  MaterialStateProperty.all(const Color(0xFF075098)),
            ),
          ),
        )
      ],
    );
  


【问题讨论】:

您需要为文本设置动画吗? 是的,我尝试为此使用一个包,但它也对我不起作用,因为我需要将当前元素的不透明度更改为 1,将元素之前的不透明度更改为 0.7,但现在没关系,因为我当我改变它时,甚至不能改变不透明度或列表内的任何东西也不会在屏幕上呈现 如果你需要我可以添加完整代码 你需要使用某种动画小部件,试试 AnimatedOpacity 或 FadeTransition。 好的,但我想在每秒循环一次的 for 循环中更改这些不透明度,它应该在 onPress 事件上运行。当我这样做时,元素的不透明度发生了变化,但它没有呈现在屏幕上。 【参考方案1】:

您需要使用setState( ),以便您的更改反映在客户端中。

不要忘记您需要保留 StatefulWidget 以便 setState 工作

代码:

  onPressed: () 
    setState(()  
      yourOpacityValue = updatedOpacityValue; );
  ,

【讨论】:

我需要为我的每一个元素分别更改不透明度。因此,如果我的文本有 10000 个单词,我需要设置 10000 个状态。也许我可以将 Text 元素呈现为单独的 Statefull 小部件,但是 IDK 如果我这样做,我该如何更改父元素内的小部件不透明度。 您可以在同一个 setState 中更改所有 10000 个值 当第 4 项的不透明度为 1、第 2 项和第 3 项的不透明度必须为 0.7 时,如何分别为每个项执行此操作。我什至不知道那段有多少字。 @kemalkaancetindag 如果您的应用有 10,000 个独立的有状态小部件,所有这些小部件都需要同时更改和刷新,那么您需要退后一步,重新评估您的方法。 很遗憾你是对的 :(

以上是关于如何在 Flutter 中动态更新列表中元素的样式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中构建动态列表?

如何在动态列表视图中导航至下一页-Flutter

如何在 StreamBuilder 中更新 Flutter Cards 而无需重置状态?

Flutter中如何改变网页的样式

如何使用 Dart / Flutter 中的列表从列表中删除重复元素?

在ListView中动态更新列表元素高度