tsacdop-podcast-app-android/lib/util/custom_widget.dart

1084 lines
29 KiB
Dart
Raw Normal View History

2020-04-11 19:23:12 +02:00
import 'dart:io';
import 'dart:math' as math;
2020-07-26 12:20:42 +02:00
import 'dart:ui' as ui;
2020-04-11 19:23:12 +02:00
import 'package:flutter/material.dart';
2020-07-26 12:20:42 +02:00
import 'episodegrid.dart';
2020-07-24 16:10:08 +02:00
import 'extension_helper.dart';
2020-04-11 19:23:12 +02:00
//Layout change indicator
class LayoutPainter extends CustomPainter {
double scale;
Color color;
LayoutPainter(this.scale, this.color);
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
2020-04-11 19:23:12 +02:00
..color = color
..strokeWidth = 1.0
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
canvas.drawRect(Rect.fromLTRB(0, 0, 10 + 5 * scale, 10), _paint);
if (scale < 4) {
canvas.drawRect(
Rect.fromLTRB(10 + 5 * scale, 0, 20 + 10 * scale, 10), _paint);
canvas.drawRect(
Rect.fromLTRB(20 + 5 * scale, 0, 30, 10 - 10 * scale), _paint);
}
2020-04-11 19:23:12 +02:00
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
//Dark sky used in sleep timer
class StarSky extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final points = [
Offset(50, 100),
Offset(150, 75),
Offset(250, 250),
Offset(130, 200),
Offset(270, 150),
];
final pisces = [
Offset(9, 4),
Offset(11, 5),
Offset(7, 6),
Offset(10, 7),
Offset(8, 8),
Offset(9, 13),
Offset(12, 17),
Offset(5, 19),
Offset(7, 19)
].map((e) => e * 10).toList();
final orion = [
Offset(3, 1),
Offset(6, 1),
Offset(1, 4),
Offset(2, 4),
Offset(2, 7),
Offset(10, 8),
Offset(3, 10),
Offset(8, 10),
Offset(19, 11),
Offset(11, 13),
Offset(18, 14),
Offset(5, 19),
Offset(7, 19),
Offset(9, 18),
Offset(15, 19),
Offset(16, 18),
Offset(2, 25),
Offset(10, 26)
].map((e) => Offset(e.dx * 10 + 250, e.dy * 10)).toList();
2020-07-26 12:20:42 +02:00
var paint = Paint()
2020-04-11 19:23:12 +02:00
..color = Colors.white
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
canvas.drawPoints(ui.PointMode.points, pisces, paint);
canvas.drawPoints(ui.PointMode.points, points, paint);
canvas.drawPoints(ui.PointMode.points, orion, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
//Listened indicator
class ListenedPainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final Color _color;
2020-04-11 19:23:12 +02:00
double stroke;
2020-04-18 07:27:43 +02:00
ListenedPainter(this._color, {this.stroke = 1.0});
2020-04-11 19:23:12 +02:00
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
2020-04-11 19:23:12 +02:00
..color = _color
..strokeWidth = stroke
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _path = Path();
2020-04-11 19:23:12 +02:00
_path.moveTo(size.width / 6, size.height * 3 / 8);
_path.lineTo(size.width / 6, size.height * 5 / 8);
_path.moveTo(size.width / 3, size.height / 4);
_path.lineTo(size.width / 3, size.height * 3 / 4);
_path.moveTo(size.width / 2, size.height / 8);
_path.lineTo(size.width / 2, size.height * 7 / 8);
_path.moveTo(size.width * 5 / 6, size.height * 3 / 8);
_path.lineTo(size.width * 5 / 6, size.height * 5 / 8);
_path.moveTo(size.width * 2 / 3, size.height / 4);
_path.lineTo(size.width * 2 / 3, size.height * 3 / 4);
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
2020-04-18 07:27:43 +02:00
//Listened Completely indicator
class ListenedAllPainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final Color color;
final double stroke;
ListenedAllPainter(this.color, {this.stroke = 1.0});
2020-04-18 07:27:43 +02:00
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
..color = color
2020-04-18 07:27:43 +02:00
..strokeWidth = stroke
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _path = Path();
2020-04-18 07:27:43 +02:00
_path.moveTo(size.width / 6, size.height * 3 / 8);
_path.lineTo(size.width / 6, size.height * 5 / 8);
_path.moveTo(size.width / 3, size.height / 4);
_path.lineTo(size.width / 3, size.height * 3 / 4);
_path.moveTo(size.width / 2, size.height * 3 / 8);
_path.lineTo(size.width / 2, size.height * 5 / 8);
_path.moveTo(size.width * 2 / 3, size.height * 4 / 9);
_path.lineTo(size.width * 2 / 3, size.height * 5 / 9);
_path.moveTo(size.width / 2, size.height * 3 / 4);
_path.lineTo(size.width * 2 / 3, size.height * 7 / 8);
_path.lineTo(size.width * 7 / 8, size.height * 5 / 8);
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
2020-06-06 06:51:34 +02:00
//Mark Listened indicator
class MarkListenedPainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final Color color;
2020-06-06 06:51:34 +02:00
double stroke;
2020-07-26 12:20:42 +02:00
MarkListenedPainter(this.color, {this.stroke = 1.0});
2020-06-06 06:51:34 +02:00
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
..color = color
2020-06-06 06:51:34 +02:00
..strokeWidth = stroke
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _path = Path();
2020-06-06 06:51:34 +02:00
_path.moveTo(size.width / 6, size.height * 3 / 8);
_path.lineTo(size.width / 6, size.height * 5 / 8);
_path.moveTo(size.width / 3, size.height / 4);
_path.lineTo(size.width / 3, size.height * 3 / 4);
_path.moveTo(size.width / 2, size.height * 3 / 8);
_path.lineTo(size.width / 2, size.height * 5 / 8);
2020-07-24 16:10:08 +02:00
// _path.moveTo(size.width * 2 / 3, size.height * 4 / 9);
// _path.lineTo(size.width * 2 / 3, size.height * 5 / 9);
2020-06-06 06:51:34 +02:00
_path.moveTo(size.width / 2, size.height * 13 / 18);
_path.lineTo(size.width * 5 / 6, size.height * 13 / 18);
_path.moveTo(size.width * 2 / 3, size.height * 5 / 9);
_path.lineTo(size.width * 2 / 3, size.height * 8 / 9);
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
2020-07-24 16:10:08 +02:00
/// Hide listened painter.
class HideListenedPainter extends CustomPainter {
Color color;
Color backgroundColor;
double fraction;
double stroke;
HideListenedPainter(
{this.color, this.stroke = 1.0, this.backgroundColor, this.fraction});
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
2020-07-24 16:10:08 +02:00
..color = color
..strokeWidth = stroke
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _linePaint = Paint()
2020-07-24 16:10:08 +02:00
..color = backgroundColor
..strokeWidth = stroke * 2
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _path = Path();
2020-07-24 16:10:08 +02:00
_path.moveTo(size.width / 6, size.height * 3 / 8);
_path.lineTo(size.width / 6, size.height * 5 / 8);
_path.moveTo(size.width / 3, size.height / 4);
_path.lineTo(size.width / 3, size.height * 3 / 4);
_path.moveTo(size.width / 2, size.height / 8);
_path.lineTo(size.width / 2, size.height * 7 / 8);
_path.moveTo(size.width * 5 / 6, size.height * 3 / 8);
_path.lineTo(size.width * 5 / 6, size.height * 5 / 8);
_path.moveTo(size.width * 2 / 3, size.height / 4);
_path.lineTo(size.width * 2 / 3, size.height * 3 / 4);
canvas.drawPath(_path, _paint);
2020-07-26 12:20:42 +02:00
if (fraction > 0) {
2020-07-24 16:10:08 +02:00
canvas.drawLine(
Offset(size.width, size.height) / 5,
Offset(size.width, size.height) / 5 +
Offset(size.width, size.height) * 3 / 5 * fraction,
_linePaint);
2020-07-26 12:20:42 +02:00
}
2020-07-24 16:10:08 +02:00
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class HideListened extends StatefulWidget {
final bool hideListened;
HideListened({this.hideListened, Key key}) : super(key: key);
@override
_HideListenedState createState() => _HideListenedState();
}
class _HideListenedState extends State<HideListened>
with SingleTickerProviderStateMixin {
double _fraction = 0.0;
Animation animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 400));
animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
2020-07-24 16:10:08 +02:00
setState(() {
_fraction = animation.value;
});
2020-07-26 12:20:42 +02:00
}
2020-07-24 16:10:08 +02:00
});
if (widget.hideListened) _controller.forward();
}
@override
void didUpdateWidget(HideListened oldWidget) {
if (oldWidget.hideListened != widget.hideListened) {
2020-07-26 12:20:42 +02:00
if (widget.hideListened) {
2020-07-24 16:10:08 +02:00
_controller.forward();
2020-07-26 12:20:42 +02:00
} else {
2020-07-24 16:10:08 +02:00
_controller.reverse();
2020-07-26 12:20:42 +02:00
}
2020-07-24 16:10:08 +02:00
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: HideListenedPainter(
fraction: _fraction,
color: context.textColor,
backgroundColor: context.accentColor));
}
}
//Add new episode to palylist
class AddToPlaylistPainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final Color color;
final Color textColor;
AddToPlaylistPainter(this.color, this.textColor);
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _paint = Paint()
..color = color
..strokeWidth = 1
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
2020-07-26 12:20:42 +02:00
var _path = Path();
_path.moveTo(0, 0);
_path.lineTo(size.width * 4 / 7, 0);
_path.moveTo(0, size.height / 3);
_path.lineTo(size.width * 4 / 7, size.height / 3);
_path.moveTo(0, size.height * 2 / 3);
_path.lineTo(size.width * 3 / 7, size.height * 2 / 3);
//_path.moveTo(size.width * 3 / 7, size.height * 2 / 3);
//_path.lineTo(size.width, size.height * 2 / 3);
//_path.moveTo(size.width * 5 / 7, size.height / 3);
//_path.lineTo(size.width * 5 / 7, size.height);
// _path.moveTo(size.width*5/7, size.height/4);
// _path.lineTo(size.width*11/14, 0);
// _path.lineTo(size.width*13/14, size.height/4);
// _path.lineTo(size.width, 0);
var textPainter = TextPainter(
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
text: TextSpan(
text: 'N',
style: TextStyle(
2020-07-26 12:20:42 +02:00
fontStyle: FontStyle.italic, color: textColor, fontSize: 10),
))
..layout();
textPainter.paint(canvas, Offset(size.width * 4 / 7, size.height / 3));
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
2020-04-11 19:23:12 +02:00
//Wave play indicator
class WavePainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final double _fraction;
2020-04-11 19:23:12 +02:00
double _value;
2020-07-26 12:20:42 +02:00
final Color _color;
2020-04-11 19:23:12 +02:00
WavePainter(this._fraction, this._color);
@override
void paint(Canvas canvas, Size size) {
if (_fraction < 0.5) {
_value = _fraction;
} else {
_value = 1 - _fraction;
}
2020-07-26 12:20:42 +02:00
var _path = Path();
var _paint = Paint()
2020-04-11 19:23:12 +02:00
..color = _color
..strokeWidth = 2.0
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
_path.moveTo(0, size.height / 2);
_path.lineTo(0, size.height / 2 + size.height * _value * 0.2);
_path.moveTo(0, size.height / 2);
_path.lineTo(0, size.height / 2 - size.height * _value * 0.2);
_path.moveTo(size.width / 4, size.height / 2);
_path.lineTo(size.width / 4, size.height / 2 + size.height * _value * 0.8);
_path.moveTo(size.width / 4, size.height / 2);
_path.lineTo(size.width / 4, size.height / 2 - size.height * _value * 0.8);
_path.moveTo(size.width / 2, size.height / 2);
_path.lineTo(size.width / 2, size.height / 2 + size.height * _value * 0.5);
_path.moveTo(size.width / 2, size.height / 2);
_path.lineTo(size.width / 2, size.height / 2 - size.height * _value * 0.5);
_path.moveTo(size.width * 3 / 4, size.height / 2);
_path.lineTo(
size.width * 3 / 4, size.height / 2 + size.height * _value * 0.6);
_path.moveTo(size.width * 3 / 4, size.height / 2);
_path.lineTo(
size.width * 3 / 4, size.height / 2 - size.height * _value * 0.6);
_path.moveTo(size.width, size.height / 2);
_path.lineTo(size.width, size.height / 2 + size.height * _value * 0.2);
_path.moveTo(size.width, size.height / 2);
_path.lineTo(size.width, size.height / 2 - size.height * _value * 0.2);
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(WavePainter oldDelegate) {
return oldDelegate._fraction != _fraction;
}
}
class WaveLoader extends StatefulWidget {
final Color color;
WaveLoader({this.color, Key key}) : super(key: key);
@override
_WaveLoaderState createState() => _WaveLoaderState();
}
class _WaveLoaderState extends State<WaveLoader>
with SingleTickerProviderStateMixin {
double _fraction = 0.0;
Animation animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, duration: Duration(milliseconds: 1000));
animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
2020-04-11 19:23:12 +02:00
setState(() {
_fraction = animation.value;
});
2020-07-26 12:20:42 +02:00
}
2020-04-11 19:23:12 +02:00
});
_controller.forward();
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: WavePainter(_fraction, widget.color ?? Colors.white));
}
}
//Love shape
class LovePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
2020-07-26 12:20:42 +02:00
var _path = Path();
var _paint = Paint()
2020-04-11 19:23:12 +02:00
..color = Colors.red
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
_path.moveTo(size.width / 2, size.height / 6);
_path.quadraticBezierTo(size.width / 4, 0, size.width / 8, size.height / 6);
_path.quadraticBezierTo(
0, size.height / 3, size.width / 8, size.height * 0.55);
_path.quadraticBezierTo(
size.width / 4, size.height * 0.8, size.width / 2, size.height);
_path.quadraticBezierTo(size.width * 0.75, size.height * 0.8,
size.width * 7 / 8, size.height * 0.55);
_path.quadraticBezierTo(
size.width, size.height / 3, size.width * 7 / 8, size.height / 6);
_path.quadraticBezierTo(
size.width * 3 / 4, 0, size.width / 2, size.height / 6);
canvas.drawPath(_path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
//Line buffer indicator
//Not used
class LinePainter extends CustomPainter {
2020-07-26 12:20:42 +02:00
final double _fraction;
2020-04-11 19:23:12 +02:00
Paint _paint;
2020-07-26 12:20:42 +02:00
final Color _maincolor;
2020-04-11 19:23:12 +02:00
LinePainter(this._fraction, this._maincolor) {
_paint = Paint()
..color = _maincolor
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
}
@override
void paint(Canvas canvas, Size size) {
canvas.drawLine(Offset(0, size.height / 2.0),
Offset(size.width * _fraction, size.height / 2.0), _paint);
}
@override
bool shouldRepaint(LinePainter oldDelegate) {
return oldDelegate._fraction != _fraction;
}
}
class LineLoader extends StatefulWidget {
@override
_LineLoaderState createState() => _LineLoaderState();
}
class _LineLoaderState extends State<LineLoader>
with SingleTickerProviderStateMixin {
double _fraction = 0.0;
Animation animation;
AnimationController controller;
@override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 500));
animation = Tween(begin: 0.0, end: 1.0).animate(controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
2020-04-11 19:23:12 +02:00
setState(() {
_fraction = animation.value;
});
2020-07-26 12:20:42 +02:00
}
2020-04-11 19:23:12 +02:00
});
controller.forward();
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reset();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: LinePainter(_fraction, Theme.of(context).accentColor));
}
}
class ImageRotate extends StatefulWidget {
final String title;
final String path;
ImageRotate({this.title, this.path, Key key}) : super(key: key);
@override
_ImageRotateState createState() => _ImageRotateState();
}
class _ImageRotateState extends State<ImageRotate>
with SingleTickerProviderStateMixin {
Animation _animation;
AnimationController _controller;
double _value;
@override
void initState() {
super.initState();
_value = 0;
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 2000),
);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
2020-04-11 19:23:12 +02:00
setState(() {
_value = _animation.value;
});
2020-07-26 12:20:42 +02:00
}
2020-04-11 19:23:12 +02:00
});
_controller.forward();
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Transform.rotate(
angle: 2 * math.pi * _value,
child: Container(
padding: EdgeInsets.all(10.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
child: Container(
height: 30.0,
width: 30.0,
color: Colors.white,
child: Image.file(File("${widget.path}")),
),
),
),
);
}
}
class LoveOpen extends StatefulWidget {
@override
_LoveOpenState createState() => _LoveOpenState();
}
class _LoveOpenState extends State<LoveOpen>
with SingleTickerProviderStateMixin {
Animation _animationA;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 1000),
2020-04-11 19:23:12 +02:00
);
_animationA = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
if (mounted) setState(() {});
});
_controller.forward();
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Widget _littleHeart(double scale, double value, double angle) => Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: value),
child: ScaleTransition(
scale: _animationA,
alignment: Alignment.center,
child: Transform.rotate(
angle: angle,
child: SizedBox(
height: 5 * scale,
width: 6 * scale,
child: CustomPaint(
painter: LovePainter(),
),
),
),
),
);
@override
Widget build(BuildContext context) {
return Container(
width: 50,
height: 50,
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
children: <Widget>[
_littleHeart(0.5, 10, -math.pi / 6),
_littleHeart(1.2, 3, 0),
],
),
Row(
children: <Widget>[
_littleHeart(0.8, 6, math.pi * 1.5),
_littleHeart(0.9, 24, math.pi / 2),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_littleHeart(1, 8, -math.pi * 0.7),
_littleHeart(0.8, 8, math.pi),
_littleHeart(0.6, 3, -math.pi * 1.2)
],
),
],
),
);
}
}
//Heart rise
class HeartSet extends StatefulWidget {
final double height;
final double width;
HeartSet({Key key, this.height, this.width}) : super(key: key);
@override
_HeartSetState createState() => _HeartSetState();
}
class _HeartSetState extends State<HeartSet>
with SingleTickerProviderStateMixin {
Animation _animation;
AnimationController _controller;
double _value;
@override
void initState() {
super.initState();
_value = 0;
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
setState(() {
_value = _animation.value;
});
2020-07-26 12:20:42 +02:00
}
});
_controller.forward();
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
height: widget.height,
width: widget.width,
alignment: Alignment(0.5, 1 - _value),
child: Icon(Icons.favorite,
color: Colors.blue.withOpacity(0.7), size: 20 * _value),
);
}
}
class HeartOpen extends StatefulWidget {
final double height;
final double width;
HeartOpen({Key key, this.height, this.width}) : super(key: key);
@override
_HeartOpenState createState() => _HeartOpenState();
}
class _HeartOpenState extends State<HeartOpen>
with SingleTickerProviderStateMixin {
Animation _animation;
AnimationController _controller;
double _value;
@override
void initState() {
super.initState();
_value = 0;
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
2020-07-26 12:20:42 +02:00
if (mounted) {
setState(() {
_value = _animation.value;
});
2020-07-26 12:20:42 +02:00
}
});
_controller.forward();
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Widget _position(int i) {
2020-07-26 12:20:42 +02:00
var scale = _list[i];
var position = _list[i + 1];
return Positioned(
left: widget.width * position,
bottom: widget.height * _value * scale,
child: Icon(Icons.favorite,
color: _value > 0.5
? Colors.red.withOpacity(2 - _value * 2)
: Colors.red,
size: 20 * _value * scale),
);
}
2020-07-26 12:20:42 +02:00
final List<double> _list =
List<double>.generate(20, (index) => math.Random().nextDouble());
2020-07-26 12:20:42 +02:00
final List<int> _index = List<int>.generate(19, (index) => index);
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
height: widget.height,
width: widget.width,
alignment: Alignment(0.5, 1 - _value),
child: Icon(Icons.favorite,
color: Colors.blue.withOpacity(0.7), size: 20 * _value),
),
2020-07-26 12:20:42 +02:00
..._index.map<Widget>(_position).toList(),
],
);
}
}
2020-07-24 16:10:08 +02:00
/// Icon using a painter.
2020-07-24 16:10:08 +02:00
class IconPainter extends StatelessWidget {
const IconPainter(this.painter, {this.height = 10, this.width = 30, Key key})
: super(key: key);
final double height;
final double width;
final CustomPainter painter;
@override
Widget build(BuildContext context) {
return SizedBox(
height: height,
width: width,
child: CustomPaint(
painter: painter,
),
);
}
}
/// A dot just a dot.
2020-07-24 16:10:08 +02:00
class DotIndicator extends StatelessWidget {
DotIndicator({this.radius = 8, Key key})
: assert(radius > 0),
super(key: key);
final double radius;
@override
Widget build(BuildContext context) {
return Container(
width: radius,
height: radius,
decoration:
BoxDecoration(shape: BoxShape.circle, color: context.accentColor));
}
}
class DownloadPainter extends CustomPainter {
double fraction;
Color color;
Color progressColor;
double progress;
double pauseProgress;
DownloadPainter(
{this.fraction,
this.color,
this.progressColor,
this.progress = 0,
this.pauseProgress = 0});
@override
void paint(Canvas canvas, Size size) {
var _paint = Paint()
..color = color
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
var _circlePaint = Paint()
..color = color.withAlpha(70)
..style = PaintingStyle.stroke
..strokeWidth = 2;
var _progressPaint = Paint()
..color = progressColor
..style = PaintingStyle.stroke
..strokeWidth = 2;
2020-07-26 12:20:42 +02:00
var width = size.width;
var height = size.height;
var center = Offset(size.width / 2, size.height / 2);
if (pauseProgress == 0) {
canvas.drawLine(
Offset(width / 2, 0), Offset(width / 2, height * 4 / 5), _paint);
canvas.drawLine(Offset(width / 5, height / 2),
Offset(width / 2, height * 4 / 5), _paint);
canvas.drawLine(Offset(width * 4 / 5, height / 2),
Offset(width / 2, height * 4 / 5), _paint);
}
2020-07-26 12:20:42 +02:00
if (fraction == 0) {
canvas.drawLine(
Offset(width / 5, height), Offset(width * 4 / 5, height), _paint);
2020-07-26 12:20:42 +02:00
} else {
canvas.drawArc(Rect.fromCircle(center: center, radius: width / 2),
math.pi / 2, math.pi * fraction, false, _circlePaint);
canvas.drawArc(Rect.fromCircle(center: center, radius: width / 2),
math.pi / 2, -math.pi * fraction, false, _circlePaint);
}
if (fraction == 1) {
canvas.drawArc(Rect.fromCircle(center: center, radius: width / 2),
-math.pi / 2, math.pi * 2 * progress, false, _progressPaint);
}
if (pauseProgress > 0) {
canvas.drawLine(
Offset(width / 5 + height * 3 * pauseProgress / 20,
height / 2 - height * 3 * pauseProgress / 10),
Offset(width / 2 - height * 3 * pauseProgress / 20, height * 4 / 5),
_paint);
canvas.drawLine(
Offset(width * 4 / 5 - height * 3 * pauseProgress / 20,
height / 2 - height * 3 * pauseProgress / 10),
Offset(width / 2 + height * 3 * pauseProgress / 20, height * 4 / 5),
_paint);
}
}
@override
bool shouldRepaint(DownloadPainter oldDelegate) {
return oldDelegate.fraction != fraction ||
oldDelegate.progress != progress ||
oldDelegate.pauseProgress != pauseProgress;
}
}
2020-07-26 12:20:42 +02:00
/// Layout icon button.
class LayoutButton extends StatelessWidget {
const LayoutButton({this.layout, this.onPressed, Key key}) : super(key: key);
final Layout layout;
final ValueChanged<Layout> onPressed;
@override
Widget build(BuildContext context) {
return IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (layout == Layout.three) {
onPressed(Layout.one);
} else if (layout == Layout.two) {
onPressed(Layout.three);
} else {
onPressed(Layout.two);
}
},
icon: layout == Layout.three
? SizedBox(
height: 10,
width: 30,
child: CustomPaint(
painter: LayoutPainter(0, context.textTheme.bodyText1.color),
),
)
: layout == Layout.two
? SizedBox(
height: 10,
width: 30,
child: CustomPaint(
painter:
LayoutPainter(1, context.textTheme.bodyText1.color),
),
)
: SizedBox(
height: 10,
width: 30,
child: CustomPaint(
painter:
LayoutPainter(4, context.textTheme.bodyText1.color),
),
),
);
}
}
2020-07-29 14:06:49 +02:00
/// Remove scroll view overlay effect.
class NoGrowBehavior extends ScrollBehavior {
@override
Widget buildViewportChrome(
BuildContext context, Widget child, AxisDirection axisDirection) {
return child;
}
}
class Meteor extends CustomPainter {
Paint _paint;
Meteor() {
_paint = Paint()
..color = Colors.white
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
}
@override
void paint(Canvas canvas, Size size) {
canvas.drawLine(Offset(0, 0), Offset(size.width, size.height), _paint);
}
@override
bool shouldRepaint(Meteor oldDelegate) {
return false;
}
}
/// Used in sleep mode widget.
class MeteorLoader extends StatefulWidget {
@override
_MeteorLoaderState createState() => _MeteorLoaderState();
}
class _MeteorLoaderState extends State<MeteorLoader>
with SingleTickerProviderStateMixin {
double _fraction = 0.0;
double _move = 0.0;
Animation animation;
AnimationController controller;
@override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 500));
animation = Tween(begin: 0.0, end: 1.0).animate(controller)
..addListener(() {
if (mounted) {
setState(() {
_move = animation.value;
if (animation.value <= 0.5) {
_fraction = animation.value * 2;
} else {
_fraction = 2 - (animation.value) * 2;
}
});
}
});
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Positioned(
top: 300 * _move + 10,
left: 150 * _move + 50,
child: SizedBox(
width: 50 * _fraction,
height: 100 * _fraction,
child: CustomPaint(painter: Meteor())),
);
}
}