Skip to content

Commit 4b9140b

Browse files
Merge pull request #32 from sikandernoori/main
Implements [Feature Request] CustomPaint for drawPath #31
2 parents ff8efd4 + 6a8b77c commit 4b9140b

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ How big the crop should be in regards to the width and height available to the c
5050

5151
How the border of the crop should be painted. default DottedCropPathPainter.drawPath and SolidCropPathPainter.drawPath are provided, but you can create/provide any CustomPaint.
5252

53+
### pathPaint
54+
Custom painting for the crop area border style.
55+
5356
### canRotate
5457

5558
Whether to allow the image to be rotated.

example/lib/main.dart

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,29 +90,53 @@ class _MyHomePageState extends State<MyHomePage> {
9090
child: CustomImageCrop(
9191
cropController: controller,
9292
// image: const AssetImage('assets/test.png'), // Any Imageprovider will work, try with a NetworkImage for example...
93-
image: const NetworkImage('https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'),
93+
image: const NetworkImage(
94+
'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'),
9495
shape: _currentShape,
95-
ratio: _currentShape == CustomCropShape.Ratio ? Ratio(width: _width, height: _height) : null,
96+
ratio: _currentShape == CustomCropShape.Ratio
97+
? Ratio(width: _width, height: _height)
98+
: null,
9699
canRotate: true,
97100
canMove: false,
98101
canScale: false,
99102
customProgressIndicator: const CupertinoActivityIndicator(),
103+
// use custom paint if needed
104+
// pathPaint: Paint()
105+
// ..color = Colors.red
106+
// ..strokeWidth = 4.0
107+
// ..style = PaintingStyle.stroke
108+
// ..strokeJoin = StrokeJoin.round,
100109
),
101110
),
102111
Row(
103112
mainAxisAlignment: MainAxisAlignment.spaceAround,
104113
children: [
105-
IconButton(icon: const Icon(Icons.refresh), onPressed: controller.reset),
106-
IconButton(icon: const Icon(Icons.zoom_in), onPressed: () => controller.addTransition(CropImageData(scale: 1.33))),
107-
IconButton(icon: const Icon(Icons.zoom_out), onPressed: () => controller.addTransition(CropImageData(scale: 0.75))),
108-
IconButton(icon: const Icon(Icons.rotate_left), onPressed: () => controller.addTransition(CropImageData(angle: -pi / 4))),
109-
IconButton(icon: const Icon(Icons.rotate_right), onPressed: () => controller.addTransition(CropImageData(angle: pi / 4))),
114+
IconButton(
115+
icon: const Icon(Icons.refresh), onPressed: controller.reset),
116+
IconButton(
117+
icon: const Icon(Icons.zoom_in),
118+
onPressed: () =>
119+
controller.addTransition(CropImageData(scale: 1.33))),
120+
IconButton(
121+
icon: const Icon(Icons.zoom_out),
122+
onPressed: () =>
123+
controller.addTransition(CropImageData(scale: 0.75))),
124+
IconButton(
125+
icon: const Icon(Icons.rotate_left),
126+
onPressed: () =>
127+
controller.addTransition(CropImageData(angle: -pi / 4))),
128+
IconButton(
129+
icon: const Icon(Icons.rotate_right),
130+
onPressed: () =>
131+
controller.addTransition(CropImageData(angle: pi / 4))),
110132
IconButton(
111133
icon: const Icon(Icons.crop),
112134
onPressed: () async {
113135
final image = await controller.onCropImage();
114136
if (image != null) {
115-
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => ResultScreen(image: image)));
137+
Navigator.of(context).push(MaterialPageRoute(
138+
builder: (BuildContext context) =>
139+
ResultScreen(image: image)));
116140
}
117141
},
118142
),

lib/src/painters/dotted_path_painter.dart

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,38 @@ import 'package:flutter/material.dart';
22

33
/// Draw a dotted path around the given path
44
class DottedCropPathPainter extends CustomPainter {
5-
static const _dashWidth = 10.0;
6-
static const _dashSpace = 5.0;
7-
static const _strokeWidth = 4.0;
5+
final double dashWidth;
6+
final double dashSpace;
87
final Path _path;
9-
final _paint = Paint()
10-
..color = Colors.white
11-
..strokeWidth = _strokeWidth
12-
..style = PaintingStyle.stroke
13-
..strokeJoin = StrokeJoin.round;
8+
final Paint pathPaint;
149

1510
/// Draw a dotted path around the given path
16-
DottedCropPathPainter(this._path);
11+
DottedCropPathPainter(
12+
this._path, {
13+
this.dashWidth = 10.0,
14+
this.dashSpace = 5.0,
15+
required this.pathPaint,
16+
});
1717

1818
/// Return a CustomPaint widget with the current CustomPainter
19-
static CustomPaint drawPath(Path path) =>
20-
CustomPaint(painter: DottedCropPathPainter(path));
19+
static CustomPaint drawPath(Path path, {Paint? pathPaint}) {
20+
if (pathPaint != null) {
21+
return CustomPaint(
22+
painter: DottedCropPathPainter(path, pathPaint: pathPaint),
23+
);
24+
} else {
25+
return CustomPaint(
26+
painter: DottedCropPathPainter(
27+
path,
28+
pathPaint: Paint()
29+
..color = Colors.white
30+
..strokeWidth = 4.0
31+
..style = PaintingStyle.stroke
32+
..strokeJoin = StrokeJoin.round,
33+
),
34+
);
35+
}
36+
}
2137

2238
@override
2339
void paint(Canvas canvas, Size size) {
@@ -26,14 +42,14 @@ class DottedCropPathPainter extends CustomPainter {
2642
for (final pathMetric in _path.computeMetrics()) {
2743
while (distance < pathMetric.length) {
2844
dashPath.addPath(
29-
pathMetric.extractPath(distance, distance + _dashWidth),
45+
pathMetric.extractPath(distance, distance + dashWidth),
3046
Offset.zero,
3147
);
32-
distance += _dashWidth;
33-
distance += _dashSpace;
48+
distance += dashWidth;
49+
distance += dashSpace;
3450
}
3551
}
36-
canvas.drawPath(dashPath, _paint);
52+
canvas.drawPath(dashPath, pathPaint);
3753
}
3854

3955
@override

lib/src/widgets/custom_image_crop_widget.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,19 @@ class CustomImageCrop extends StatefulWidget {
5353
/// The path drawer of the border see [DottedCropPathPainter],
5454
/// [SolidPathPainter] for more details or how to implement a
5555
/// custom one
56-
final CustomPaint Function(Path) drawPath;
56+
final CustomPaint Function(Path, {Paint? pathPaint}) drawPath;
57+
58+
/// Custom paint options for drawing the cropping border.
59+
///
60+
/// If [paint] is provided, it will be used for customizing the appearance
61+
/// of the cropping border.
62+
///
63+
/// If [paint] is not provided, default values will be used:
64+
/// - Color: [Colors.white]
65+
/// - Stle [PaintingStyle.stroke]
66+
/// - Stroke Join [StrokeJoin.round]
67+
/// - Stroke Width: 4.0
68+
final Paint? pathPaint;
5769

5870
/// Whether to allow the image to be rotated.
5971
final bool canRotate;
@@ -101,6 +113,7 @@ class CustomImageCrop extends StatefulWidget {
101113
this.imageFit = CustomImageFit.fitCropSpace,
102114
this.cropPercentage = 0.8,
103115
this.drawPath = DottedCropPathPainter.drawPath,
116+
this.pathPaint,
104117
this.canRotate = true,
105118
this.canScale = true,
106119
this.canMove = true,
@@ -222,7 +235,7 @@ class _CustomImageCropState extends State<CustomImageCrop>
222235
),
223236
),
224237
),
225-
widget.drawPath(_path),
238+
widget.drawPath(_path, pathPaint: widget.pathPaint),
226239
],
227240
),
228241
),

0 commit comments

Comments
 (0)