Simple Eye Dropper
A simple eye dropper widget that depends only on standard libraries.
Table of Contents
Use with asset images
Build the EyeDropper
widget as follows:
final byteData = await rootBundle.load('asset/example.png');
(snip)
EyeDropper.of(
// Encoded Uint8List.
bytes: byteData.buffer.asUint8List(),
// Size to display.
size: const Size(200, 400),
// Callback called when color is selected.
onSelected: (color) => print('Selected color is $color'),
);
bytes
argument is a Uint8List of image bytes obtained by image_picker etc. Ifbytes
argument is null, a blank area is displayed.onSelected
specifies a callback to be called when the color is selected.
Pointer
Choose a Pointer implementation
By default, the following pointers with magnification are specified.
EyeDropper.of(
bytes: bytes,
size: const Size(200, 400),
// By default.
pointerBuilder: MagnifierPointer.new,
onSelected: (color) => print('Selected color is $color'),
);
You can also specify a simple pointer as follows:
EyeDropper.of(
bytes: bytes,
size: const Size(200, 400),
// Simple small square pointer without magnification.
pointerBuilder: (_, __) => SimplePointer(),
onSelected: (color) => print('Selected color is $color'),
);
Or CircularMagnifierPointer is the following:
EyeDropper.of(
bytes: bytes,
size: const Size(200, 400),
pointerBuilder: CircularMagnifierPointer.new,
onSelected: (color) => print('Selected color is $color'),
);
Both of these pointers have several parameters providing for some customization.
EyeDropper.of(
bytes: bytes,
size: const Size(200, 400),
// Customize the pointer with magnification.
pointerBuilder: (uiImage, ratio) => MagnifierPointer(
uiImage,
ratio,
magnification: 2.5,
outerRectSize: 101,
outerStrokeWidth: 3,
innerRectSize: 9,
innerStrokeWidth: 3,
),
onSelected: (color) => print('Selected color is $color'),
);
Implement Pointer
You can also create your own pointers by inheriting from Pointer
classes.
Refer to the code of the CircleMagnifierPointer
class for how to implement Pointer
.
Image related
Supported image formats and error handling
Supported image formats are similar to
instantiateImageCodec
function of dart:ui.
At least the following image formats are supported: JPEG, PNG, GIF, Animated GIF, WebP,
Animated WebP, BMP, and WBMP.
When passing an unsupported image format Uint8List to bytes
, errorBuilder
is called.
The usage of errorBuilder
is the same as in
Image.errorBuilder.
By default, a gray error icon is displayed.
If you pass null
for bytes
, a blank area will be displayed.
Use with image_picker
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if(image == null) {
return;
}
final bytes = await image.readAsBytes();
(snip)
EyeDropper.of(
bytes: bytes,
size: const Size(200, 400),
onSelected: (color) => print('Selected color is $color'),
);
In practice, you will probably use FutureBuilder
for async/await support.
See example/lib/main.dart
for detailed coding examples.
Use with network images
For example, if you use the http package, you can do the following:
import 'package:http/http.dart' as http;
(snip)
final response = await http.get(Uri.parse('https://example.org/sample.jpg'));
(snip)
EyeDropper.of(
bytes: response.bodyBytes,
size: const Size(200, 400),
onSelected: (color) => print('Selected color is $color'),
);
Just pass the response body as is to bytes
.
Use with Dart Image Library
If you want to pass an image processed with image
(Dart Image Library) to EyeDropper, pass a Uint8List that has been re-encoded with img.encodeXXX
as shown below.
import 'package:image/image.dart' as img;
(snip)
final imgImage = img.decodeImage(bytes);
final grayImage = img.grayscale(imgImage!);
grayBytes = img.encodeJpg(grayImage);
(snip)
EyeDropper.of(
bytes: grayBytes,
size: const Size(200, 400),
onSelected: (color) => print('Selected color is $color'),
);
Use with Riverpod
When EyeDropper is used with ConsumerWidget or ConsumerStatefulWidget of Riverpod, the pointer may not be displayed because it is redrawn in its entirety.
// BAD example.
import 'package:flutter_riverpod/flutter_riverpod.dart';
final colorProvider = StateProvider<Color>((ref) => Colors.white);
(snip)
class MyHomePage extends ConsumerWidget {
(snip)
// Display color code.
Text(ref.watch(colorProvider).toString()),
(snip)
}
In such cases, instead of using ConsumerWidget or ConsumerStatefulWidget's ref
as is, use
Consumer
to specify the redraw range.
// GOOD example.
import 'package:flutter_riverpod/flutter_riverpod.dart';
final colorProvider = StateProvider<Color>((ref) => Colors.white);
class MyHomePage extends ConsumerWidget {
(snip)
// Display color code.
Consumer(
builder: (_, ref, __) {
return Text(ref.watch(colorProvider).toString());
},
),
(snip)
}
Libraries
- simple_eye_dropper
- A simple eye dropper widget that depends only on standard libraries.