mirror of
https://github.com/krille-chan/fluffychat
synced 2024-10-05 15:12:44 +00:00
refactor: new flutter only typing animation
This commit is contained in:
parent
4fca106a51
commit
a8606f18b6
3 changed files with 67 additions and 88 deletions
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
|
@ -1,80 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
width="64"
|
|
||||||
height="30"
|
|
||||||
viewBox="0 0 64 30"
|
|
||||||
version="1.1"
|
|
||||||
id="svg8"
|
|
||||||
sodipodi:docname="typing.svg"
|
|
||||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs12" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview10"
|
|
||||||
pagecolor="#505050"
|
|
||||||
bordercolor="#eeeeee"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:showpageshadow="0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#505050"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="9.9296875"
|
|
||||||
inkscape:cx="24.018883"
|
|
||||||
inkscape:cy="15.307632"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1012"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg8" />
|
|
||||||
<circle
|
|
||||||
style="fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:normal"
|
|
||||||
cx="10"
|
|
||||||
cy="15"
|
|
||||||
r="9"
|
|
||||||
id="circle2">
|
|
||||||
<animate
|
|
||||||
attributeName="fill"
|
|
||||||
dur="2s"
|
|
||||||
values="#000000; #efefef; #000000"
|
|
||||||
calcMode="spline"
|
|
||||||
keyTimes="0; 0.5; 1"
|
|
||||||
keySplines="0 .75 .25 1; .5 0 .5 1"
|
|
||||||
begin="0s" />
|
|
||||||
</circle>
|
|
||||||
<circle
|
|
||||||
style="fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:normal"
|
|
||||||
cx="32"
|
|
||||||
cy="15"
|
|
||||||
r="9"
|
|
||||||
id="circle4">
|
|
||||||
<animate
|
|
||||||
attributeName="fill"
|
|
||||||
dur="2s"
|
|
||||||
values="#000000; #efefef; #000000"
|
|
||||||
calcMode="spline"
|
|
||||||
keyTimes="0; 0.5; 1"
|
|
||||||
keySplines="0 .75 .25 1; .5 0 .5 1"
|
|
||||||
begin="0.25s" />
|
|
||||||
</circle>
|
|
||||||
<circle
|
|
||||||
style="fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:normal"
|
|
||||||
cx="54"
|
|
||||||
cy="15"
|
|
||||||
r="9"
|
|
||||||
id="circle6">
|
|
||||||
<animate
|
|
||||||
attributeName="fill"
|
|
||||||
dur="2s"
|
|
||||||
values="#000000; #efefef; #000000"
|
|
||||||
calcMode="spline"
|
|
||||||
keyTimes="0; 0.5; 1"
|
|
||||||
keySplines="0 .75 .25 1; .5 0 .5 1"
|
|
||||||
begin="0.5s" />
|
|
||||||
</circle>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
|
@ -78,14 +80,8 @@ class TypingIndicators extends StatelessWidget {
|
||||||
bottomRight: Radius.circular(AppConfig.borderRadius),
|
bottomRight: Radius.circular(AppConfig.borderRadius),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: typingUsers.isEmpty
|
child: typingUsers.isEmpty ? null : const _TypingDots(),
|
||||||
? null
|
|
||||||
: Image.asset(
|
|
||||||
'assets/typing.gif',
|
|
||||||
height: 30,
|
|
||||||
filterQuality: FilterQuality.high,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -95,3 +91,66 @@ class TypingIndicators extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _TypingDots extends StatefulWidget {
|
||||||
|
const _TypingDots();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_TypingDots> createState() => __TypingDotsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __TypingDotsState extends State<_TypingDots> {
|
||||||
|
int _tick = 0;
|
||||||
|
|
||||||
|
late final Timer _timer;
|
||||||
|
|
||||||
|
static const Duration animationDuration = Duration(milliseconds: 300);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_timer = Timer.periodic(
|
||||||
|
animationDuration,
|
||||||
|
(_) {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_tick = (_tick + 1) % 4;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const size = 8.0;
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
for (var i = 1; i <= 3; i++)
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: animationDuration * 1.5,
|
||||||
|
curve: FluffyThemes.animationCurve,
|
||||||
|
width: size,
|
||||||
|
height: _tick == i ? size * 2 : size,
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: 2,
|
||||||
|
vertical: _tick == i ? 4 : 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(size * 2),
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue