Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master' into codeformat

flutter-beta
Timo von Holtz 5 anni fa
parent
commit
1125aef18c
32 ha cambiato i file con 471 aggiunte e 272 eliminazioni
  1. +24
    -0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. +17
    -0
      .github/ISSUE_TEMPLATE/feature_request.md
  3. BIN
      .resources/android_back_camera_flash.gif
  4. BIN
      .resources/android_front_camera_scan.gif
  5. BIN
      .resources/ios_back_camera_flash.gif
  6. BIN
      .resources/ios_front_camera_scan.gif
  7. +11
    -0
      CHANGELOG.md
  8. +17
    -6
      README.md
  9. +2
    -1
      analysis_options.yaml
  10. +6
    -5
      android/build.gradle
  11. +103
    -10
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt
  12. +18
    -72
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt
  13. +3
    -3
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt
  14. +9
    -0
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt
  15. +133
    -35
      example/README.md
  16. +5
    -6
      example/android/app/build.gradle
  17. +12
    -7
      example/android/app/src/main/AndroidManifest.xml
  18. +1
    -8
      example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt
  19. +11
    -0
      example/android/app/src/main/res/values/styles.xml
  20. +2
    -2
      example/android/build.gradle
  21. +1
    -0
      example/android/gradle.properties
  22. +2
    -2
      example/android/gradle/wrapper/gradle-wrapper.properties
  23. +17
    -48
      example/ios/Podfile
  24. +17
    -29
      example/ios/Runner.xcodeproj/project.pbxproj
  25. +0
    -8
      example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  26. +24
    -14
      example/lib/main.dart
  27. +1
    -1
      example/pubspec.yaml
  28. +13
    -6
      ios/Classes/QRView.swift
  29. +1
    -1
      ios/Classes/QRViewFactory.swift
  30. +12
    -5
      lib/src/qr_code_scanner.dart
  31. +7
    -1
      lib/src/qr_scanner_overlay_shape.dart
  32. +2
    -2
      pubspec.yaml

+ 24
- 0
.github/ISSUE_TEMPLATE/bug_report.md Vedi File

@@ -0,0 +1,24 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Flutter information**
Always provide the output of `flutter doctor -v` as it is needed in order to know on which Flutter versions the bug exists in.

**Device (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.

+ 17
- 0
.github/ISSUE_TEMPLATE/feature_request.md Vedi File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE] "
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Additional context**
Add any other context or screenshots about the feature request here.

BIN
.resources/android_back_camera_flash.gif Vedi File

Prima Dopo
Larghezza: 320  |  Altezza: 646  |  Dimensione: 12 MiB

BIN
.resources/android_front_camera_scan.gif Vedi File

Prima Dopo
Larghezza: 320  |  Altezza: 646  |  Dimensione: 4.7 MiB

BIN
.resources/ios_back_camera_flash.gif Vedi File

Prima Dopo
Larghezza: 320  |  Altezza: 566  |  Dimensione: 6.6 MiB

BIN
.resources/ios_front_camera_scan.gif Vedi File

Prima Dopo
Larghezza: 320  |  Altezza: 535  |  Dimensione: 6.9 MiB

+ 11
- 0
CHANGELOG.md Vedi File

