mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 21:23:44 +02:00
fix: change the template selection to use light and dark checkmark
This commit is contained in:
parent
97318ff8c0
commit
fc0fcc7c9c
2 changed files with 98 additions and 25 deletions
|
@ -144,6 +144,8 @@ class AvailabilityColors {
|
||||||
this.textDarkColor,
|
this.textDarkColor,
|
||||||
this.textLightColor,
|
this.textLightColor,
|
||||||
this.templateWeekOverviewBackgroundColor,
|
this.templateWeekOverviewBackgroundColor,
|
||||||
|
this.templateColorLightCheckmarkColor,
|
||||||
|
this.templateColorDarkCheckmarkColor,
|
||||||
this.templateColors = const [
|
this.templateColors = const [
|
||||||
Color(0xFF9bb8f2),
|
Color(0xFF9bb8f2),
|
||||||
Color(0xFF4b77d0),
|
Color(0xFF4b77d0),
|
||||||
|
@ -179,6 +181,14 @@ class AvailabilityColors {
|
||||||
/// If not provided the text color will be the theme's text color
|
/// If not provided the text color will be the theme's text color
|
||||||
final Color? textDarkColor;
|
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
|
/// The color of the background in the template week overview that creates a
|
||||||
/// layered effect by interchanging a color and a transparent color
|
/// layered effect by interchanging a color and a transparent color
|
||||||
/// If not provided the color will be the theme's [ColorScheme.surface]
|
/// 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/material.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
|
@ -38,35 +40,96 @@ class TemplateColorSelection extends StatelessWidget {
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
children: [
|
children: [
|
||||||
for (var color in colors.templateColors)
|
for (var color in colors.templateColors) ...[
|
||||||
GestureDetector(
|
_TemplateColorItem(
|
||||||
onTap: () => _onColorClick(color),
|
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(
|
child: Container(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: color,
|
||||||
borderRadius: options.borderRadius,
|
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
|
/// Computes the relative luminance of a color
|
||||||
void _onColorClick(Color color) => onColorSelected(
|
/// This is following the formula from the WCAG guidelines
|
||||||
color.value == selectedColor ? null : color.value,
|
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