优化打字机效果

This commit is contained in:
toly
2021-05-14 14:47:01 +08:00
parent 165f6384af
commit 9af363a775
6 changed files with 146 additions and 86 deletions

View File

@@ -1,66 +1,66 @@
import 'package:flutter/material.dart';
class AnimatedText extends StatefulWidget {
final String text;
final int delayInMilliseconds;
final int durationInMilliseconds;
final TextStyle textStyle;
AnimatedText(this.text, this.delayInMilliseconds,
{this.durationInMilliseconds: 2500, this.textStyle});
@override createState() => AnimatedTextState();
}
class AnimatedTextState extends State<AnimatedText>
with SingleTickerProviderStateMixin {
String currentText = '';
AnimationController _controller;
List<int> get textRunes=> widget.text.runes.toList();
int get value => _controller.value.toInt();
int curIndex = 0;
@override
void initState() {
super.initState();
currentText = String.fromCharCode(textRunes[0]);
_controller = AnimationController(
vsync: this,
value: 0.0,
lowerBound: 0.0,
upperBound: textRunes.length.toDouble(),
duration: Duration(milliseconds: widget.durationInMilliseconds));
_controller..addListener(_updateText)..forward();
}
_updateText(){
if (value > curIndex && value < textRunes.length) {
setState(() {
curIndex = value;
currentText += String.fromCharCode(textRunes[curIndex]);
});
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text(currentText, textAlign: TextAlign.left,
style: widget.textStyle ??
TextStyle(fontWeight: FontWeight.w600, fontSize: 20.0),);
}
}
//
// import 'package:flutter/material.dart';
//
// class AnimatedText extends StatefulWidget {
// final String text;
// final int delayInMilliseconds;
// final int durationInMilliseconds;
// final TextStyle textStyle;
//
// AnimatedText(this.text, this.delayInMilliseconds,
// {this.durationInMilliseconds: 2500, this.textStyle});
//
// @override createState() => AnimatedTextState();
// }
//
// class AnimatedTextState extends State<AnimatedText>
// with SingleTickerProviderStateMixin {
//
// String currentText = '';
//
// AnimationController _controller;
//
// List<int> get textRunes=> widget.text.runes.toList();
// int get value => _controller.value.toInt();
//
// int curIndex = 0;
//
//
// @override
// void initState() {
// super.initState();
// currentText = String.fromCharCode(textRunes[0]);
//
// _controller = AnimationController(
// vsync: this,
// value: 0.0,
// lowerBound: 0.0,
// upperBound: textRunes.length.toDouble(),
// duration: Duration(milliseconds: widget.durationInMilliseconds));
//
// _controller..addListener(_updateText)..forward();
//
// }
//
// _updateText(){
// if (value > curIndex && value < textRunes.length) {
// setState(() {
// curIndex = value;
// currentText += String.fromCharCode(textRunes[curIndex]);
// });
// }
// }
//
// @override
// void dispose() {
// _controller.dispose();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return Text(currentText, textAlign: TextAlign.left,
// style: widget.textStyle ??
// TextStyle(fontWeight: FontWeight.w600, fontSize: 20.0),);
// }
// }

View File

@@ -0,0 +1,68 @@
import 'dart:async';
import 'package:flutter/material.dart';
class TextTyper extends StatefulWidget {
final String text;
final Duration duration;
final TextStyle textStyle;
TextTyper(
{this.text,
Key key,
this.textStyle =
const TextStyle(fontWeight: FontWeight.w600, fontSize: 20.0),
this.duration = const Duration(milliseconds: 150)})
: super(key: key);
@override
_TextTyperState createState() => _TextTyperState();
}
class _TextTyperState extends State<TextTyper> {
final ValueNotifier<String> data = ValueNotifier<String>("");
Timer _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(widget.duration, _type);
}
int currentIndex = 0;
String get currentText => widget.text.substring(0, currentIndex);
void _type(Timer timer) {
if (currentIndex < widget.text.length) {
currentIndex++;
data.value = currentText;
} else {
_timer?.cancel();
_timer = null;
}
}
@override
void dispose() {
_timer?.cancel();
data.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: 300,
child: AnimatedBuilder(
animation: data,
builder: _buildByAnim,
),
);
}
Widget _buildByAnim(BuildContext context, Widget child) => Text(
data.value,
style: widget.textStyle,
);
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/views/components/permanent/animated_text.dart';
import 'package:flutter_unit/views/components/permanent/circle_image.dart';
import 'package:flutter_unit/views/components/permanent/text_typer.dart';
class AttrUnitPage extends StatelessWidget {
final info = '【Flutter属性集录】是Unit项目计划的第二阶段的功能之一。'
@@ -42,10 +42,8 @@ class AttrUnitPage extends StatelessWidget {
child: ShaderMask(
shaderCallback: (rect) =>
_buildShader(rect, Theme.of(context).primaryColor),
child: AnimatedText(
info,
0,
durationInMilliseconds: 10000,
child: TextTyper(
text:info,
textStyle: TextStyle(
shadows: [
Shadow(

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/views/components/permanent/animated_text.dart';
import 'package:flutter_unit/views/components/permanent/circle_image.dart';
import 'package:flutter_unit/views/components/permanent/text_typer.dart';
class LayoutUnitPage extends StatelessWidget {
final info = '【Flutter布局集录】是Unit项目计划的第二阶段的功能之一。'
@@ -44,10 +44,8 @@ class LayoutUnitPage extends StatelessWidget {
child: ShaderMask(
shaderCallback: (rect) =>
_buildShader(rect, Theme.of(context).primaryColor),
child: AnimatedText(
info,
0,
durationInMilliseconds: 10000,
child: TextTyper(
text:info,
textStyle: TextStyle(
shadows: [
Shadow(

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/views/components/permanent/animated_text.dart';
import 'package:flutter_unit/views/components/permanent/circle_image.dart';
import 'package:flutter_unit/views/components/permanent/text_typer.dart';
class PaintUnitPage extends StatelessWidget {
final info = '【Flutter绘制集录】是Unit项目计划的第二阶段的功能之一。'
@@ -44,10 +44,8 @@ class PaintUnitPage extends StatelessWidget {
child: ShaderMask(
shaderCallback: (rect) =>
_buildShader(rect, Theme.of(context).primaryColor),
child: AnimatedText(
info,
0,
durationInMilliseconds: 10000,
child: TextTyper(
text:info,
textStyle: TextStyle(
shadows: [
Shadow(

View File

@@ -2,9 +2,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/app/router/unit_router.dart';
import 'package:flutter_unit/views/components/permanent/animated_text.dart';
import 'package:flutter_unit/views/components/permanent/circle_image.dart';
import 'package:flutter_unit/views/components/permanent/feedback_widget.dart';
import 'package:flutter_unit/views/components/permanent/text_typer.dart';
class BugUnitPage extends StatelessWidget {
@@ -52,10 +52,8 @@ class BugUnitPage extends StatelessWidget {
child: ShaderMask(
shaderCallback: (rect) =>
_buildShader(rect, Theme.of(context).primaryColor),
child: AnimatedText(
info,
0,
durationInMilliseconds: 10000,
child: TextTyper(
text:info,
textStyle: TextStyle(
shadows: [
Shadow(