@@ -1,3 +1,14 @@
## 0.1.0
* Changed Android minSDKversion from 24 to 21 (#170)
* Fix preview size after iPad rotation (#125)
* Implemented Android Embedding V2 (#132)
* Added cutout bottom offset (#115)
* Fix Android ActivityLifecycleCallbacks (#166)
* Fix some other small bugs

## 0.0.14
* Fix disposing camera on iOS 14 (#113)

## 0.0.13 ## 0.0.13
* Fix misalignment when QRView doesn't start from the top left (#45) * Fix misalignment when QRView doesn't start from the top left (#45)
* Fix crash on iOS when scanning returns nil (#69, #72) * Fix crash on iOS when scanning returns nil (#69, #72)


+ 17
- 6
README.md Vedi File

@@ -63,9 +63,20 @@ class _QRViewExampleState extends State<QRViewExample> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
flex: 5, flex: 5,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
child: NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
), ),
), ),
Expanded( Expanded(
@@ -120,16 +131,16 @@ controller.toggleFlash();
## Resume/Pause ## Resume/Pause
Pause camera stream and scanner. Pause camera stream and scanner.
```dart ```dart
controller.pause();
controller.pauseCamera();
``` ```
Resume camera stream and scanner. Resume camera stream and scanner.
```dart ```dart
controller.resume();
controller.resumeCamera();
``` ```




# SDK # SDK
Requires at least SDK 24 (Android 7.0).
Requires at least SDK 21 (Android 5.0).


# TODOs # TODOs
* iOS Native embedding is written to match what is supported in the framework as of the date of publication of this package. It needs to be improved as the framework support improves. * iOS Native embedding is written to match what is supported in the framework as of the date of publication of this package. It needs to be improved as the framework support improves.


+ 2
- 1
analysis_options.yaml Vedi File

@@ -1,4 +1,5 @@
include: package:pedantic/analysis_options.1.9.0.yaml
include: package:pedantic/analysis_options.yaml

linter: linter:
rules: rules:
- always_put_required_named_parameters_first - always_put_required_named_parameters_first


+ 6
- 5
android/build.gradle Vedi File

@@ -2,14 +2,14 @@ group 'net.touchcapture.qr.flutterqr'
version '1.0-SNAPSHOT' version '1.0-SNAPSHOT'


buildscript { buildscript {
ext.kotlin_version = '1.3.21'
ext.kotlin_version = '1.4.21'
repositories { repositories {
google() google()
jcenter() jcenter()
} }


dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
@@ -27,14 +27,15 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'


android { android {
compileSdkVersion 28
compileSdkVersion 30




sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
} }
defaultConfig { defaultConfig {
minSdkVersion 19
// minSdkVersion is determined by Native View.
minSdkVersion 20
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
lintOptions { lintOptions {
@@ -48,6 +49,6 @@ android {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false } implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.zxing:core:3.3.0' implementation 'com.google.zxing:core:3.3.0'
} }

+ 103
- 10
android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt Vedi File

@@ -1,25 +1,118 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformViewRegistry


class FlutterQrPlugin : MethodCallHandler {

class FlutterQrPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

var cameraPermissionContinuation: Runnable? = null
var requestingPermission = false

/** Plugin registration embedding v1 */
companion object { companion object {
@JvmStatic @JvmStatic
fun registerWith(registrar: Registrar) {
registrar
.platformViewRegistry()
.registerViewFactory(
"net.touchcapture.qr.flutterqr/qrview", QRViewFactory(registrar))
fun registerWith(registrar: PluginRegistry.Registrar) {
FlutterQrPlugin().onAttachedToV1(registrar)
} }
} }


private fun onAttachedToV1(registrar: PluginRegistry.Registrar) {
Shared.activity = registrar.activity()
registrar.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
checkAndRequestPermission(null)
onAttachedToEngines(registrar.platformViewRegistry(), registrar.messenger())
}

/** Plugin registration embedding v2 */
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
onAttachedToEngines(flutterPluginBinding.platformViewRegistry, flutterPluginBinding.binaryMessenger)
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}

/** Plugin start for both embedding v1 & v2 */
private fun onAttachedToEngines(platformViewRegistry: PlatformViewRegistry, messenger: BinaryMessenger) {
platformViewRegistry
.registerViewFactory(
"net.touchcapture.qr.flutterqr/qrview", QRViewFactory(messenger))
}

override fun onMethodCall(call: MethodCall, result: Result) { override fun onMethodCall(call: MethodCall, result: Result) {
when {
call.method == "getPlatformVersion" -> result.success("Android ${android.os.Build.VERSION.RELEASE}")
else -> result.notImplemented()
when (call.method) {
"checkAndRequestPermission" -> checkAndRequestPermission(result)
}
}

override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) {
Shared.activity = activityPluginBinding.activity
activityPluginBinding.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
checkAndRequestPermission(null)
}

override fun onDetachedFromActivityForConfigChanges() {
Shared.activity = null
}

override fun onReattachedToActivityForConfigChanges(activityPluginBinding: ActivityPluginBinding) {
Shared.activity = activityPluginBinding.activity
}

override fun onDetachedFromActivity() {
Shared.activity = null
}

private inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener {
override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean {
if (id == QRView.CAMERA_REQUEST_ID && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
cameraPermissionContinuation?.run()
return true
}
return false
}
}

private fun hasCameraPermission(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
Shared.activity?.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}

private fun checkAndRequestPermission(result: Result?) {
if (cameraPermissionContinuation != null) {
result?.error("cameraPermission", "Camera permission request ongoing", null)
}

cameraPermissionContinuation = Runnable {
cameraPermissionContinuation = null
if (!hasCameraPermission()) {
result?.error(
"cameraPermission", "MediaRecorderCamera permission not granted", null)
return@Runnable
}
}

requestingPermission = false
if (hasCameraPermission()) {
cameraPermissionContinuation?.run()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestingPermission = true
Shared.activity?.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
QRView.CAMERA_REQUEST_ID)
}
} }
} }
} }

+ 18
- 72
android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt Vedi File

@@ -1,12 +1,9 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import com.google.zxing.ResultPoint import com.google.zxing.ResultPoint
@@ -14,56 +11,51 @@ import android.hardware.Camera.CameraInfo
import com.journeyapps.barcodescanner.BarcodeCallback import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.BarcodeView import com.journeyapps.barcodescanner.BarcodeView
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformView

class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
PlatformView,MethodChannel.MethodCallHandler {
class QRView(messenger: BinaryMessenger, id: Int, private val context: Context) :
PlatformView, MethodChannel.MethodCallHandler {


companion object { companion object {
const val CAMERA_REQUEST_ID = 513469796 const val CAMERA_REQUEST_ID = 513469796
} }


var barcodeView: BarcodeView? = null var barcodeView: BarcodeView? = null
private val activity = registrar.activity()
var cameraPermissionContinuation: Runnable? = null
var requestingPermission = false

private var isTorchOn: Boolean = false private var isTorchOn: Boolean = false
val channel: MethodChannel val channel: MethodChannel


init { init {
registrar.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
channel = MethodChannel(registrar.messenger(), "net.touchcapture.qr.flutterqr/qrview_$id")
channel = MethodChannel(messenger, "net.touchcapture.qr.flutterqr/qrview_$id")
channel.setMethodCallHandler(this) channel.setMethodCallHandler(this)
checkAndRequestPermission(null)
registrar.activity().application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity?) {
if (p0 == registrar.activity()) {
Shared.activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity) {
if (p0 == Shared.activity) {
barcodeView?.pause() barcodeView?.pause()
} }
} }


override fun onActivityResumed(p0: Activity?) {
if (p0 == registrar.activity()) {
override fun onActivityResumed(p0: Activity) {
if (p0 == Shared.activity) {
barcodeView?.resume() barcodeView?.resume()
} }
} }


override fun onActivityStarted(p0: Activity?) {
override fun onActivityStarted(p0: Activity) {
} }


override fun onActivityDestroyed(p0: Activity?) {
override fun onActivityDestroyed(p0: Activity) {
} }


override fun onActivitySaveInstanceState(p0: Activity?, p1: Bundle?) {
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
} }


override fun onActivityStopped(p0: Activity?) {
override fun onActivityStopped(p0: Activity) {
} }


override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
override fun onActivityCreated(p0: Activity, p1: Bundle?) {
} }
}) })
} }
@@ -102,7 +94,7 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }


