gradually_print_text.dart 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import 'dart:async';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. class GraduallyPrintText extends StatefulWidget {
  5. const GraduallyPrintText({
  6. super.key,
  7. this.initTxt,
  8. required this.graduallyController,
  9. this.textStyle,
  10. });
  11. final TextStyle? textStyle;
  12. final GraduallyController graduallyController;
  13. final String? initTxt;
  14. @override
  15. State<GraduallyPrintText> createState() => _GraduallyPrintTextState();
  16. }
  17. typedef GraduallyTxtListener = void Function(String txt);
  18. class GraduallyController {
  19. String graduallyTxt = '';
  20. int progressIndex = 0;
  21. Timer? appendTimer;
  22. bool? isAppendDone;
  23. bool? isShowDone;
  24. Duration printSpeed;
  25. GraduallyTxtListener? listener;
  26. VoidCallback? finishedListener;
  27. GraduallyController({this.printSpeed = const Duration(milliseconds: 60)});
  28. setGraduallyTxtListener(GraduallyTxtListener listener) {
  29. this.listener = listener;
  30. }
  31. setGraduallyFinishedListener(VoidCallback finishedListener) {
  32. this.finishedListener = finishedListener;
  33. }
  34. void clear() {
  35. appendTimer?.cancel();
  36. appendTimer = null;
  37. graduallyTxt = '';
  38. progressIndex = 0;
  39. isAppendDone = null;
  40. isShowDone = null;
  41. listener?.call(''); // 通知 UI 清空
  42. }
  43. append(String txt) {
  44. graduallyTxt += txt;
  45. _startAppend();
  46. }
  47. void _initAppend() {
  48. progressIndex = 0;
  49. isAppendDone = null;
  50. isShowDone = null;
  51. appendTimer = null;
  52. }
  53. appendDone() {
  54. isAppendDone = true;
  55. // debugPrint('GraduallyMdText: appendDone');
  56. }
  57. _startAppend() {
  58. if (appendTimer != null) {
  59. return;
  60. }
  61. _initAppend();
  62. appendTimer = Timer.periodic(printSpeed, (timer) {
  63. // debugPrint('GraduallyMdText-progressIndex: $progressIndex');
  64. if (progressIndex < graduallyTxt.length) {
  65. progressIndex += 1;
  66. listener?.call(graduallyTxt.substring(0, progressIndex));
  67. } else if (isAppendDone == true) {
  68. // debugPrint('GraduallyMdText: appendTimer done');
  69. dispose();
  70. finishedListener?.call();
  71. }
  72. });
  73. }
  74. dispose() {
  75. appendTimer?.cancel();
  76. isAppendDone = null;
  77. isShowDone = true;
  78. appendTimer = null;
  79. }
  80. }
  81. class _GraduallyPrintTextState extends State<GraduallyPrintText> {
  82. String mdTxt = '';
  83. @override
  84. void initState() {
  85. super.initState();
  86. mdTxt = widget.initTxt ?? '';
  87. widget.graduallyController.setGraduallyTxtListener((txt) {
  88. if (mounted) {
  89. setState(() {
  90. mdTxt = txt;
  91. });
  92. }
  93. });
  94. }
  95. @override
  96. void dispose() {
  97. super.dispose();
  98. }
  99. @override
  100. Widget build(BuildContext context) {
  101. return SelectionArea(
  102. child: Text(
  103. mdTxt,
  104. style: widget.textStyle,
  105. ),
  106. );
  107. }
  108. }