* 修复 UUID 创建失败的问题 * 移除 scanning 属性 * 临时提交 * CentralManager 开发 & 示例项目开发 * CentralManager 开发 & 示例项目开发 * android 插件生命周期监听 * 修改 API * 示例程序开发 * 修改字体,添加 API,解决后台问题 * Central#connect API * 蓝牙连接部分开发 * 蓝牙连接部分开发 * 解决一些问题 * 解决一些问题 * Connect API 优化 * 添加 API * example 开发 * API 基本完成 * 消息重命名 * API 修改,Android 实现 * 删除多余代码 * 删除多余文件 * 解决 descriptor 自动生成报错的问题 * 还原 Kotlin 版本,广播处理代码迁移至 dart 端 * Kotlin 版本升至 1.5.20 * 解决特征值通知没有在主线程触发的问题,优化代码 * 引入哈希值,避免对象销毁后继续使用 * 使用下拉刷新代替搜索按钮 * 解决由于热重载和蓝牙关闭产生的问题 * 更新插件信息 * 更新 README 和 CHANGELOG * 更新许可证 * 添加注释 * 添加注释,central 拆分
107 lines
2.8 KiB
Dart
107 lines
2.8 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
class FlipCard extends StatefulWidget {
|
|
final Widget? front;
|
|
final Widget? back;
|
|
const FlipCard({
|
|
Key? key,
|
|
@required this.front,
|
|
@required this.back,
|
|
}) : assert(front != null),
|
|
assert(back != null),
|
|
super(key: key);
|
|
|
|
@override
|
|
_FlipCardState createState() => _FlipCardState();
|
|
}
|
|
|
|
class _FlipCardState extends State<FlipCard> with TickerProviderStateMixin {
|
|
final ValueNotifier<double> angle;
|
|
late AnimationController animationController;
|
|
late Animation<double> frontAnimation;
|
|
late Animation<double> backAnimation;
|
|
|
|
_FlipCardState() : angle = ValueNotifier(0.0);
|
|
|
|
bool isFront = true;
|
|
bool hasHalf = false;
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
animationController = AnimationController(
|
|
vsync: this,
|
|
duration: Duration(milliseconds: 1000),
|
|
);
|
|
animationController.addListener(() {
|
|
if (animationController.value > 0.5) {
|
|
if (hasHalf == false) {
|
|
isFront = !isFront;
|
|
}
|
|
hasHalf = true;
|
|
}
|
|
setState(() {});
|
|
});
|
|
animationController.addStatusListener((status) {
|
|
if (status == AnimationStatus.completed) {
|
|
hasHalf = false;
|
|
}
|
|
});
|
|
frontAnimation = Tween(begin: 0.0, end: 0.5).animate(
|
|
CurvedAnimation(
|
|
parent: animationController,
|
|
curve: Interval(0.0, 0.5, curve: Curves.easeIn),
|
|
),
|
|
);
|
|
backAnimation = Tween(begin: 1.5, end: 2.0).animate(CurvedAnimation(
|
|
parent: animationController,
|
|
curve: Interval(0.5, 1.0, curve: Curves.easeOut)));
|
|
}
|
|
|
|
void animate() {
|
|
animationController.stop();
|
|
animationController.value = 0;
|
|
animationController.forward();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
animationController.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (animationController.status == AnimationStatus.forward) {
|
|
if (hasHalf == true) {
|
|
angle.value = backAnimation.value;
|
|
} else {
|
|
angle.value = frontAnimation.value;
|
|
}
|
|
}
|
|
return GestureDetector(
|
|
onHorizontalDragUpdate: (details) {
|
|
print(details.delta);
|
|
angle.value += 0.01;
|
|
},
|
|
child: Container(
|
|
child: ValueListenableBuilder(
|
|
valueListenable: angle,
|
|
builder: (BuildContext context, double angle, Widget? child) {
|
|
return Transform(
|
|
transform: Matrix4.identity()
|
|
..setEntry(3, 2, 0.001)
|
|
..rotateY(angle),
|
|
alignment: Alignment.center,
|
|
child: IndexedStack(
|
|
index: isFront ? 0 : 1,
|
|
children: <Widget>[widget.front!, widget.back!],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|