【问题标题】:How to create multiple Streams dynamically in Flutter?如何在 Flutter 中动态创建多个 Streams?
【发布时间】:2021-10-07 06:44:31
【问题描述】:

我有这段代码,它将字符串中的每个字符添加到计时器内的流中,从而产生这种效果:

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

void main() async {
  runApp(
    MaterialApp(
      home: TextSpanStream(),
    ),
  );
}

class TextSpanStream extends StatefulWidget {
  TextSpanStream({Key? key}) : super(key: key);

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

class _TextSpanStreamState extends State<TextSpanStream> {
  Timer? _timer;
  StreamController<String> _textShowController =
      StreamController<String>.broadcast();

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration(seconds: 1), () => startBroadcast());
  }

  @override
  void dispose() {
    _textShowController.close();
    _timer?.cancel();
    super.dispose();
  }

  void startBroadcast() {
    String title = 'This is a title';
    int countLetter = 1;

    _timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
      _textShowController.add(title.substring(0, countLetter));
      countLetter++;
      if (countLetter == title.length + 1) {
        timer.cancel();
        countLetter = 1;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.cyan[900],
      body: Center(
        child: Container(
          color: Colors.black26,
          width: 400,
          child: StreamBuilder<String>(
            stream: _textShowController.stream,
            builder: (context, snapshot) {
              return Text(
                snapshot.hasData ? (snapshot.data ?? '') : '',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

问题是,我想使用 RichText 执行此操作,而不是单个字符串,其中每个 TextSpan 都来自长度未知的 TextSpan 列表。这样,每个 TextSpan 都会有自己不同的样式,并且会按顺序(一个接一个)进行动画处理。

例如:

List<TextSpan> allSpans = [TextSpan(text: 'This is a ', style: TextStyle(color: Colors.white)), TextSpan(text: 'title', style: TextStyle(color: Colors.red))];

是否可以为每个 TextSpan 创建单独的 Stream?还是有更好的方法?

【问题讨论】:

    标签: flutter dart stream


    【解决方案1】:

    您可以创建 TextSpan 并通过要构建的流发送它。

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Rich Text Animation',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Rich Text Animation'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      StreamController<List<TextSpan>> _streamController =
          StreamController.broadcast();
      static const DELAY = Duration(milliseconds: 100); 
    
      @override
      void initState() {
        super.initState();
        _animate();
      }
    
      void _animate() {
        final _allSpans = [
          TextSpan(text: 'This is a ', style: TextStyle(color: Colors.white)),
          TextSpan(text: 'title', style: TextStyle(color: Colors.red)),
        ];
        Duration _delay = Duration(seconds: 1);
        _allSpans.forEach((span) {
          for (int i = 0; i < (span.text?.length ?? 0); i++) {
            Future.delayed(_delay, () {
              _streamController.add([
                ..._allSpans.sublist(0, _allSpans.indexOf(span)),
                TextSpan(text: span.text!.substring(0, i + 1), style: span.style)
              ]);
            });
            _delay += DELAY;
          }
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Container(
            color: Colors.green.shade700,
            child: Center(
              child: StreamBuilder<List<TextSpan>>(
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return RichText(
                      text: TextSpan(children: snapshot.data),
                    );
                  }
                  return CircularProgressIndicator();
                },
                stream: _streamController.stream,
              ),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.animation),
            onPressed: () {
              _animate();
            },
          ),
        );
      }
    
      @override
      void dispose() {
        _streamController.close();
        super.dispose();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-11-17
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多