main
1import 'dart:async';
2
3import 'package:flutter/material.dart';
4import 'package:blood_pressure_app/l10n/app_localizations.dart';
5
6/// A list of colors in circles where one can be selected at a time.
7class ColorPicker extends StatefulWidget {
8 /// Create a widget to select one color from a list.
9 const ColorPicker({super.key,
10 required this.onColorSelected,
11 this.availableColors,
12 this.initialColor,
13 this.showTransparentColor = true,
14 this.circleSize = 50,
15 });
16
17 /// Colors to choose from.
18 ///
19 /// Defaults to [ColorPicker.allColors].
20 final List<Color>? availableColors;
21
22 /// Color that starts out highlighted.
23 ///
24 /// When [initialColor] is null the transparent color is selected. When
25 /// [showTransparentColor] is false as well no color is selected.
26 final Color? initialColor;
27
28 /// Called after a click on a color.
29 final FutureOr<void> Function(Color? color) onColorSelected;
30
31 /// Controls whether a option for selecting that no color is displayed.
32 final bool showTransparentColor;
33
34 /// List of all material colors and black/white
35 static final List<Color> allColors = [
36 const Color(0xFFFFFFFF),
37 const Color(0xFF000000),
38 Colors.red,
39 Colors.redAccent,
40 Colors.pink,
41 Colors.pinkAccent,
42 Colors.purple,
43 Colors.purpleAccent,
44 Colors.deepPurple,
45 Colors.deepPurpleAccent,
46 Colors.indigo,
47 Colors.indigoAccent,
48 Colors.blue,
49 Colors.blueAccent,
50 Colors.lightBlue,
51 Colors.lightBlueAccent,
52 Colors.cyan,
53 Colors.cyanAccent,
54 Colors.teal,
55 Colors.tealAccent,
56 Colors.green,
57 Colors.greenAccent,
58 Colors.lightGreen,
59 Colors.lightGreenAccent,
60 Colors.lime,
61 Colors.limeAccent,
62 Colors.yellow,
63 Colors.yellowAccent,
64 Colors.amber,
65 Colors.amberAccent,
66 Colors.orange,
67 Colors.orangeAccent,
68 Colors.deepOrange,
69 Colors.deepOrangeAccent,
70 Colors.brown,
71 Colors.grey,
72 Colors.blueGrey,
73 ];
74
75 /// Size of the color circles.
76 final double circleSize;
77
78 @override
79 State<ColorPicker> createState() => _ColorPickerState();
80}
81
82class _ColorPickerState extends State<ColorPicker> {
83 /// Currently selected color.
84 late Color _selected;
85 late final List<Color> availableColors;
86
87 @override
88 void initState() {
89 super.initState();
90 _selected = widget.initialColor ?? Colors.transparent;
91 availableColors = widget.availableColors ?? ColorPicker.allColors;
92 }
93 @override
94 Widget build(BuildContext context) => Wrap(
95 children: [
96 for (final color in availableColors)
97 InkWell(
98 onTap: () {
99 setState(() {
100 _selected = color;
101 widget.onColorSelected(_selected);
102 });
103 },
104 child: Container(
105 decoration: BoxDecoration(
106 color: _selected == color
107 ? Theme.of(context).disabledColor
108 : Colors.transparent,
109 shape: BoxShape.circle,),
110 padding: const EdgeInsets.all(5),
111 child: Container(
112 height: widget.circleSize,
113 width: widget.circleSize,
114 decoration: BoxDecoration(
115 color: color,
116 shape: BoxShape.circle,
117 ),
118 ),
119 ),
120 ),
121 if (widget.showTransparentColor)
122 InkWell(
123 onTap: () {
124 setState(() {
125 _selected = Colors.transparent;
126 widget.onColorSelected(_selected);
127 });
128 },
129 child: Container(
130 padding: const EdgeInsets.all(5),
131 decoration: BoxDecoration(
132 color: _selected == Colors.transparent
133 ? Theme.of(context).disabledColor
134 : Colors.transparent,
135 shape: BoxShape.circle,),
136 child: SizedBox(
137 height: widget.circleSize,
138 width: widget.circleSize,
139 child: const Icon(Icons.block),
140 ),
141 ),
142 ),
143 ],
144 );
145}
146
147/// Shows a dialog with a ColorPicker and with an cancel button inside.
148///
149/// Returns the selected color or null when cancel is pressed.
150Future<Color?> showColorPickerDialog(
151 BuildContext context, [
152 Color? initialColor,
153]) async => showDialog(
154 context: context,
155 builder: (_) => AlertDialog(
156 contentPadding: const EdgeInsets.all(6.0),
157 content: ColorPicker(
158 initialColor: initialColor,
159 onColorSelected: (color) {
160 Navigator.pop(context, color);
161 },
162 ),
163 actions: [
164 TextButton(
165 onPressed: Navigator.of(context).pop,
166 child: Text(AppLocalizations.of(context)!.btnCancel),
167 ),
168 ],
169 ),
170);