Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
mobile_scanner
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Julian Steenbakker
2022-02-10 17:12:50 +0100
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9750c754e6b7cb95e6c34dcfc187cc3897a15277
9750c754
1 parent
f83a27fa
ci: update view
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
442 additions
and
479 deletions
analysis_options.yaml
android/build.gradle
android/src/main/kotlin/dev/steenbakker/mobile_scanner/MobileScanner.kt
example/android/app/build.gradle
example/android/app/src/debug/AndroidManifest.xml
example/android/app/src/main/AndroidManifest.xml
example/android/app/src/profile/AndroidManifest.xml
example/android/build.gradle
example/lib/main.dart
lib/src/camera_controller.dart
lib/src/camera_facing.dart
lib/src/camera_view.dart
lib/src/mobile_scanner.dart
lib/src/mobile_scanner_preview.dart
pubspec.yaml
analysis_options.yaml
View file @
9750c75
include
:
package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
include
:
package:flutter_lints/flutter.yaml
\ No newline at end of file
...
...
android/build.gradle
View file @
9750c75
...
...
@@ -9,8 +9,7 @@ buildscript {
}
dependencies
{
classpath
'com.android.tools.build:gradle:4.1.3'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath
'com.android.tools.build:gradle:7.1.0'
}
}
...
...
android/src/main/kotlin/dev/steenbakker/mobile_scanner/MobileScanner.kt
View file @
9750c75
...
...
@@ -31,10 +31,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
private var camera: Camera? = null
private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null
// @AnalyzeMode
// private var analyzeMode: Int = AnalyzeMode.NONE
@AnalyzeMode
private var analyzeMode: Int = AnalyzeMode.NONE
@ExperimentalGetImage
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) {
when (call.method) {
"state" -> stateNative(result)
...
...
@@ -101,8 +100,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
val preview = Preview.Builder().build().apply { setSurfaceProvider(surfaceProvider) }
// Analyzer
val analyzer = ImageAnalysis.Analyzer { imageProxy -> // YUV_420_888 format
// when (analyzeMode) {
// AnalyzeMode.BARCODE -> {
when (analyzeMode) {
AnalyzeMode.BARCODE -> {
val mediaImage = imageProxy.image ?: return@Analyzer
val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
val scanner = BarcodeScanning.getClient()
...
...
@@ -115,9 +114,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
}
.addOnFailureListener { e -> Log.e(TAG, e.message, e) }
.addOnCompleteListener { imageProxy.close() }
// }
// else -> imageProxy.close()
// }
}
else -> imageProxy.close()
}
}
val analysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
...
...
@@ -152,7 +151,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
}
private fun analyzeNative(call: MethodCall, result: MethodChannel.Result) {
//
analyzeMode = call.arguments as Int
analyzeMode = call.arguments as Int
result.success(null)
}
...
...
@@ -162,6 +161,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
cameraProvider!!.unbindAll()
textureEntry!!.release()
analyzeMode = AnalyzeMode.NONE
camera = null
textureEntry = null
cameraProvider = null
...
...
@@ -169,14 +169,13 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
result.success(null)
}
}
//
//
//@IntDef(AnalyzeMode.NONE, AnalyzeMode.BARCODE)
//@Target(AnnotationTarget.FIELD)
//@Retention(AnnotationRetention.SOURCE)
//annotation class AnalyzeMode {
// companion object {
// const val NONE = 0
// const val BARCODE = 1
// }
//}
\ No newline at end of file
@IntDef(AnalyzeMode.NONE, AnalyzeMode.BARCODE)
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.SOURCE)
annotation class AnalyzeMode {
companion object {
const val NONE = 0
const val BARCODE = 1
}
}
\ No newline at end of file
...
...
example/android/app/build.gradle
View file @
9750c75
...
...
@@ -24,8 +24,6 @@ if (flutterVersionName == null) {
apply
plugin:
'com.android.application'
apply
plugin:
'kotlin-android'
apply
from:
"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
// Apply the Performance Monitoring plugin
apply
plugin:
'com.google.firebase.firebase-perf'
android
{
compileSdkVersion
flutter
.
compileSdkVersion
...
...
@@ -59,6 +57,7 @@ android {
signingConfig
signingConfigs
.
debug
}
}
namespace
'dev.steenbakker.mobile_scanner_example'
}
flutter
{
...
...
example/android/app/src/debug/AndroidManifest.xml
View file @
9750c75
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"dev.steenbakker.mobile_scanner_example"
>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
...
...
example/android/app/src/main/AndroidManifest.xml
View file @
9750c75
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"dev.steenbakker.mobile_scanner_example"
>
package=
"dev.steenbakker.mobile_scanner.example"
>
<application
android:label=
"mobile_scanner_example"
android:name=
"${applicationName}"
android:icon=
"@mipmap/ic_launcher"
>
<activity
android:name=
"
.Main
Activity"
android:name=
"
io.flutter.embedding.android.Flutter
Activity"
android:exported=
"true"
android:launchMode=
"singleTop"
android:theme=
"@style/LaunchTheme"
...
...
example/android/app/src/profile/AndroidManifest.xml
View file @
9750c75
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"dev.steenbakker.mobile_scanner_example"
>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
...
...
example/android/build.gradle
View file @
9750c75
...
...
@@ -6,8 +6,7 @@ buildscript {
}
dependencies
{
classpath
'com.google.firebase:perf-plugin:1.4.0'
// Performanc
classpath
'com.android.tools.build:gradle:7.0.4'
classpath
'com.android.tools.build:gradle:7.1.0'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
...
...
example/lib/main.dart
View file @
9750c75
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
...
...
@@ -17,76 +16,75 @@ class AnalyzeView extends StatefulWidget {
class
_AnalyzeViewState
extends
State
<
AnalyzeView
>
with
SingleTickerProviderStateMixin
{
List
<
Offset
>
points
=
[];
CameraController
cameraController
=
CameraController
();
String
?
barcode
=
null
;
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
home:
Scaffold
(
body:
Builder
(
builder:
(
context
)
{
return
Stack
(
children:
[
CameraView
(
cameraController
,
onDetect:
(
barcode
,
args
)
{
if
(
this
.
barcode
!=
barcode
.
rawValue
)
{
this
.
barcode
=
barcode
.
rawValue
;
if
(
barcode
.
corners
!=
null
)
{
debugPrint
(
'Size:
${MediaQuery.of(context).size}
'
);
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'
${barcode.rawValue}
'
),
duration:
Duration
(
milliseconds:
200
),
animation:
null
,));
setState
(()
{
final
List
<
Offset
>
points
=
[];
double
factorWidth
=
args
.
size
.
width
/
520
;
double
factorHeight
=
args
.
size
.
height
/
640
;
for
(
var
point
in
barcode
.
corners
!)
{
points
.
add
(
Offset
(
point
.
dx
*
factorWidth
,
point
.
dy
*
factorHeight
));
}
this
.
points
=
points
;
});
body:
Builder
(
builder:
(
context
)
{
return
Stack
(
children:
[
CameraView
(
controller:
cameraController
,
onDetect:
(
barcode
,
args
)
{
if
(
this
.
barcode
!=
barcode
.
rawValue
)
{
this
.
barcode
=
barcode
.
rawValue
;
if
(
barcode
.
corners
!=
null
)
{
debugPrint
(
'Size:
${MediaQuery.of(context).size}
'
);
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'
${barcode.rawValue}
'
),
duration:
Duration
(
milliseconds:
200
),
animation:
null
,
));
setState
(()
{
final
List
<
Offset
>
points
=
[];
double
factorWidth
=
args
.
size
.
width
/
520
;
double
factorHeight
=
args
.
size
.
height
/
640
;
for
(
var
point
in
barcode
.
corners
!)
{
points
.
add
(
Offset
(
point
.
dx
*
factorWidth
,
point
.
dy
*
factorHeight
));
}
this
.
points
=
points
;
});
}
}
}
// Default 640 x480
}),
Container
(
// width: 400,
// height: 400,
child:
CustomPaint
(
painter:
OpenPainter
(
points
),
),
// Default 640 x480
}),
Container
(
// width: 400,
// height: 400,
child:
CustomPaint
(
painter:
OpenPainter
(
points
),
),
Container
(
alignment:
Alignment
.
bottomCenter
,
margin:
EdgeInsets
.
only
(
bottom:
80.0
),
child:
IconButton
(
icon:
ValueListenableBuilder
(
valueListenable:
cameraController
.
torchState
,
builder:
(
context
,
state
,
child
)
{
final
color
=
state
==
TorchState
.
off
?
Colors
.
grey
:
Colors
.
white
;
return
Icon
(
Icons
.
bolt
,
color:
color
);
},
),
iconSize:
32.0
,
onPressed:
()
=>
cameraController
.
torch
(),
),
Container
(
alignment:
Alignment
.
bottomCenter
,
margin:
EdgeInsets
.
only
(
bottom:
80.0
),
child:
IconButton
(
icon:
ValueListenableBuilder
(
valueListenable:
cameraController
.
torchState
,
builder:
(
context
,
state
,
child
)
{
final
color
=
state
==
TorchState
.
off
?
Colors
.
grey
:
Colors
.
white
;
return
Icon
(
Icons
.
bolt
,
color:
color
);
},
),
iconSize:
32.0
,
onPressed:
()
=>
cameraController
.
torch
(),
),
],
);
}
),
),
],
);
}),
),
);
}
@override
void
dispose
()
{
cameraController
.
dispose
();
...
...
lib/src/camera_controller.dart
View file @
9750c75
...
...
@@ -4,11 +4,20 @@ import 'package:flutter/cupertino.dart';
import
'package:flutter/services.dart'
;
import
'camera_args.dart'
;
import
'camera_facing.dart'
;
import
'objects/barcode.dart'
;
import
'torch_state.dart'
;
import
'util.dart'
;
/// The facing of a camera.
enum
CameraFacing
{
/// Front facing camera.
front
,
/// Back facing camera.
back
,
}
/// A camera controller.
abstract
class
CameraController
{
/// Arguments for [CameraView].
...
...
lib/src/camera_facing.dart
deleted
100644 → 0
View file @
f83a27f
/// The facing of a camera.
enum
CameraFacing
{
/// Front facing camera.
front
,
/// Back facing camera.
back
,
}
lib/src/camera_view.dart
View file @
9750c75
...
...
@@ -2,44 +2,60 @@ import 'package:flutter/material.dart';
import
'package:mobile_scanner/mobile_scanner.dart'
;
import
'camera_args.dart'
;
import
'camera_controller.dart'
;
/// A widget showing a live camera preview.
class
CameraView
extends
State
less
Widget
{
class
CameraView
extends
State
ful
Widget
{
/// The controller of the camera.
final
CameraController
controller
;
final
CameraController
?
controller
;
final
Function
(
Barcode
barcode
,
CameraArgs
args
)?
onDetect
;
/// Create a [CameraView] with a [controller], the [controller] must has been initialized.
CameraView
(
this
.
controller
,
{
this
.
onDetect
});
const
CameraView
({
Key
?
key
,
this
.
onDetect
,
this
.
controller
})
:
super
(
key:
key
);
@override
State
<
CameraView
>
createState
()
=>
_CameraViewState
();
}
class
_CameraViewState
extends
State
<
CameraView
>
{
late
CameraController
controller
;
@override
initState
()
{
super
.
initState
();
controller
=
widget
.
controller
??
CameraController
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
ValueListenableBuilder
(
valueListenable:
controller
.
args
,
builder:
(
context
,
value
,
child
)
=>
_build
(
context
,
value
as
CameraArgs
?),
);
}
valueListenable:
controller
.
args
,
builder:
(
context
,
value
,
child
)
{
value
=
value
as
CameraArgs
?;
if
(
value
==
null
)
{
return
Container
(
color:
Colors
.
black
);
}
else
{
controller
.
barcodes
.
listen
((
a
)
=>
widget
.
onDetect
!(
a
,
value
as
CameraArgs
));
Widget
_build
(
BuildContext
context
,
CameraArgs
?
value
)
{
if
(
value
==
null
)
{
return
Container
(
color:
Colors
.
black
);
}
else
{
return
ClipRect
(
child:
Transform
.
scale
(
scale:
value
.
size
.
fill
(
MediaQuery
.
of
(
context
).
size
),
child:
Center
(
child:
AspectRatio
(
aspectRatio:
value
.
size
.
aspectRatio
,
child:
Texture
(
textureId:
value
.
textureId
),
),
),
),
);
}
});
}
controller
.
barcodes
.
listen
((
a
)
=>
onDetect
!(
a
,
value
));
return
ClipRect
(
child:
Transform
.
scale
(
scale:
value
.
size
.
fill
(
MediaQuery
.
of
(
context
)
.
size
),
child:
Center
(
child:
AspectRatio
(
aspectRatio:
value
.
size
.
aspectRatio
,
child:
Texture
(
textureId:
value
.
textureId
),
),
),
),
);
}
@override
void
dispose
()
{
controller
.
dispose
();
super
.
dispose
();
}
}
...
...
lib/src/mobile_scanner.dart
View file @
9750c75
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:mobile_scanner/src/mobile_scanner_handler.dart'
;
import
'package:mobile_scanner/src/objects/preview_details.dart'
;
import
'mobile_scanner_preview.dart'
;
import
'objects/barcode_formats.dart'
;
typedef
ErrorCallback
=
Widget
Function
(
BuildContext
context
,
Object
?
error
);
Text
_defaultNotStartedBuilder
(
context
)
=>
const
Text
(
"Camera Loading ..."
);
Text
_defaultOffscreenBuilder
(
context
)
=>
const
Text
(
"Camera Paused."
);
Text
_defaultOnError
(
BuildContext
context
,
Object
?
error
)
{
debugPrint
(
"Error reading from camera:
$error
"
);
return
const
Text
(
"Error reading from camera..."
);
}
class
MobileScanner
extends
StatefulWidget
{
const
MobileScanner
(
{
Key
?
key
,
required
this
.
qrCodeCallback
,
this
.
child
,
this
.
fit
=
BoxFit
.
cover
,
WidgetBuilder
?
notStartedBuilder
,
WidgetBuilder
?
offscreenBuilder
,
ErrorCallback
?
onError
,
this
.
formats
,
this
.
rearLens
=
true
,
this
.
manualFocus
=
false
})
:
notStartedBuilder
=
notStartedBuilder
??
_defaultNotStartedBuilder
,
offscreenBuilder
=
offscreenBuilder
??
notStartedBuilder
??
_defaultOffscreenBuilder
,
onError
=
onError
??
_defaultOnError
,
super
(
key:
key
);
final
BoxFit
fit
;
final
ValueChanged
<
String
?>
qrCodeCallback
;
final
Widget
?
child
;
final
WidgetBuilder
notStartedBuilder
;
final
WidgetBuilder
offscreenBuilder
;
final
ErrorCallback
onError
;
final
List
<
BarcodeFormats
>?
formats
;
final
bool
rearLens
;
final
bool
manualFocus
;
static
void
toggleFlash
()
{
MobileScannerHandler
.
toggleFlash
();
}
static
void
flipCamera
()
{
MobileScannerHandler
.
switchCamera
();
}
@override
_MobileScannerState
createState
()
=>
_MobileScannerState
();
}
class
_MobileScannerState
extends
State
<
MobileScanner
>
with
WidgetsBindingObserver
{
bool
onScreen
=
true
;
Future
<
PreviewDetails
>?
_previewDetails
;
@override
void
initState
()
{
super
.
initState
();
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
@override
void
dispose
()
{
WidgetsBinding
.
instance
!.
removeObserver
(
this
);
super
.
dispose
();
}
@override
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
if
(
state
==
AppLifecycleState
.
resumed
)
{
setState
(()
=>
onScreen
=
true
);
}
else
{
if
(
_previewDetails
!=
null
&&
onScreen
)
{
MobileScannerHandler
.
stop
();
}
setState
(()
{
onScreen
=
false
;
_previewDetails
=
null
;
});
}
}
Future
<
PreviewDetails
>
_initPreview
(
num
width
,
num
height
)
async
{
final
devicePixelRatio
=
MediaQuery
.
of
(
context
).
devicePixelRatio
;
return
await
MobileScannerHandler
.
start
(
width:
(
devicePixelRatio
*
width
.
toInt
()).
ceil
(),
height:
(
devicePixelRatio
*
height
.
toInt
()).
ceil
(),
qrCodeHandler:
widget
.
qrCodeCallback
,
formats:
widget
.
formats
,
);
}
void
switchCamera
()
{
MobileScannerHandler
.
rearLens
=
!
MobileScannerHandler
.
rearLens
;
restart
();
}
void
switchFocus
()
{
MobileScannerHandler
.
manualFocus
=
!
MobileScannerHandler
.
manualFocus
;
restart
();
}
/// This method can be used to restart scanning
/// the event that it was paused.
Future
<
void
>
restart
()
async
{
await
MobileScannerHandler
.
stop
();
setState
(()
{
_previewDetails
=
null
;
});
}
/// This method can be used to manually stop the
/// camera.
Future
<
void
>
stop
()
async
{
await
MobileScannerHandler
.
stop
();
}
@override
deactivate
()
{
super
.
deactivate
();
MobileScannerHandler
.
stop
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
LayoutBuilder
(
builder:
(
BuildContext
context
,
BoxConstraints
constraints
)
{
if
(
_previewDetails
==
null
&&
onScreen
)
{
_previewDetails
=
_initPreview
(
constraints
.
maxWidth
,
constraints
.
maxHeight
);
}
else
if
(!
onScreen
)
{
return
widget
.
offscreenBuilder
(
context
);
}
return
FutureBuilder
(
future:
_previewDetails
,
builder:
(
BuildContext
context
,
AsyncSnapshot
<
PreviewDetails
>
details
)
{
switch
(
details
.
connectionState
)
{
case
ConnectionState
.
none
:
case
ConnectionState
.
waiting
:
return
widget
.
notStartedBuilder
(
context
);
case
ConnectionState
.
done
:
if
(
details
.
hasError
)
{
debugPrint
(
details
.
error
.
toString
());
return
widget
.
onError
(
context
,
details
.
error
);
}
Widget
preview
=
SizedBox
(
width:
constraints
.
maxWidth
,
height:
constraints
.
maxHeight
,
child:
Preview
(
previewDetails:
details
.
data
!,
targetWidth:
constraints
.
maxWidth
,
targetHeight:
constraints
.
maxHeight
,
fit:
widget
.
fit
,
),
);
if
(
widget
.
child
!=
null
)
{
return
Stack
(
children:
[
preview
,
widget
.
child
!,
],
);
}
return
preview
;
default
:
throw
AssertionError
(
"
${details.connectionState}
not supported."
);
}
},
);
});
}
}
// import 'dart:async';
// import 'package:flutter/material.dart';
// import 'package:mobile_scanner/src/mobile_scanner_handler.dart';
// import 'package:mobile_scanner/src/objects/preview_details.dart';
//
// import 'mobile_scanner_preview.dart';
// import 'objects/barcode_formats.dart';
//
// typedef ErrorCallback = Widget Function(BuildContext context, Object? error);
//
// Text _defaultNotStartedBuilder(context) => const Text("Camera Loading ...");
// Text _defaultOffscreenBuilder(context) => const Text("Camera Paused.");
// Text _defaultOnError(BuildContext context, Object? error) {
// debugPrint("Error reading from camera: $error");
// return const Text("Error reading from camera...");
// }
//
// class MobileScanner extends StatefulWidget {
// const MobileScanner(
// {Key? key,
// required this.qrCodeCallback,
// this.child,
// this.fit = BoxFit.cover,
// WidgetBuilder? notStartedBuilder,
// WidgetBuilder? offscreenBuilder,
// ErrorCallback? onError,
// this.formats,
// this.rearLens = true,
// this.manualFocus = false})
// : notStartedBuilder = notStartedBuilder ?? _defaultNotStartedBuilder,
// offscreenBuilder =
// offscreenBuilder ?? notStartedBuilder ?? _defaultOffscreenBuilder,
// onError = onError ?? _defaultOnError,
// super(key: key);
//
// final BoxFit fit;
// final ValueChanged<String?> qrCodeCallback;
// final Widget? child;
// final WidgetBuilder notStartedBuilder;
// final WidgetBuilder offscreenBuilder;
// final ErrorCallback onError;
// final List<BarcodeFormats>? formats;
// final bool rearLens;
// final bool manualFocus;
//
// static void toggleFlash() {
// MobileScannerHandler.toggleFlash();
// }
//
// static void flipCamera() {
// MobileScannerHandler.switchCamera();
// }
//
// @override
// _MobileScannerState createState() => _MobileScannerState();
// }
//
// class _MobileScannerState extends State<MobileScanner>
// with WidgetsBindingObserver {
//
// bool onScreen = true;
// Future<PreviewDetails>? _previewDetails;
//
// @override
// void initState() {
// super.initState();
// WidgetsBinding.instance!.addObserver(this);
// }
//
// @override
// void dispose() {
// WidgetsBinding.instance!.removeObserver(this);
// super.dispose();
// }
//
// @override
// void didChangeAppLifecycleState(AppLifecycleState state) {
// if (state == AppLifecycleState.resumed) {
// setState(() => onScreen = true);
// } else {
// if (_previewDetails != null && onScreen) {
// MobileScannerHandler.stop();
// }
// setState(() {
// onScreen = false;
// _previewDetails = null;
// });
// }
// }
//
// Future<PreviewDetails> _initPreview(num width, num height) async {
// final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
// return await MobileScannerHandler.start(
// width: (devicePixelRatio * width.toInt()).ceil(),
// height: (devicePixelRatio * height.toInt()).ceil(),
// qrCodeHandler: widget.qrCodeCallback,
// formats: widget.formats,
// );
// }
//
// void switchCamera() {
// MobileScannerHandler.rearLens = !MobileScannerHandler.rearLens;
// restart();
// }
//
//
// void switchFocus() {
// MobileScannerHandler.manualFocus = !MobileScannerHandler.manualFocus;
// restart();
// }
//
// /// This method can be used to restart scanning
// /// the event that it was paused.
// Future<void> restart() async {
// await MobileScannerHandler.stop();
// setState(() {
// _previewDetails = null;
// });
// }
//
// /// This method can be used to manually stop the
// /// camera.
// Future<void> stop() async {
// await MobileScannerHandler.stop();
// }
//
// @override
// deactivate() {
// super.deactivate();
// MobileScannerHandler.stop();
// }
//
// @override
// Widget build(BuildContext context) {
// return LayoutBuilder(
// builder: (BuildContext context, BoxConstraints constraints) {
// if (_previewDetails == null && onScreen) {
// _previewDetails =
// _initPreview(constraints.maxWidth, constraints.maxHeight);
// } else if (!onScreen) {
// return widget.offscreenBuilder(context);
// }
//
// return FutureBuilder(
// future: _previewDetails,
// builder: (BuildContext context, AsyncSnapshot<PreviewDetails> details) {
// switch (details.connectionState) {
// case ConnectionState.none:
// case ConnectionState.waiting:
// return widget.notStartedBuilder(context);
// case ConnectionState.done:
// if (details.hasError) {
// debugPrint(details.error.toString());
// return widget.onError(context, details.error);
// }
// Widget preview = SizedBox(
// width: constraints.maxWidth,
// height: constraints.maxHeight,
// child: Preview(
// previewDetails: details.data!,
// targetWidth: constraints.maxWidth,
// targetHeight: constraints.maxHeight,
// fit: widget.fit,
// ),
// );
//
// if (widget.child != null) {
// return Stack(
// children: [
// preview,
// widget.child!,
// ],
// );
// }
// return preview;
//
// default:
// throw AssertionError("${details.connectionState} not supported.");
// }
// },
// );
// });
// }
// }
...
...
lib/src/mobile_scanner_preview.dart
View file @
9750c75
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:mobile_scanner/src/objects/preview_details.dart'
;
import
'package:native_device_orientation/native_device_orientation.dart'
;
import
'package:sensors_plus/sensors_plus.dart'
;
class
Preview
extends
StatefulWidget
{
final
double
width
,
height
;
final
double
targetWidth
,
targetHeight
;
final
int
?
textureId
;
final
int
?
sensorOrientation
;
final
BoxFit
fit
;
Preview
({
Key
?
key
,
required
PreviewDetails
previewDetails
,
required
this
.
targetWidth
,
required
this
.
targetHeight
,
required
this
.
fit
,
})
:
textureId
=
previewDetails
.
textureId
,
width
=
previewDetails
.
width
!.
toDouble
(),
height
=
previewDetails
.
height
!.
toDouble
(),
sensorOrientation
=
previewDetails
.
sensorOrientation
as
int
?,
super
(
key:
key
);
@override
State
<
Preview
>
createState
()
=>
_PreviewState
();
}
class
_PreviewState
extends
State
<
Preview
>
{
final
_streamSubscriptions
=
<
StreamSubscription
<
dynamic
>>[];
bool
landscapeLeft
=
false
;
@override
void
initState
()
{
super
.
initState
();
_streamSubscriptions
.
add
(
magnetometerEvents
.
listen
(
(
MagnetometerEvent
event
)
{
if
(
event
.
x
<=
0
)
{
landscapeLeft
=
true
;
}
else
{
landscapeLeft
=
false
;
}
},
),
);
}
@override
void
dispose
()
{
super
.
dispose
();
for
(
final
subscription
in
_streamSubscriptions
)
{
subscription
.
cancel
();
}
}
int
_getRotationCompensation
(
NativeDeviceOrientation
nativeOrientation
)
{
int
nativeRotation
=
0
;
switch
(
nativeOrientation
)
{
case
NativeDeviceOrientation
.
portraitUp
:
nativeRotation
=
0
;
break
;
case
NativeDeviceOrientation
.
landscapeRight
:
nativeRotation
=
90
;
break
;
case
NativeDeviceOrientation
.
portraitDown
:
nativeRotation
=
180
;
break
;
case
NativeDeviceOrientation
.
landscapeLeft
:
nativeRotation
=
270
;
break
;
case
NativeDeviceOrientation
.
unknown
:
default
:
break
;
}
return
((
nativeRotation
-
widget
.
sensorOrientation
!
+
450
)
%
360
)
~/
90
;
}
@override
Widget
build
(
BuildContext
context
)
{
final
orientation
=
MediaQuery
.
of
(
context
).
orientation
;
double
frameHeight
=
widget
.
width
;
double
frameWidth
=
widget
.
height
;
return
ClipRect
(
child:
FittedBox
(
fit:
widget
.
fit
,
child:
RotatedBox
(
quarterTurns:
orientation
==
Orientation
.
landscape
?
landscapeLeft
?
1
:
3
:
0
,
child:
SizedBox
(
width:
frameWidth
,
height:
frameHeight
,
child:
Texture
(
textureId:
widget
.
textureId
!),
),
),
),
);
return
NativeDeviceOrientationReader
(
builder:
(
context
)
{
var
nativeOrientation
=
NativeDeviceOrientationReader
.
orientation
(
context
);
double
frameHeight
=
widget
.
width
;
double
frameWidth
=
widget
.
height
;
return
ClipRect
(
child:
FittedBox
(
fit:
widget
.
fit
,
child:
RotatedBox
(
quarterTurns:
_getRotationCompensation
(
nativeOrientation
),
child:
SizedBox
(
width:
frameWidth
,
height:
frameHeight
,
child:
Texture
(
textureId:
widget
.
textureId
!),
),
),
),
);
},
);
}
}
// import 'dart:async';
//
// import 'package:flutter/material.dart';
// import 'package:mobile_scanner/src/objects/preview_details.dart';
//
// class Preview extends StatefulWidget {
// final double width, height;
// final double targetWidth, targetHeight;
// final int? textureId;
// final int? sensorOrientation;
// final BoxFit fit;
//
// Preview({
// Key? key,
// required PreviewDetails previewDetails,
// required this.targetWidth,
// required this.targetHeight,
// required this.fit,
// }) : textureId = previewDetails.textureId,
// width = previewDetails.width!.toDouble(),
// height = previewDetails.height!.toDouble(),
// sensorOrientation = previewDetails.sensorOrientation as int?,
// super(key: key);
//
// @override
// State<Preview> createState() => _PreviewState();
// }
//
// class _PreviewState extends State<Preview> {
//
// final _streamSubscriptions = <StreamSubscription<dynamic>>[];
// bool landscapeLeft = false;
//
// @override
// void initState() {
// super.initState();
// _streamSubscriptions.add(
// magnetometerEvents.listen(
// (MagnetometerEvent event) {
// if (event.x <= 0) {
// landscapeLeft = true;
// } else {
// landscapeLeft = false;
// }
// },
// ),
// );
// }
//
// @override
// void dispose() {
// super.dispose();
// for (final subscription in _streamSubscriptions) {
// subscription.cancel();
// }
// }
//
//
// int _getRotationCompensation(NativeDeviceOrientation nativeOrientation) {
// int nativeRotation = 0;
// switch (nativeOrientation) {
// case NativeDeviceOrientation.portraitUp:
// nativeRotation = 0;
// break;
// case NativeDeviceOrientation.landscapeRight:
// nativeRotation = 90;
// break;
// case NativeDeviceOrientation.portraitDown:
// nativeRotation = 180;
// break;
// case NativeDeviceOrientation.landscapeLeft:
// nativeRotation = 270;
// break;
// case NativeDeviceOrientation.unknown:
// default:
// break;
// }
//
// return ((nativeRotation - widget.sensorOrientation! + 450) % 360) ~/ 90;
// }
//
// @override
// Widget build(BuildContext context) {
// final orientation = MediaQuery.of(context).orientation;
// double frameHeight = widget.width;
// double frameWidth = widget.height;
//
// return ClipRect(
// child: FittedBox(
// fit: widget.fit,
// child: RotatedBox(
// quarterTurns: orientation == Orientation.landscape ? landscapeLeft ? 1 : 3 : 0,
// child: SizedBox(
// width: frameWidth,
// height: frameHeight,
// child: Texture(textureId: widget.textureId!),
// ),
// ),
// ),
// );
//
// return NativeDeviceOrientationReader(
// builder: (context) {
// var nativeOrientation =
// NativeDeviceOrientationReader.orientation(context);
//
// double frameHeight = widget.width;
// double frameWidth = widget.height;
//
// return ClipRect(
// child: FittedBox(
// fit: widget.fit,
// child: RotatedBox(
// quarterTurns: _getRotationCompensation(nativeOrientation),
// child: SizedBox(
// width: frameWidth,
// height: frameHeight,
// child: Texture(textureId: widget.textureId!),
// ),
// ),
// ),
// );
// },
// );
// }
// }
...
...
pubspec.yaml
View file @
9750c75
...
...
@@ -8,25 +8,15 @@ environment:
flutter
:
"
>=2.5.0"
dependencies
:
native_device_orientation
:
^1.0.0
sensors_plus
:
^1.2.1
flutter
:
sdk
:
flutter
dev_dependencies
:
flutter_test
:
sdk
:
flutter
flutter_lints
:
^1.0.
0
flutter_lints
:
^1.0.
4
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter
:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin
:
platforms
:
android
:
...
...
@@ -36,34 +26,3 @@ flutter:
pluginClass
:
MobileScannerPlugin
macos
:
pluginClass
:
MobileScannerPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
...
...
Please
register
or
login
to post a comment