实现组合组件TurnBox组件,它可以任意角度来旋转其子节点,而且可以在角度发生变化时执行一个过渡动画到新状态,同时,还可以手动指定动画的速度。
示例:
class SSLTurnBox extends StatefulWidget{
final double turns;
final int speed;
final Widget child;
const SSLTurnBox({
Key? key,
this.turns = 0.0,
this.speed = 200,
required this.child,
}):super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SSLTurnBoxState();
}
}
class SSLTurnBoxState extends State<SSLTurnBox> with SingleTickerProviderStateMixin{
late AnimationController controller;
@override
void initState() {
// TODO: implement initState
super.initState();
controller = AnimationController(
vsync: this,
lowerBound: - double.infinity,
upperBound: double.infinity,
);
controller.value = widget.turns;
}
@override
void dispose() {
// TODO: implement dispose
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return RotationTransition(
turns: controller,
child: widget.child,
);
}
@override
void didUpdateWidget(covariant SSLTurnBox oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
if (oldWidget.turns != widget.turns){
controller.animateTo(
widget.turns,
duration: Duration(milliseconds: widget.speed??200),
curve: Curves.easeOut,
);
}
}
}
代码分析:
- 通过组合RotationTransition和child来实现旋转效果。
- 在didUpdateWidget中,判断要旋转的角度是否发生变化,如果变化则执行一个动画。
使用示例:
class SSLTurnBoxTest extends StatefulWidget{
const SSLTurnBoxTest({Key? key}):super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SSLTurnBoxTestState();
}
}
class SSLTurnBoxTestState extends State<SSLTurnBoxTest>{
double turns = 0.0;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: const Text("TurnBox"),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 100,
width: 100,
child: SSLTurnBox(
turns: turns,
speed: 500,
child: Image.asset("images/apple.jpg"),
),
),
Container(
height: 150,
color: Colors.lightBlue,
child: SSLTurnBox(
turns: turns,
speed: 200,
child: Image.asset("images/device.jpg"),
),
),
ElevatedButton(
onPressed: (){
setState(() {
turns += 0.2;
});
},
child: const Text("Start Animation")
),
TextButton(
onPressed: (){
setState(() {
turns -= 0.2;
});
},
child: const Text("Reverse Animation"),
),
],
),
),
);
}
}
下面封装一个富文本展示组件RichText,可以自动处理url连接,定义如下:
class SSLRichText extends StatefulWidget{
final String text;
final TextStyle? linkStyle;
const SSLRichText({Key? key, required this.text, this.linkStyle}):super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SSLRichTextState();
}
}
class SSLRichTextState extends State<SSLRichText>{
late TextSpan textSpan;
@override
Widget build(BuildContext context) {
// TODO: implement build
return RichText(
text: textSpan
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
textSpan = parseText(widget.text);
}
@override
void didUpdateWidget(covariant SSLRichText oldWidget) {
// TODO: implement didUpdateWidget
//文本变化时重新识别,一定要记得同步变化
if (widget.text != oldWidget.text){
textSpan = parseText(widget.text);
}
super.didUpdateWidget(oldWidget);
}
TextSpan parseText(String text){
//正则解析字符串
RegExp reg = RegExp(r"((https|http|ftp|rtsp|mms)?://)[^\s]+");
List<TextSpan> textSpans = [];
int index = 0;
reg.allMatches(text).forEach((element) {
String c = text.substring(element.start, element.end);
debugPrint("get string $c\n");
if (element.start == index){
index = element.end;
}
if (element.start > index){
String d = text.substring(index + 1, element.start);
index = element.end;
//未识别字符串添加
textSpans.add(TextSpan(
text: d,
style: const TextStyle(color: Colors.red),
//TapGestureRecognizer() 相当于是创建了一个TapGestureRecognizer对象,然后给这个对象的onTap赋值
recognizer: TapGestureRecognizer()..onTap=(){
debugPrint("ssl chick text 2 $d");
},
)
);
}
//识别字符串添加
if (c.isNotEmpty){
textSpans.add(TextSpan(
text: c,
style: const TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()..onTap=(){
debugPrint("ssl chick text 1 $c");
},
)
);
}
});
//组装TextSpan
return TextSpan(children: textSpans);
}
}
使用示例:
class SSLRichTextTest extends StatefulWidget{
const SSLRichTextTest({Key? key}):super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SSLRichTextTestState();
}
}
class SSLRichTextTestState extends State<SSLRichTextTest>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: const Text("SSL Rich Text"),
),
//由于正则没有很到位,只能识别两个,但是效果还是出来了
body: const SSLRichText(text: "农家阿婆古代诗歌http://www.baidu.com,你还是个i说,https://www.wechat.com",),
);
}
}