Skip to content

Commit fedb855

Browse files
committed
Updated color picker to support only red,black and white colors.
1 parent eb6e359 commit fedb855

4 files changed

Lines changed: 584 additions & 2 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
// Flutter imports:
2+
import 'package:flutter/material.dart';
3+
import 'package:magic_epaper_app/pro_image_editor/features/color_picker.dart';
4+
import 'package:pro_image_editor/core/models/editor_configs/pro_image_editor_configs.dart';
5+
import 'package:pro_image_editor/core/ui/pro_image_editor_icons.dart';
6+
7+
/// Represents the bottom bar for the paint functionality in the WhatsApp theme.
8+
///
9+
/// This widget provides controls for adjusting the stroke width and color
10+
/// for paint operations, using a design inspired by WhatsApp.
11+
class BottomBarCustom extends StatefulWidget {
12+
/// Creates a [BottomBarCustom] widget.
13+
///
14+
/// This bottom bar allows users to select stroke widths and colors for
15+
/// paint, integrating seamlessly with the WhatsApp theme.
16+
///
17+
/// Example:
18+
/// ```
19+
/// BottomBarCustom(
20+
/// configs: myEditorConfigs,
21+
/// strokeWidth: 5.0,
22+
/// onSetLineWidth: (width) {
23+
/// // Handle stroke width change
24+
/// },
25+
/// initColor: Colors.black,
26+
/// onColorChanged: (color) {
27+
/// // Handle color change
28+
/// },
29+
/// )
30+
/// ```
31+
const BottomBarCustom({
32+
super.key,
33+
required this.configs,
34+
required this.strokeWidth,
35+
required this.onSetLineWidth,
36+
required this.initColor,
37+
required this.onColorChanged,
38+
this.iconStrokeWidthThin = ProImageEditorIcons.penSize1,
39+
this.iconStrokeWidthMedium = ProImageEditorIcons.penSize2,
40+
this.iconStrokeWidthBold = ProImageEditorIcons.penSize3,
41+
});
42+
43+
/// The configuration for the image editor.
44+
///
45+
/// These settings determine various aspects of the bottom bar's behavior
46+
/// and appearance, ensuring it aligns with the application's overall theme.
47+
final ProImageEditorConfigs configs;
48+
49+
/// The current stroke width for paint.
50+
///
51+
/// This value determines the thickness of the lines drawn in the paint
52+
/// editor, allowing users to customize the appearance of their artwork.
53+
final double strokeWidth;
54+
55+
/// Callback function for setting the stroke width.
56+
///
57+
/// This function is called whenever the user selects a different stroke
58+
/// width, allowing the application to update the line thickness.
59+
final Function(double value) onSetLineWidth;
60+
61+
/// The initial color for paint.
62+
///
63+
/// This color sets the initial paint color, providing a starting point
64+
/// for color customization.
65+
final Color initColor;
66+
67+
/// Callback function for handling color changes.
68+
///
69+
/// This function is called whenever the user selects a new color, allowing
70+
/// the application to update the paint color.
71+
final ValueChanged<Color> onColorChanged;
72+
73+
/// Icon representing thin stroke width.
74+
///
75+
/// This icon is used to visually represent the option for selecting a
76+
/// thin stroke width in the paint toolbar.
77+
final IconData iconStrokeWidthThin;
78+
79+
/// Icon representing medium stroke width.
80+
///
81+
/// This icon is used to visually represent the option for selecting a
82+
/// medium stroke width in the paint toolbar.
83+
final IconData iconStrokeWidthMedium;
84+
85+
/// Icon representing bold stroke width.
86+
///
87+
/// This icon is used to visually represent the option for selecting a
88+
/// bold stroke width in the paint toolbar.
89+
final IconData iconStrokeWidthBold;
90+
91+
@override
92+
State<BottomBarCustom> createState() => _BottomBarCustomState();
93+
}
94+
95+
class _BottomBarCustomState extends State<BottomBarCustom> {
96+
final double _space = 10;
97+
98+
bool _showColorPicker = true;
99+
100+
bool get _isMaterial =>
101+
widget.configs.designMode == ImageEditorDesignMode.material;
102+
103+
@override
104+
Widget build(BuildContext context) {
105+
return Positioned(
106+
bottom: _space,
107+
left: _space,
108+
right: 0,
109+
height: 40,
110+
child: !_isMaterial
111+
? _buildLineWidths()
112+
: Row(
113+
crossAxisAlignment: CrossAxisAlignment.stretch,
114+
mainAxisAlignment: MainAxisAlignment.start,
115+
children: [
116+
IconButton(
117+
onPressed: () {
118+
setState(() {
119+
_showColorPicker = !_showColorPicker;
120+
});
121+
},
122+
icon: Icon(
123+
_showColorPicker ? Icons.draw : Icons.color_lens,
124+
),
125+
style: IconButton.styleFrom(backgroundColor: Colors.black38),
126+
),
127+
Container(
128+
margin: const EdgeInsets.fromLTRB(14.0, 4, 0, 4),
129+
width: 1.5,
130+
decoration: BoxDecoration(
131+
color: Colors.white54,
132+
borderRadius: BorderRadius.circular(2),
133+
),
134+
),
135+
_showColorPicker
136+
? Expanded(
137+
child: ColorPickerCustom(
138+
onColorChanged: widget.onColorChanged,
139+
initColor: widget.initColor,
140+
),
141+
)
142+
: _buildLineWidths(),
143+
],
144+
),
145+
);
146+
}
147+
148+
Widget _buildLineWidths() {
149+
ButtonStyle buttonStyle = IconButton.styleFrom(
150+
backgroundColor: Colors.black38,
151+
foregroundColor:
152+
widget.configs.paintEditor.style.bottomBarInactiveItemColor,
153+
padding: const EdgeInsets.all(10),
154+
iconSize: 22,
155+
minimumSize: const Size.fromRadius(10),
156+
);
157+
return Padding(
158+
padding: const EdgeInsets.only(left: 14),
159+
child: Wrap(
160+
alignment:
161+
_isMaterial ? WrapAlignment.start : WrapAlignment.spaceEvenly,
162+
runAlignment: WrapAlignment.center,
163+
spacing: 10,
164+
children: [
165+
IconButton(
166+
onPressed: () {
167+
widget.onSetLineWidth(2);
168+
},
169+
icon: Icon(widget.iconStrokeWidthThin),
170+
style: buttonStyle.copyWith(
171+
backgroundColor: widget.strokeWidth != 2
172+
? null
173+
: const WidgetStatePropertyAll(Colors.white),
174+
foregroundColor: widget.strokeWidth != 2
175+
? null
176+
: const WidgetStatePropertyAll(Colors.black),
177+
),
178+
),
179+
IconButton(
180+
onPressed: () {
181+
widget.onSetLineWidth(5);
182+
},
183+
icon: Icon(widget.iconStrokeWidthMedium),
184+
style: buttonStyle.copyWith(
185+
backgroundColor: widget.strokeWidth != 5
186+
? null
187+
: const WidgetStatePropertyAll(Colors.white),
188+
foregroundColor: widget.strokeWidth != 5
189+
? null
190+
: const WidgetStatePropertyAll(Colors.black),
191+
),
192+
),
193+
IconButton(
194+
onPressed: () {
195+
widget.onSetLineWidth(10);
196+
},
197+
icon: Icon(widget.iconStrokeWidthBold),
198+
style: buttonStyle.copyWith(
199+
backgroundColor: widget.strokeWidth != 10
200+
? null
201+
: const WidgetStatePropertyAll(Colors.white),
202+
foregroundColor: widget.strokeWidth != 10
203+
? null
204+
: const WidgetStatePropertyAll(Colors.black),
205+
),
206+
),
207+
],
208+
),
209+
);
210+
}
211+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Flutter imports:
2+
import 'package:flutter/material.dart';
3+
4+
/// A stateful widget that provides a color picker inspired by WhatsApp.
5+
///
6+
/// This color picker allows users to select a color, providing a callback for
7+
/// color changes and initializing with a specified color.
8+
class ColorPickerCustom extends StatefulWidget {
9+
/// Creates a [ColorPickerCustom].
10+
///
11+
/// This color picker lets users select a color, triggering a callback when
12+
/// the color changes, and initializing with a specified color.
13+
///
14+
/// Example:
15+
/// ```
16+
/// ColorPickerCustom(
17+
/// onColorChanged: (color) {
18+
/// // Handle color change
19+
/// },
20+
/// initColor: Colors.blue,
21+
/// )
22+
/// ```
23+
const ColorPickerCustom({
24+
super.key,
25+
required this.onColorChanged,
26+
required this.initColor,
27+
});
28+
29+
/// Callback for handling color changes.
30+
///
31+
/// This callback is triggered whenever the user selects a new color, allowing
32+
/// the application to update its UI or perform other actions.
33+
final ValueChanged<Color> onColorChanged;
34+
35+
/// The initial color selected in the color picker.
36+
///
37+
/// This color sets the initial value of the picker, providing a starting
38+
/// point for color selection.
39+
final Color initColor;
40+
41+
@override
42+
State<ColorPickerCustom> createState() => _ColorPickerCustomState();
43+
}
44+
45+
class _ColorPickerCustomState extends State<ColorPickerCustom> {
46+
Color _selectedColor = Colors.black;
47+
48+
final List<Color> _colors = [
49+
Colors.white,
50+
Colors.black,
51+
Colors.red,
52+
];
53+
54+
@override
55+
void initState() {
56+
super.initState();
57+
_selectedColor = widget.initColor;
58+
}
59+
60+
@override
61+
Widget build(BuildContext context) {
62+
return ListView.builder(
63+
padding: const EdgeInsets.symmetric(horizontal: 14),
64+
scrollDirection: Axis.horizontal,
65+
primary: false,
66+
shrinkWrap: true,
67+
itemBuilder: (context, index) {
68+
Color color = _colors[index];
69+
bool selected = _selectedColor == color;
70+
71+
double size = !selected ? 20 : 24;
72+
double borderWidth = !selected ? 2.5 : 4;
73+
74+
return Center(
75+
child: GestureDetector(
76+
onTap: () {
77+
setState(() {
78+
_selectedColor = color;
79+
widget.onColorChanged(color);
80+
});
81+
},
82+
child: AnimatedContainer(
83+
margin: const EdgeInsets.symmetric(horizontal: 10.0),
84+
duration: const Duration(milliseconds: 100),
85+
width: size,
86+
height: size,
87+
decoration: BoxDecoration(
88+
color: color,
89+
borderRadius: BorderRadius.circular(100),
90+
border: Border.all(
91+
color: Colors.grey,
92+
width: borderWidth,
93+
),
94+
),
95+
),
96+
),
97+
);
98+
},
99+
itemCount: _colors.length,
100+
);
101+
}
102+
}

0 commit comments

Comments
 (0)