private fun hasFlash(): Boolean { private fun hasFlash(): Boolean {
return registrar.activeContext().packageManager
return context.packageManager
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH) .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
} }


@@ -120,7 +112,7 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }


private fun createBarCodeView(): BarcodeView? { private fun createBarCodeView(): BarcodeView? {
val barcode = BarcodeView(registrar.activity())
val barcode = BarcodeView(Shared.activity)
barcode.decodeContinuous( barcode.decodeContinuous(
object : BarcodeCallback { object : BarcodeCallback {
override fun barcodeResult(result: BarcodeResult) { override fun barcodeResult(result: BarcodeResult) {
@@ -139,27 +131,8 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
barcodeView = null barcodeView = null
} }


private inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener {
override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean {
if (id == CAMERA_REQUEST_ID && grantResults[0] == PERMISSION_GRANTED) {
cameraPermissionContinuation?.run()
return true
}
return false
}
}

private fun hasCameraPermission(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
activity.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}


override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call?.method){
"checkAndRequestPermission" -> {
checkAndRequestPermission(result)
}
when(call.method){
"flipCamera" -> { "flipCamera" -> {
flipCamera() flipCamera()
} }
@@ -175,33 +148,6 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }
} }


private fun checkAndRequestPermission(result: MethodChannel.Result?) {
if (cameraPermissionContinuation != null) {
result?.error("cameraPermission", "Camera permission request ongoing", null);
}

cameraPermissionContinuation = Runnable {
cameraPermissionContinuation = null
if (!hasCameraPermission()) {
result?.error(
"cameraPermission", "MediaRecorderCamera permission not granted", null)
return@Runnable
}
}


requestingPermission = false
if (hasCameraPermission()) {
cameraPermissionContinuation?.run()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestingPermission = true
registrar
.activity()
.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
CAMERA_REQUEST_ID)
}
}
}


} }

