mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
fix: change the template selection to use light and dark checkmark
This commit is contained in:
parent
6cc3becd99
commit
93fc1d1fbc
2 changed files with 98 additions and 25 deletions
|
@ -144,6 +144,8 @@ class AvailabilityColors {
|
|||
this.textDarkColor,
|
||||
this.textLightColor,
|
||||
this.templateWeekOverviewBackgroundColor,
|
||||
this.templateColorLightCheckmarkColor,
|
||||
this.templateColorDarkCheckmarkColor,
|
||||
this.templateColors = const [
|
||||
Color(0xFF9bb8f2),
|
||||
Color(0xFF4b77d0),
|
||||
|
@ -179,6 +181,14 @@ class AvailabilityColors {
|
|||
/// If not provided the text color will be the theme's text color
|
||||
final Color? textDarkColor;
|
||||
|
||||
/// The light color variant of the checkmark icon when selecting a color for
|
||||
/// a template
|
||||
final Color? templateColorLightCheckmarkColor;
|
||||
|
||||
/// The dark color variant of the checkmark icon when selecting a color for
|
||||
/// a template
|
||||
final Color? templateColorDarkCheckmarkColor;
|
||||
|
||||
/// The color of the background in the template week overview that creates a
|
||||
/// layered effect by interchanging a color and a transparent color
|
||||
/// If not provided the color will be the theme's [ColorScheme.surface]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:math";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
|
||||
|
@ -38,35 +40,96 @@ class TemplateColorSelection extends StatelessWidget {
|
|||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
for (var color in colors.templateColors)
|
||||
GestureDetector(
|
||||
onTap: () => _onColorClick(color),
|
||||
for (var color in colors.templateColors) ...[
|
||||
_TemplateColorItem(
|
||||
color: color,
|
||||
selectedColor: selectedColor,
|
||||
onColorSelected: onColorSelected,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TemplateColorItem extends StatelessWidget {
|
||||
const _TemplateColorItem({
|
||||
required this.color,
|
||||
required this.selectedColor,
|
||||
required this.onColorSelected,
|
||||
});
|
||||
|
||||
/// Callback for when a color is selected or deselected
|
||||
final void Function(int?) onColorSelected;
|
||||
|
||||
final Color color;
|
||||
|
||||
final int? selectedColor;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var availabilityScope = AvailabilityScope.of(context);
|
||||
var options = availabilityScope.options;
|
||||
var colors = options.colors;
|
||||
|
||||
/// If the color is selected, deselect it, otherwise select it
|
||||
void onColorClick(Color color) => onColorSelected(
|
||||
color.value == selectedColor ? null : color.value,
|
||||
);
|
||||
|
||||
var checkMarkColor = _hasHighContrast(color)
|
||||
? colors.templateColorLightCheckmarkColor
|
||||
: colors.templateColorDarkCheckmarkColor;
|
||||
|
||||
var icon = selectedColor == color.value
|
||||
? Icon(Icons.check, color: checkMarkColor)
|
||||
: null;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => onColorClick(color),
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: options.borderRadius,
|
||||
border: Border.all(
|
||||
color: color.value == selectedColor
|
||||
? Colors.black
|
||||
: Colors.transparent,
|
||||
width: 1,
|
||||
),
|
||||
child: icon,
|
||||
),
|
||||
child: selectedColor == color.value
|
||||
? const Icon(Icons.check)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// If the color is selected, deselect it, otherwise select it
|
||||
void _onColorClick(Color color) => onColorSelected(
|
||||
color.value == selectedColor ? null : color.value,
|
||||
);
|
||||
/// Computes the relative luminance of a color
|
||||
/// This is following the formula from the WCAG guidelines
|
||||
double _relativeLuminance(Color color) {
|
||||
double channelLuminance(int channel) {
|
||||
var c = channel / 255.0;
|
||||
return c <= 0.03928 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4).toDouble();
|
||||
}
|
||||
|
||||
return 0.2126 * channelLuminance(color.red) +
|
||||
0.7152 * channelLuminance(color.green) +
|
||||
0.0722 * channelLuminance(color.blue);
|
||||
}
|
||||
|
||||
/// Computes the contrast ratio between two colors
|
||||
/// This is following the formula from the WCAG guidelines
|
||||
double _contrastRatio(Color color1, Color color2) {
|
||||
var luminance1 = _relativeLuminance(color1);
|
||||
var luminance2 = _relativeLuminance(color2);
|
||||
if (luminance1 > luminance2) {
|
||||
return (luminance1 + 0.05) / (luminance2 + 0.05);
|
||||
} else {
|
||||
return (luminance2 + 0.05) / (luminance1 + 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the color has high contrast with white
|
||||
/// This is following the WCAG guidelines
|
||||
bool _hasHighContrast(Color color) {
|
||||
const white = Color(0xFFFFFFFF);
|
||||
return _contrastRatio(color, white) > 4.5;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue