Skip to content

Commit 537cc40

Browse files
authored
Merge pull request #111 from aslangery/show_gallery_button
add property for show gallery button or not
2 parents 85f6b5a + 94df7ae commit 537cc40

File tree

1 file changed

+39
-116
lines changed

1 file changed

+39
-116
lines changed

lib/src/ai_barcode_scanner.dart

Lines changed: 39 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ class AiBarcodeScanner extends StatefulWidget {
1818
/// You can use your own custom overlay builder
1919
/// to build your own overlay
2020
/// This will override the default custom overlay
21-
final Widget? Function(BuildContext, bool?, MobileScannerController)?
22-
customOverlayBuilder;
21+
final Widget? Function(BuildContext, bool?, MobileScannerController)? customOverlayBuilder;
2322

2423
/// Overlay border color (default: white)
2524
final Color? borderColor;
@@ -65,8 +64,7 @@ class AiBarcodeScanner extends StatefulWidget {
6564
///
6665
/// If this is null, defaults to a black [ColoredBox]
6766
/// with a centered white [Icons.error] icon.
68-
final Widget Function(BuildContext, MobileScannerException, Widget?)?
69-
errorBuilder;
67+
final Widget Function(BuildContext, MobileScannerException, Widget?)? errorBuilder;
7068

7169
/// The function that builds a placeholder widget when the scanner
7270
/// is not yet displaying its camera preview.
@@ -79,87 +77,19 @@ class AiBarcodeScanner extends StatefulWidget {
7977

8078
/// AppBar widget
8179
/// you can use this to add appBar to the scanner screen
82-
///
83-
final PreferredSizeWidget? Function(
84-
BuildContext context, MobileScannerController controller)? appBarBuilder;
80+
final PreferredSizeWidget? Function(BuildContext context, MobileScannerController controller)? appBarBuilder;
8581

8682
/// The builder for the bottom sheet.
8783
/// This is displayed below the camera preview.
88-
final Widget? Function(
89-
BuildContext context, MobileScannerController controller)?
90-
bottomSheetBuilder;
84+
final Widget? Function(BuildContext context, MobileScannerController controller)? bottomSheetBuilder;
9185

9286
/// The builder for the overlay above the camera preview.
93-
///
94-
/// The resulting widget can be combined with the [scanWindow] rectangle
95-
/// to create a cutout for the camera preview.
96-
///
97-
/// The [BoxConstraints] for this builder
98-
/// are the same constraints that are used to compute the effective [scanWindow].
99-
///
100-
/// The overlay is only displayed when the camera preview is visible.
10187
final LayoutWidgetBuilder? overlayBuilder;
10288

10389
/// The scan window rectangle for the barcode scanner.
104-
///
105-
/// If this is not null, the barcode scanner will only scan barcodes
106-
/// which intersect this rectangle.
107-
///
108-
/// This rectangle is relative to the layout size
109-
/// of the *camera preview widget* in the widget tree,
110-
/// rather than the actual size of the camera preview output.
111-
/// This is because the size of the camera preview widget
112-
/// might not be the same as the size of the camera output.
113-
///
114-
/// For example, the applied [fit] has an effect on the size of the camera preview widget,
115-
/// while the camera preview size remains the same.
116-
///
117-
/// The following example shows a scan window that is centered,
118-
/// fills half the height and one third of the width of the layout:
119-
///
120-
/// ```dart
121-
/// LayoutBuider(
122-
/// builder: (BuildContext context, BoxConstraints constraints) {
123-
/// final Size layoutSize = constraints.biggest;
124-
///
125-
/// final double scanWindowWidth = layoutSize.width / 3;
126-
/// final double scanWindowHeight = layoutSize.height / 2;
127-
///
128-
/// final Rect scanWindow = Rect.fromCenter(
129-
/// center: layoutSize.center(Offset.zero),
130-
/// width: scanWindowWidth,
131-
/// height: scanWindowHeight,
132-
/// );
133-
/// }
134-
/// );
135-
/// ```
13690
final Rect? scanWindow;
13791

13892
/// The threshold for updates to the [scanWindow].
139-
///
140-
/// If the [scanWindow] would be updated,
141-
/// due to new layout constraints for the scanner,
142-
/// and the width or height of the new scan window have not changed by this threshold,
143-
/// then the scan window is not updated.
144-
///
145-
/// It is recommended to set this threshold
146-
/// if scan window updates cause performance issues.
147-
///
148-
/// Defaults to no threshold for scan window updates.
149-
///
150-
final void Function(BarcodeCapture)? onDetect;
151-
152-
/// The threshold for updates to the [scanWindow].
153-
///
154-
/// If the [scanWindow] would be updated,
155-
/// due to new layout constraints for the scanner,
156-
/// and the width or height of the new scan window have not changed by this threshold,
157-
/// then the scan window is not updated.
158-
///
159-
/// It is recommended to set this threshold
160-
/// if scan window updates cause performance issues.
161-
///
162-
/// Defaults to no threshold for scan window updates.
16393
final double scanWindowUpdateThreshold;
16494

16595
/// Validator function to check if barcode is valid or not
@@ -191,15 +121,16 @@ class AiBarcodeScanner extends StatefulWidget {
191121
final bool extendBodyBehindAppBar;
192122

193123
/// Upload from gallery button alignment
194-
/// default: bottom center, center, 0.75
195124
final AlignmentGeometry? galleryButtonAlignment;
196125

197126
/// actions for the app bar (optional)
198127
/// Camera switch and torch toggle buttons are added by default
199128
/// You can add more actions to the app bar using this parameter
200129
final List<Widget>? actions;
201130

131+
/// Lock orientation to portrait (default: true)
202132
final bool setPortraitOrientation;
133+
203134
const AiBarcodeScanner({
204135
super.key,
205136
this.fit = BoxFit.cover,
@@ -232,12 +163,12 @@ class AiBarcodeScanner extends StatefulWidget {
232163
this.sheetChild = const SizedBox.shrink(),
233164
this.hideSheetDragHandler = false,
234165
this.hideSheetTitle = false,
235-
this.galleryButtonAlignment,
236-
this.actions,
237166
this.hideGalleryButton = false,
238167
this.hideGalleryIcon = true,
239168
this.bottomSheetBuilder,
240169
this.extendBodyBehindAppBar = true,
170+
this.galleryButtonAlignment,
171+
this.actions,
241172
this.setPortraitOrientation = true,
242173
});
243174

@@ -246,37 +177,37 @@ class AiBarcodeScanner extends StatefulWidget {
246177
}
247178

248179
class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
249-
/// bool to check if barcode is valid or not
250180
final ValueNotifier<bool?> _isSuccess = ValueNotifier<bool?>(null);
251-
252-
/// Scanner controller
253181
late MobileScannerController controller;
254-
255182
double _cutOutBottomOffset = 0;
256183

257184
@override
258185
void initState() {
186+
if (widget.setPortraitOrientation) {
187+
SystemChrome.setPreferredOrientations([
188+
DeviceOrientation.portraitUp,
189+
DeviceOrientation.portraitDown,
190+
]);
191+
}
259192
controller = widget.controller ?? MobileScannerController();
260193
_cutOutBottomOffset = widget.cutOutBottomOffset;
261194
super.initState();
262195
}
263196

264197
@override
265198
void dispose() {
266-
// controller.dispose();
267-
// widget.controller?.dispose();
199+
if (widget.controller == null) {
200+
controller.dispose();
201+
}
268202
widget.onDispose?.call();
203+
if (widget.setPortraitOrientation) {
204+
SystemChrome.setPreferredOrientations(DeviceOrientation.values);
205+
}
269206
super.dispose();
270207
}
271208

272209
@override
273210
Widget build(BuildContext context) {
274-
if (widget.setPortraitOrientation) {
275-
SystemChrome.setPreferredOrientations([
276-
DeviceOrientation.portraitUp,
277-
DeviceOrientation.portraitDown,
278-
]);
279-
}
280211
return Scaffold(
281212
appBar: widget.appBarBuilder?.call(context, controller) ??
282213
AppBar(
@@ -286,17 +217,16 @@ class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
286217
actions: [
287218
IconButton(
288219
icon: const Icon(Icons.cameraswitch_rounded),
289-
onPressed: controller.switchCamera,
220+
onPressed: () => controller.switchCamera(),
290221
),
291-
292222
IconButton(
293223
icon: controller.value.torchState == TorchState.on
294224
? const Icon(Icons.flashlight_off_rounded)
295225
: const Icon(Icons.flashlight_on_rounded),
296-
onPressed: (){
226+
onPressed: () {
297227
controller.toggleTorch();
298228
setState(() {});
299-
}
229+
},
300230
),
301231
if (!widget.hideGalleryIcon)
302232
GalleryButton.icon(
@@ -323,8 +253,7 @@ class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
323253
onDetect: onDetect,
324254
controller: controller,
325255
fit: widget.fit,
326-
errorBuilder:
327-
widget.errorBuilder ?? (_, error, ___) => const ErrorBuilder(),
256+
errorBuilder: widget.errorBuilder ?? (_, __, ___) => const ErrorBuilder(),
328257
placeholderBuilder: widget.placeholderBuilder,
329258
scanWindow: widget.scanWindow,
330259
key: widget.key,
@@ -334,30 +263,27 @@ class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
334263
ValueListenableBuilder<bool?>(
335264
valueListenable: _isSuccess,
336265
builder: (context, isSuccess, __) {
337-
return widget.customOverlayBuilder
338-
?.call(context, isSuccess, controller) ??
266+
return widget.customOverlayBuilder?.call(context, isSuccess, controller) ??
339267
Container(
340268
decoration: ShapeDecoration(
341269
shape: OverlayShape(
342270
borderRadius: widget.borderRadius,
343-
borderColor:
344-
((isSuccess ?? false) && widget.showSuccess)
345-
? widget.successColor
346-
: (!(isSuccess ?? true) && widget.showError)
347-
? widget.errorColor
348-
: widget.borderColor ?? Colors.white,
271+
borderColor: ((isSuccess ?? false) && widget.showSuccess)
272+
? widget.successColor
273+
: (!(isSuccess ?? true) && widget.showError)
274+
? widget.errorColor
275+
: widget.borderColor ?? Colors.white,
349276
borderLength: widget.borderLength,
350277
borderWidth: widget.borderWidth,
351278
cutOutSize: widget.cutOutSize,
352279
cutOutBottomOffset: _cutOutBottomOffset,
353280
cutOutWidth: widget.cutOutWidth,
354281
cutOutHeight: widget.cutOutHeight,
355-
overlayColor:
356-
((isSuccess ?? false) && widget.showSuccess)
357-
? widget.successColor.withOpacity(0.4)
358-
: (!(isSuccess ?? true) && widget.showError)
359-
? widget.errorColor.withOpacity(0.4)
360-
: widget.overlayColor,
282+
overlayColor: ((isSuccess ?? false) && widget.showSuccess)
283+
? widget.successColor.withOpacity(0.4)
284+
: (!(isSuccess ?? true) && widget.showError)
285+
? widget.errorColor.withOpacity(0.4)
286+
: widget.overlayColor,
361287
),
362288
),
363289
);
@@ -366,11 +292,7 @@ class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
366292
if (!widget.hideGalleryButton)
367293
Align(
368294
alignment: widget.galleryButtonAlignment ??
369-
Alignment.lerp(
370-
Alignment.bottomCenter,
371-
Alignment.center,
372-
0.75,
373-
)!,
295+
Alignment.lerp(Alignment.bottomCenter, Alignment.center, 0.75)!,
374296
child: GalleryButton(
375297
onImagePick: widget.onImagePick,
376298
onDetect: widget.onDetect,
@@ -388,11 +310,12 @@ class _AiBarcodeScannerState extends State<AiBarcodeScanner> {
388310
widget.onDetect?.call(barcodes);
389311
if (widget.validator != null) {
390312
final isValid = widget.validator!(barcodes);
313+
_isSuccess.value = isValid;
391314
if (!isValid) {
392315
HapticFeedback.heavyImpact();
316+
} else {
317+
HapticFeedback.mediumImpact();
393318
}
394-
HapticFeedback.mediumImpact();
395-
_isSuccess.value = isValid;
396319
}
397320
}
398321
}

0 commit comments

Comments
 (0)