123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import 'dart:math';
- import 'dart:ui';
- import 'dart:ui' as ui;
- import 'package:flutter/material.dart';
- import 'package:sport/widgets/circular_percent_indicator.dart';
- class RulerWidget extends StatefulWidget {
- final double initialIndex;
- RulerWidget({this.initialIndex = 60});
- @override
- State<StatefulWidget> createState() => _State();
- }
- class _State extends State<RulerWidget> with SingleTickerProviderStateMixin {
- double _x = 0;
- double _value = 0;
- AnimationController? _animationController;
- Animation? _animation;
- @override
- void initState() {
- super.initState();
- _value = widget.initialIndex;
- _animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 250))
- ..addStatusListener((status) {
- if (status == AnimationStatus.completed) {
- _notifyValue();
- }
- });
- }
- _notifyValue() {
- RulerValue(max(0, _value)).dispatch(context);
- }
- @override
- void dispose() {
- _animationController?.dispose();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- onHorizontalDragStart: (detail) {
- _x = detail.globalPosition.dx;
- },
- onHorizontalDragEnd: (detail) {
- if(_animationController == null)
- return;
- if (_value < 0.0) {
- _animation = Tween(begin: _value, end: 0.0).animate(
- _animationController!,
- )..addListener(() {
- setState(() {
- _value = _animation?.value ?? 0;
- });
- });
- _animationController!.forward(from: .0);
- }
- if (_value != _value.truncateToDouble()) {
- var old = _value * 1.0;
- var diff = _value - double.parse(_value.toStringAsFixed(1));
- _animation = Tween(begin: diff, end: .0).animate(
- _animationController!,
- )..addListener(() {
- setState(() {
- _value = old - diff - _animation?.value;
- });
- });
- _animationController!.forward(from: .0);
- }
- },
- onHorizontalDragUpdate: (detail) {
- _value = _value - (detail.globalPosition.dx - _x) / 50;
- _value = max(10, min(_value, 200));
- _x = detail.globalPosition.dx;
- setState(() {
- _notifyValue();
- });
- },
- child: CustomPaint(
- painter: _Painter(scrollLen: _value),
- child: Container(
- width: double.infinity,
- height: 280.0,)
- ),
- );
- }
- }
- class RulerValue extends Notification {
- final double value;
- RulerValue(this.value);
- }
- class _Painter extends CustomPainter {
- _Painter({required this.scrollLen});
- final double scrollLen;
- static const double _bgWidth = 100;
- var _bg = Paint()
- ..style = PaintingStyle.stroke
- ..color = const Color(0xfff2f2f2)
- ..strokeWidth = _bgWidth
- ..isAntiAlias = true;
- var _line = Paint()
- ..color = const Color(0xff6d6d6d)
- ..strokeWidth = 1
- ..isAntiAlias = true;
- final ParagraphStyle _labelStyle = ParagraphStyle(
- textAlign: TextAlign.center,
- fontWeight: FontWeight.w600,
- fontSize: 24,
- );
- final Paint _current = Paint()
- ..color = const Color(0xffFFC400)
- ..isAntiAlias = true;
- @override
- void paint(Canvas canvas, Size size) {
- canvas.save();
- canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height));
- var center = Offset(size.width / 2, size.width + 120);
- var cx = center.dx;
- var cy = center.dy;
- var radius = size.width;
- // radius = size.width / 2;
- canvas.drawArc(Rect.fromCircle(center: center, radius: radius), pi, pi, false, _bg);
- var dy = center.dy - radius - _bgWidth / 2;
- var unit = 2;
- double startAngle = scrollLen * 10 * unit;
- // startAngle = startAngle % 360;
- // print("scrollLen: $scrollLen, startAngle:$startAngle, toint: ${startAngle.floor()}, ${startAngle % 90}");
- // canvas.save();
- canvas.translate(cx, cy);
- canvas.rotate(radians(-startAngle - unit));
- canvas.translate(-cx, -cy);
- double angle = -startAngle;
- // print("angle: $angle");
- int index = 0;
- while (angle <= 90) {
- angle += unit;
- index++;
- canvas.translate(cx, cy);
- canvas.rotate(radians(unit));
- canvas.translate(-cx, -cy);
- if (angle < -90) continue;
- bool scale = (index - 1) % 10 == 0;
- // print("angle: $angle, scale: $scale == ${ angle % 20}");
- canvas.drawLine(Offset(cx, dy), Offset(cx, dy + (scale ? 38.0 : 20.0)), _line);
- if (scale) {
- ParagraphBuilder pb = ParagraphBuilder(_labelStyle)
- ..pushStyle(ui.TextStyle(color: const Color(0xff515151)))
- ..addText("${(angle + startAngle) ~/ 20}");
- ParagraphConstraints constraints = ParagraphConstraints(width: 50);
- Paragraph paragraph = pb.build()..layout(constraints);
- paragraph.computeLineMetrics().forEach((element) {
- canvas.drawParagraph(paragraph, Offset(cx - 25, dy + 40.0));
- });
- }
- }
- canvas.restore();
- canvas.drawPath(
- Path()
- ..moveTo(cx, dy + 8)
- ..lineTo(cx - 8, dy - 14)
- ..lineTo(cx + 8, dy - 14)
- ..close(),
- _current);
- }
- @override
- bool shouldRepaint(_Painter oldDelegate) => oldDelegate.scrollLen != scrollLen;
- }
|