+ 3
- 3
android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt Vedi File

@@ -1,17 +1,17 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.content.Context import android.content.Context
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory import io.flutter.plugin.platform.PlatformViewFactory




class QRViewFactory(private val registrar: PluginRegistry.Registrar) :
class QRViewFactory(private val messenger: BinaryMessenger) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) { PlatformViewFactory(StandardMessageCodec.INSTANCE) {


override fun create(context: Context, id: Int, obj: Any?): PlatformView { override fun create(context: Context, id: Int, obj: Any?): PlatformView {
return QRView(registrar,id)
return QRView(messenger, id, context)
} }


} }

+ 9
- 0
android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt Vedi File

@@ -0,0 +1,9 @@
package net.touchcapture.qr.flutterqr

import android.app.Activity
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding


object Shared {
var activity: Activity? = null
}

+ 133
- 35
example/README.md Vedi File

@@ -22,11 +22,15 @@ Demonstrates how to use the qr_code_scanner plugin.
## Example: ## Example:
```dart ```dart
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart';


void main() => runApp(MaterialApp(home: QRViewExample())); void main() => runApp(MaterialApp(home: QRViewExample()));


const flashOn = 'FLASH ON';
const flashOff = 'FLASH OFF';
const frontCamera = 'FRONT CAMERA';
const backCamera = 'BACK CAMERA';

class QRViewExample extends StatefulWidget { class QRViewExample extends StatefulWidget {
const QRViewExample({ const QRViewExample({
Key key, Key key,
@@ -37,60 +41,154 @@ class QRViewExample extends StatefulWidget {
} }


class _QRViewExampleState extends State<QRViewExample> { class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
var qrText = "";
var qrText = '';
var flashState = flashOn;
var cameraState = frontCamera;
QRViewController controller; QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded( Expanded(
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
flex: 4,
),
Expanded(
child: Column(children:
<Widget>[
Text("This is the result of scan: $qrText"),
RaisedButton(
onPressed: (){
if(controller != null){
controller.flipCamera();
}
},
child: Text(
'Flip',
style: TextStyle(fontSize: 20)
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('This is the result of scan: $qrText'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.toggleFlash();
if (_isFlashOn(flashState)) {
setState(() {
flashState = flashOff;
});
} else {
setState(() {
flashState = flashOn;
});
}
}
},
child:
Text(flashState, style: TextStyle(fontSize: 20)),
),
),
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.flipCamera();
if (_isBackCamera(cameraState)) {
setState(() {
cameraState = frontCamera;
});
} else {
setState(() {
cameraState = backCamera;
});
}
}
},
child:
Text(cameraState, style: TextStyle(fontSize: 20)),
),
)
],
), ),
)
],
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
controller?.pauseCamera();
},
child: Text('pause', style: TextStyle(fontSize: 20)),
),
),
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
controller?.resumeCamera();
},
child: Text('resume', style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
), ),
flex: 1,
) )
], ],
), ),
); );
} }


