zxing with compose 用于 qr 扫描

zxing with compose for qr scan

我想使用 zxing 和 compose 实现 qr 扫描仪。 我尝试了很多次但都失败了。 我该如何实施?

此代码对我不起作用。

@Composable
fun AdminClubMembershipScanScreen(navController: NavHostController) {
    val context = LocalContext.current
    var scanFlag by remember {
        mutableStateOf(false)
    }

    val compoundBarcodeView = remember {
        CompoundBarcodeView(context).apply {
            val capture = CaptureManager(context as Activity, this)
            capture.initializeFromIntent(context.intent, null)
            this.setStatusText("")
            capture.decode()
            this.decodeContinuous { result ->
                if(scanFlag){
                    return@decodeContinuous
                }
                scanFlag = true
                result.text?.let { barCodeOrQr->
                    //Do something and when you finish this something
                    //put scanFlag = false to scan another item
                    scanFlag = false
                }
                //If you don't put this scanFlag = false, it will never work again.
                //you can put a delay over 2 seconds and then scanFlag = false to prevent multiple scanning 
                
            }
        }
    }

    AndroidView(
        modifier = Modifier,
        factory = { compoundBarcodeView },
    )
}

来自 Compose 互操作 documentation:

Note: Constructing the view in the AndroidView viewBlock is the best practice. Do not hold or remember a direct view reference outside AndroidView.

相反,您应该在 factory 中创建视图 - 它也会为您提供上下文,因此您不需要 LocalContext.

但它对您不起作用的主要问题是您没有启动相机。您应该调用 resume() 来这样做。所以最终代码可以是这样的:

var scanFlag by remember {
    mutableStateOf(false)
}

AndroidView(
    factory = { context ->
        CompoundBarcodeView(context).apply {
            val capture = CaptureManager(context as Activity, this)
            capture.initializeFromIntent(context.intent, null)
            this.setStatusText("")
            capture.decode()
            this.decodeContinuous { result ->
                if (scanFlag) {
                    return@decodeContinuous
                }
                println("scanFlag true")
                scanFlag = true
                result.text?.let { barCodeOrQr ->
                    println("$barCodeOrQr")
                    //Do something and when you finish this something
                    //put scanFlag = false to scan another item
                    scanFlag = false
                }
                //If you don't put this scanFlag = false, it will never work again.
                //you can put a delay over 2 seconds and then scanFlag = false to prevent multiple scanning
            }
            this.resume()
        }
    },
    modifier = Modifier
)