diff --git a/android/src/main/kotlin/net/touchcapture/qr/flutterqr/CustomFramingRectBarcodeView.java b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/CustomFramingRectBarcodeView.java new file mode 100644 index 0000000..5203968 --- /dev/null +++ b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/CustomFramingRectBarcodeView.java @@ -0,0 +1,50 @@ +package net.touchcapture.qr.flutterqr; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; + +import com.journeyapps.barcodescanner.BarcodeView; +import com.journeyapps.barcodescanner.Size; + +public class CustomFramingRectBarcodeView extends BarcodeView { + + private static final int BOTTOM_OFFSET_NOT_SET_VALUE = -1; + + private int bottomOffset = BOTTOM_OFFSET_NOT_SET_VALUE; + + public CustomFramingRectBarcodeView(Context context) { + super(context); + } + + public CustomFramingRectBarcodeView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CustomFramingRectBarcodeView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected Rect calculateFramingRect(Rect container, Rect surface) { + Rect containerArea = new Rect(container); + boolean intersects = containerArea.intersect(surface);//adjusts the containerArea (code from super.calculateFramingRect) + Rect scanAreaRect = super.calculateFramingRect(container, surface); + if (bottomOffset != BOTTOM_OFFSET_NOT_SET_VALUE) {//if the setFramingRect function was called, then we shift the scan area by Y + Rect scanAreaRectWithOffset = new Rect(scanAreaRect); + scanAreaRectWithOffset.bottom -= bottomOffset; + scanAreaRectWithOffset.top -= bottomOffset; + + boolean belongsToContainer = scanAreaRectWithOffset.intersect(containerArea); + if(belongsToContainer){ + return scanAreaRectWithOffset; + } + } + return scanAreaRect; + } + + public void setFramingRect(int rectWidth, int rectHeight, int bottomOffset) { + this.bottomOffset = bottomOffset; + this.setFramingRectSize(new Size(rectWidth, rectHeight)); + } +} diff --git a/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt index 6875675..8750158 100644 --- a/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt +++ b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt @@ -3,6 +3,7 @@ package net.touchcapture.qr.flutterqr import android.Manifest import android.app.Activity import android.app.Application +import android.content.Context import android.content.pm.PackageManager import android.hardware.Camera.CameraInfo import android.os.Build @@ -12,7 +13,6 @@ import com.google.zxing.BarcodeFormat import com.google.zxing.ResultPoint import com.journeyapps.barcodescanner.BarcodeCallback import com.journeyapps.barcodescanner.BarcodeResult -import com.journeyapps.barcodescanner.BarcodeView import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel @@ -20,12 +20,12 @@ import io.flutter.plugin.common.PluginRegistry import io.flutter.plugin.platform.PlatformView -class QRView(messenger: BinaryMessenger,private val id: Int, private val params: HashMap) : +class QRView(private val context: Context, messenger: BinaryMessenger, private val id: Int, private val params: HashMap) : PlatformView, MethodChannel.MethodCallHandler, PluginRegistry.RequestPermissionsResultListener { private var isTorchOn: Boolean = false private var isPaused: Boolean = false - private var barcodeView: BarcodeView? = null + private var barcodeView: CustomFramingRectBarcodeView? = null private val channel: MethodChannel = MethodChannel(messenger, "net.touchcapture.qr.flutterqr/qrview_$id") private var permissionGranted: Boolean = false @@ -88,6 +88,11 @@ class QRView(messenger: BinaryMessenger,private val id: Int, private val params: "getCameraInfo" -> getCameraInfo(result) "getFlashInfo" -> getFlashInfo(result) "getSystemFeatures" -> getSystemFeatures(result) + "changeScanArea" -> changeScanArea( + call.argument("cutOutSize")!!, + call.argument("cutOutBottomOffset")!!, + result, + ) else -> result.notImplemented() } } @@ -190,9 +195,10 @@ class QRView(messenger: BinaryMessenger,private val id: Int, private val params: return initBarCodeView().apply {}!! } - private fun initBarCodeView(): BarcodeView? { + private fun initBarCodeView(): CustomFramingRectBarcodeView? { if (barcodeView == null) { - barcodeView = BarcodeView(Shared.activity) + barcodeView = + CustomFramingRectBarcodeView(Shared.activity) if (params["cameraFacing"] as Int == 1) { barcodeView?.cameraSettings?.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT } @@ -246,6 +252,30 @@ class QRView(messenger: BinaryMessenger,private val id: Int, private val params: } } + private fun changeScanArea( + cutOutSize: Double, + cutOutBottomOffset: Double, + result: MethodChannel.Result + ) { + setScanAreaSize(cutOutSize, cutOutSize, cutOutBottomOffset) + result.success(true) + } + + private fun setScanAreaSize( + dpScanAreaWidth: Double, + dpScanAreaHeight: Double, + dpCutOutBottomOffset: Double + ) { + barcodeView?.setFramingRect( + convertDpToPixels(dpScanAreaWidth), + convertDpToPixels(dpScanAreaHeight), + convertDpToPixels(dpCutOutBottomOffset), + ) + } + + private fun convertDpToPixels(dp: Double) = + (dp * context.resources.displayMetrics.density).toInt() + private fun hasCameraPermission(): Boolean { return permissionGranted || Build.VERSION.SDK_INT < Build.VERSION_CODES.M || diff --git a/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt index e16df1d..fcc3f58 100644 --- a/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt +++ b/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt @@ -12,7 +12,7 @@ class QRViewFactory(private val messenger: BinaryMessenger) : override fun create(context: Context, id: Int, args: Any?): PlatformView { val params = args as HashMap - return QRView(messenger, id, params) + return QRView(context, messenger, id, params) } } \ No newline at end of file diff --git a/lib/src/qr_code_scanner.dart b/lib/src/qr_code_scanner.dart index 2010755..d7f9e5c 100644 --- a/lib/src/qr_code_scanner.dart +++ b/lib/src/qr_code_scanner.dart @@ -341,6 +341,15 @@ class QRViewController { } on PlatformException catch (e) { throw CameraException(e.code, e.message); } + } else if (defaultTargetPlatform == TargetPlatform.android) { + if (overlay == null) { + return false; + } + await channel.invokeMethod('changeScanArea', { + 'cutOutSize': overlay.cutOutSize, + 'cutOutBottomOffset': overlay.cutOutBottomOffset + }); + return true; } return false; }