bool _isFlashOn(String current) {
return flashOn == current;
}

bool _isBackCamera(String current) {
return backCamera == current;
}

Widget _buildQrView(BuildContext context) {
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)));
}

void _onQRViewCreated(QRViewController controller) { void _onQRViewCreated(QRViewController controller) {
final channel = controller.channel;
controller.init(qrKey);
this.controller = controller; this.controller = controller;
channel.setMethodCallHandler((MethodCall call) async {
switch (call.method) {
case "onRecognizeQR":
dynamic arguments = call.arguments;
setState(() {
qrText = arguments.toString();
});
}
controller.scannedDataStream.listen((scanData) {
setState(() {
qrText = scanData;
});
}); });
} }

@override
void dispose() {
controller.dispose();
super.dispose();
}
} }

``` ```






+ 5
- 6
example/android/app/build.gradle Vedi File

@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"


android { android {
compileSdkVersion 28
compileSdkVersion 30


sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
@@ -37,10 +37,10 @@ android {
} }


defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "net.touchcapture.qr.flutterqrexample" applicationId "net.touchcapture.qr.flutterqrexample"
minSdkVersion 19
targetSdkVersion 27
// minSdkVersion is determined by Native View.
minSdkVersion 20
targetSdkVersion 30
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -48,7 +48,6 @@ android {


buildTypes { buildTypes {
release { release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works. // Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
} }
@@ -61,7 +60,7 @@ flutter {


dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
} }

+ 12
- 7
example/android/app/src/main/AndroidManifest.xml Vedi File

@@ -13,7 +13,6 @@
additional functionality it is fine to subclass or reimplement additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<application <application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_qr_example" android:label="flutter_qr_example"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@@ -23,13 +22,19 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<!-- Specify that the launch screen should continue being displayed -->
<!-- until Flutter renders its first frame. -->
<meta-data <meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<!-- Theme to apply as soon as Flutter begins rendering frames -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>


+ 1
- 8
example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt Vedi File

@@ -1,13 +1,6 @@
package net.touchcapture.qr.flutterqrexample package net.touchcapture.qr.flutterqrexample


import android.os.Bundle

import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.embedding.android.FlutterActivity


class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
}
} }

+ 11
- 0
example/android/app/src/main/res/values/styles.xml Vedi File

@@ -1,8 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame --> Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.

This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>

</resources> </resources>

+ 2
- 2
example/android/build.gradle Vedi File

@@ -1,12 +1,12 @@
buildscript { buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.4.21'
repositories { repositories {
google() google()
jcenter() jcenter()
} }


dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }


+ 1
- 0
example/android/gradle.properties Vedi File

@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.enableR8=true

+ 2
- 2
example/android/gradle/wrapper/gradle-wrapper.properties Vedi File

@@ -1,6 +1,6 @@
#Thu May 14 12:19:05 CEST 2020
#Thu Dec 10 21:49:57 CET 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

+ 17
- 48
example/ios/Podfile Vedi File

@@ -4,69 +4,38 @@
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'



project 'Runner', { project 'Runner', {
'Debug' => :debug, 'Debug' => :debug,
'Profile' => :release, 'Profile' => :release,
'Release' => :release, 'Release' => :release,
} }


def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end end
pods_ary = []
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) { |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
pods_ary.push({:name => podname, :path => podpath});
else
puts "Invalid plugin specification: #{line}"
end
}
return pods_ary
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end end


target 'Runner' do
use_frameworks!
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)


# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
flutter_ios_podfile_setup


# Flutter Pods
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
if generated_xcode_build_settings.empty?
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
end
generated_xcode_build_settings.map { |p|
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
symlink = File.join('.symlinks', 'flutter')
File.symlink(File.dirname(p[:path]), symlink)
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
end
}
target 'Runner' do
use_frameworks!
use_modular_headers!


# Plugin Pods
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.map { |p|
symlink = File.join('.symlinks', 'plugins', p[:name])
File.symlink(p[:path], symlink)
pod p[:name], :path => File.join(symlink, 'ios')
}
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end end


post_install do |installer| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
flutter_additional_ios_build_settings(target)
end end
end end

+ 17
- 29
example/ios/Runner.xcodeproj/project.pbxproj Vedi File

@@ -9,12 +9,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */; }; 72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -27,8 +23,6 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -39,18 +33,19 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
4465DBB6FCA236431DE34346 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
87B204D37F3832F9BE4979B0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9994328F3BE8CB44F875A29E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */


@@ -59,8 +54,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */, 72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -71,6 +64,9 @@
0972BCF1757D16A75C3EC240 /* Pods */ = { 0972BCF1757D16A75C3EC240 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4465DBB6FCA236431DE34346 /* Pods-Runner.debug.xcconfig */,
9994328F3BE8CB44F875A29E /* Pods-Runner.release.xcconfig */,
87B204D37F3832F9BE4979B0 /* Pods-Runner.profile.xcconfig */,
); );
name = Pods; name = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -78,9 +74,7 @@
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */, 9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -174,6 +168,7 @@
TargetAttributes = { TargetAttributes = {
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1; CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 5LSCTACHT8;
LastSwiftMigration = 1020; LastSwiftMigration = 1020;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
@@ -224,7 +219,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
3C208BB7148E708611B40C3B /* [CP] Check Pods Manifest.lock */ = { 3C208BB7148E708611B40C3B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
@@ -253,17 +248,13 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = (
);
inputPaths = ( inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework",
"${BUILT_PRODUCTS_DIR}/qr_code_scanner/qr_code_scanner.framework", "${BUILT_PRODUCTS_DIR}/qr_code_scanner/qr_code_scanner.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework",
@@ -271,7 +262,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
@@ -324,7 +315,6 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = { 249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -382,7 +372,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -394,7 +384,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 4.0; SWIFT_VERSION = 4.0;
@@ -404,7 +394,6 @@
}; };
97C147031CF9000F007C117D /* Debug */ = { 97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -462,7 +451,6 @@
}; };
97C147041CF9000F007C117D /* Release */ = { 97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -522,7 +510,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -534,7 +522,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -553,7 +541,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -565,7 +553,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";


+ 0
- 8
example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings Vedi File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>

+ 24
- 14
example/lib/main.dart Vedi File

@@ -37,20 +37,7 @@ class _QRViewExampleState extends State<QRViewExample> {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
),
),
Expanded(flex: 4, child: _buildQrView(context)),
Expanded( Expanded(
flex: 1, flex: 1,
child: FittedBox( child: FittedBox(
@@ -148,6 +135,29 @@ class _QRViewExampleState extends State<QRViewExample> {
return backCamera == current; return backCamera == current;
} }


Widget _buildQrView(BuildContext context) {
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)));
}

void _onQRViewCreated(QRViewController controller) { void _onQRViewCreated(QRViewController controller) {
this.controller = controller; this.controller = controller;
controller.scannedDataStream.listen((scanData) { controller.scannedDataStream.listen((scanData) {


+ 1
- 1
example/pubspec.yaml Vedi File

@@ -3,7 +3,7 @@ description: Demonstrates how to use the flutter_qr plugin.
publish_to: 'none' publish_to: 'none'


environment: environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.3.0 <3.0.0"


dependencies: dependencies:
flutter: flutter:


+ 13
- 6
ios/Classes/QRView.swift Vedi File

@@ -23,7 +23,7 @@ public class QRView:NSObject,FlutterPlatformView {
func isCameraAvailable(success: Bool) -> Void { func isCameraAvailable(success: Bool) -> Void {
if success { if success {
do { do {
try scanner?.startScanning(resultBlock: { codes in
try scanner?.startScanning(resultBlock: { [weak self] codes in
if let codes = codes { if let codes = codes {
for code in codes { for code in codes {
var typeString: String; var typeString: String;
@@ -56,7 +56,7 @@ public class QRView:NSObject,FlutterPlatformView {


guard let stringValue = code.stringValue else { continue } guard let stringValue = code.stringValue else { continue }
let result = ["code": stringValue, "type": typeString] let result = ["code": stringValue, "type": typeString]
self.channel.invokeMethod("onRecognizeQR", arguments: result)
self?.channel.invokeMethod("onRecognizeQR", arguments: result)
} }
} }
}) })
@@ -73,7 +73,7 @@ public class QRView:NSObject,FlutterPlatformView {
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
switch(call.method){ switch(call.method){
case "setDimensions": case "setDimensions":
var arguments = call.arguments as! Dictionary<String, Double>
let arguments = call.arguments as! Dictionary<String, Double>
self?.setDimensions(width: arguments["width"] ?? 0,height: arguments["height"] ?? 0) self?.setDimensions(width: arguments["width"] ?? 0,height: arguments["height"] ?? 0)
case "flipCamera": case "flipCamera":
self?.flipCamera() self?.flipCamera()
@@ -92,9 +92,16 @@ public class QRView:NSObject,FlutterPlatformView {
} }
func setDimensions(width: Double, height: Double) -> Void { func setDimensions(width: Double, height: Double) -> Void {
previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)
scanner = MTBBarcodeScanner(previewView: previewView)
MTBBarcodeScanner.requestCameraPermission(success: isCameraAvailable)
previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)

if let sc: MTBBarcodeScanner = scanner {
if let previewLayer = sc.previewLayer {
previewLayer.frame = previewView.bounds;
}
} else {
scanner = MTBBarcodeScanner(previewView: previewView)
MTBBarcodeScanner.requestCameraPermission(success: isCameraAvailable)
}
} }
func flipCamera(){ func flipCamera(){


+ 1
- 1
ios/Classes/QRViewFactory.swift Vedi File

@@ -17,7 +17,7 @@ public class QRViewFactory: NSObject, FlutterPlatformViewFactory {
} }
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
var dictionary = args as! Dictionary<String, Double>
let dictionary = args as! Dictionary<String, Double>
return QRView(withFrame: CGRect(x: 0, y: 0, width: dictionary["width"] ?? 0, height: dictionary["height"] ?? 0), withRegistrar: registrar!,withId: viewId) return QRView(withFrame: CGRect(x: 0, y: 0, width: dictionary["width"] ?? 0, height: dictionary["height"] ?? 0), withRegistrar: registrar!,withId: viewId)
} }


+ 12
- 5
lib/src/qr_code_scanner.dart Vedi File

@@ -91,6 +91,7 @@ class QRView extends StatefulWidget {
@required Key key, @required Key key,
@required this.onQRViewCreated, @required this.onQRViewCreated,
this.overlay, this.overlay,
this.overlayMargin = EdgeInsets.zero,
}) : assert(key != null), }) : assert(key != null),
assert(onQRViewCreated != null), assert(onQRViewCreated != null),
super(key: key); super(key: key);
@@ -98,6 +99,7 @@ class QRView extends StatefulWidget {
final QRViewCreatedCallback onQRViewCreated; final QRViewCreatedCallback onQRViewCreated;


final ShapeBorder overlay; final ShapeBorder overlay;
final EdgeInsetsGeometry overlayMargin;


@override @override
State<StatefulWidget> createState() => _QRViewState(); State<StatefulWidget> createState() => _QRViewState();
@@ -111,6 +113,7 @@ class _QRViewState extends State<QRView> {
_getPlatformQrView(), _getPlatformQrView(),
if (widget.overlay != null) if (widget.overlay != null)
Container( Container(
padding: widget.overlayMargin,
decoration: ShapeDecoration( decoration: ShapeDecoration(
shape: widget.overlay, shape: widget.overlay,
), ),
@@ -177,11 +180,7 @@ class _CreationParams {
class QRViewController { class QRViewController {
QRViewController._(int id, GlobalKey qrKey) QRViewController._(int id, GlobalKey qrKey)
: _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id') { : _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id') {
if (defaultTargetPlatform == TargetPlatform.iOS) {
final RenderBox renderBox = qrKey.currentContext.findRenderObject();
_channel.invokeMethod('setDimensions',
{'width': renderBox.size.width, 'height': renderBox.size.height});
}
updateDimensions(qrKey);
_channel.setMethodCallHandler( _channel.setMethodCallHandler(
(call) async { (call) async {
switch (call.method) { switch (call.method) {
@@ -231,4 +230,12 @@ class QRViewController {
void dispose() { void dispose() {
_scanUpdateController.close(); _scanUpdateController.close();
} }

void updateDimensions(GlobalKey key) {
if (defaultTargetPlatform == TargetPlatform.iOS) {
final RenderBox renderBox = key.currentContext.findRenderObject();
_channel.invokeMethod('setDimensions',
{'width': renderBox.size.width, 'height': renderBox.size.height});
}
}
} }

+ 7
- 1
lib/src/qr_scanner_overlay_shape.dart Vedi File

@@ -10,6 +10,7 @@ class QrScannerOverlayShape extends ShapeBorder {
this.borderRadius = 0, this.borderRadius = 0,
this.borderLength = 40, this.borderLength = 40,
this.cutOutSize = 250, this.cutOutSize = 250,
this.cutOutBottomOffset = 0,
}) : assert( }) : assert(
cutOutSize != null ?? cutOutSize != null ??
cutOutSize != null ?? cutOutSize != null ??
@@ -22,6 +23,7 @@ class QrScannerOverlayShape extends ShapeBorder {
final double borderRadius; final double borderRadius;
final double borderLength; final double borderLength;
final double cutOutSize; final double cutOutSize;
final double cutOutBottomOffset;


@override @override
EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10); EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10);
@@ -86,7 +88,11 @@ class QrScannerOverlayShape extends ShapeBorder {


final cutOutRect = Rect.fromLTWH( final cutOutRect = Rect.fromLTWH(
rect.left + width / 2 - _cutOutSize / 2 + borderOffset, rect.left + width / 2 - _cutOutSize / 2 + borderOffset,
rect.top + height / 2 - _cutOutSize / 2 + borderOffset,
-cutOutBottomOffset +
rect.top +
height / 2 -
_cutOutSize / 2 +
borderOffset,
_cutOutSize - borderOffset * 2, _cutOutSize - borderOffset * 2,
_cutOutSize - borderOffset * 2, _cutOutSize - borderOffset * 2,
); );


+ 2
- 2
pubspec.yaml Vedi File

@@ -1,6 +1,6 @@
name: qr_code_scanner name: qr_code_scanner
description: QR code scanner that can be embedded inside flutter. It uses zxing in Android and MTBBarcode scanner in iOS. description: QR code scanner that can be embedded inside flutter. It uses zxing in Android and MTBBarcode scanner in iOS.
version: 0.0.13
version: 0.1.0
author: Julius Canute <juliuscanute at touchcapture.net> author: Julius Canute <juliuscanute at touchcapture.net>
homepage: https://juliuscanute.com homepage: https://juliuscanute.com
repository: https://github.com/juliuscanute/qr_code_scanner repository: https://github.com/juliuscanute/qr_code_scanner
@@ -14,7 +14,7 @@ dependencies:
sdk: flutter sdk: flutter


dev_dependencies: dev_dependencies:
pedantic: ^1.9.0
pedantic: ^1.9.2


flutter: flutter:
plugin: plugin:


Caricamento…
Annulla
Salva