forked from lxm_flutter/FlutterUnit
优化打字机效果
This commit is contained in:
@@ -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),);
|
||||
// }
|
||||
// }
|
||||
68
lib/views/components/permanent/text_typer.dart
Normal file
68
lib/views/components/permanent/text_typer.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user