Neda/call/lib/ui/widgets/level_meter.dart

88 lines
2.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
/// Vertical or horizontal audio level meter.
///
/// [level] is a normalised value 0.0 1.0.
/// Colour transitions green → amber → red above 0.7.
class LevelMeter extends StatelessWidget {
final double level;
final double width;
final double height;
final bool vertical;
const LevelMeter({
super.key,
required this.level,
this.width = 24,
this.height = 120,
this.vertical = true,
});
@override
Widget build(BuildContext context) {
final clamped = level.clamp(0.0, 1.0);
return SizedBox(
width: width,
height: height,
child: CustomPaint(
painter: _LevelPainter(level: clamped, vertical: vertical),
),
);
}
}
class _LevelPainter extends CustomPainter {
final double level;
final bool vertical;
const _LevelPainter({required this.level, required this.vertical});
@override
void paint(Canvas canvas, Size size) {
// Background.
canvas.drawRect(
Rect.fromLTWH(0, 0, size.width, size.height),
Paint()..color = const Color(0xFF1A1A2E),
);
// Filled bar.
final barColor = level < 0.6
? const Color(0xFF00C853) // green
: level < 0.8
? const Color(0xFFFFAB00) // amber
: const Color(0xFFD50000); // red
final paint = Paint()..color = barColor;
if (vertical) {
final fillH = size.height * level;
canvas.drawRect(
Rect.fromLTWH(0, size.height - fillH, size.width, fillH),
paint,
);
} else {
final fillW = size.width * level;
canvas.drawRect(
Rect.fromLTWH(0, 0, fillW, size.height),
paint,
);
}
// Tick marks at 25 %, 50 %, 75 %.
final tickPaint = Paint()
..color = Colors.white24
..strokeWidth = 1;
for (final frac in [0.25, 0.50, 0.75]) {
if (vertical) {
final y = size.height * (1.0 - frac);
canvas.drawLine(Offset(0, y), Offset(size.width, y), tickPaint);
} else {
final x = size.width * frac;
canvas.drawLine(Offset(x, 0), Offset(x, size.height), tickPaint);
}
}
}
@override
bool shouldRepaint(_LevelPainter old) => old.level != level;
}