在Jetpack Compose中为QR码扫描器添加小方块焦点。

huangapple go评论73阅读模式
英文:

Adding Small Square Focus to QR Code Scanner in Jetpack Compose

问题

我已成功在Jetpack Compose中实现了QR码扫描器,但我想通过在QR码图标上添加一个小正方形焦点来提升用户体验。这个正方形焦点会直观地指示用户应该将QR码放置在哪里进行扫描。我应该如何实现这个效果并将其集成到我的QR码扫描器实现中?

通过在提供的代码中实现这些更改,我期望在相机预览的顶部看到一个小红色正方形叠加层,表示QR码的焦点区域。由于先前代码实现中存在错误,小正方形叠加层未正确绘制在相机预览的顶部,并且编译错误阻止了代码按预期工作。

英文:

I have successfully implemented a QR Code Scanner in Jetpack Compose, but I would like to enhance the user experience by adding a small square focus that hovers over the icon of the QR code. This square focus will visually indicate to the user where to position the QR code for scanning. How can I achieve this effect and integrate it into my existing QR Code Scanner implementation?

By implementing the changes in the provided code, I would expect to see a small red square overlay on top of the camera preview, indicating the focus area for the QR code.Due to errors in the previous code implementation, the small square overlay was not drawn correctly on top of the camera preview, and the compilation errors prevented the code from functioning as intended.

答案1

得分: 0

你可以尝试使用Google Code Scanner库,以下实现可能会对你有帮助:

QRCodeScanner.kt
-----------------

import kotlinx.coroutines.flow.Flow

interface QRCodeScanner {

    fun startScanning(): Flow<String?>
}
QRCodeScannerImpl.kt
--------------------

import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.android.gms.common.moduleinstall.ModuleInstallRequest
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import timber.log.Timber

class QRCodeScannerImpl(
    private val scanner: GmsBarcodeScanner,
    private val playModule: ModuleInstallClient,
) : QRCodeScanner {

    init {
        /** 检查设备上是否安装了ScannerModule,否则使用ModuleClientAPI进行安装,更多信息请访问
        https://developers.google.com/android/guides/module-install-apis **/

        playModule
            .areModulesAvailable(scanner)
            .addOnSuccessListener {
                if (!it.areModulesAvailable()) {
                    Timber.d("Downloading QR Code Module")
                    // 模块在设备上不存在,进行安装...
//                    playModule.deferredInstall(scanner)
                    val newRequest = ModuleInstallRequest.newBuilder().addApi(scanner).build()
                    playModule.installModules(newRequest)
                }
            }.addOnFailureListener {
                Timber.d("Failed to install QRCodeScanner Module")
            }
    }

    override fun startScanning(): Flow<String?> {
        return callbackFlow {
            scanner.startScan()
                .addOnSuccessListener {
                    launch {
                        send(getDetails(it))
                    }
                }.addOnFailureListener {
                    launch {
                        send(null)
                    }
                }
            awaitClose {  }
        }
    }

    private fun getDetails(barcode: Barcode): String? {
        return when (barcode.valueType) {
            Barcode.TYPE_WIFI -> {
                val ssid = barcode.wifi!!.ssid
                val password = barcode.wifi!!.password
                val type = barcode.wifi!!.encryptionType
                "ssid : $ssid, password : $password, type : $type"
            }

            Barcode.TYPE_URL -> {
                "${barcode.url?.url}"
            }

            Barcode.TYPE_PRODUCT -> {
                barcode.displayValue
            }

            Barcode.TYPE_EMAIL -> {
                "${barcode.email?.address}"
            }

            Barcode.TYPE_CONTACT_INFO -> {
                "${barcode.contactInfo?.name?.formattedName}"
            }

            Barcode.TYPE_PHONE -> {
                "${barcode.phone?.number}"
            }

            Barcode.TYPE_CALENDAR_EVENT -> {
                "${barcode.calendarEvent?.description}"
            }

            Barcode.TYPE_GEO -> {
                "${barcode.geoPoint?.lat} ${barcode.geoPoint?.lng}"
            }

            Barcode.TYPE_ISBN -> {
                barcode.displayValue
            }

            Barcode.TYPE_DRIVER_LICENSE -> {
                "${barcode.driverLicense?.firstName} ${barcode.driverLicense?.lastName }${barcode.driverLicense?.lastName}"
            }

            Barcode.TYPE_SMS -> {
                "${barcode.sms}"
            }

            Barcode.TYPE_TEXT -> {
                barcode.rawValue
            }

            Barcode.TYPE_UNKNOWN -> {
                "${barcode.rawValue}"
            }

            else -> {
                null
            }
        }
    }
}
ScannerModule.kt

import android.app.Application
import android.content.Context
import com.google.android.gms.common.moduleinstall.ModuleInstall
import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
import com.niyaj.popos.features.qrcode_scanner.data.QRCodeScannerImpl
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object ScannerModule {

    @Provides
    fun provideContext(app: Application): Context {
        return app.applicationContext
    }

    @Provides
    fun provideBarCodeOptions(): GmsBarcodeScannerOptions {
        return GmsBarcodeScannerOptions.Builder()
            .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
            .build()
    }

    @Provides
    fun provideGooglePlayModule(context: Context): ModuleInstallClient {
        return ModuleInstall.getClient(context)
    }

    @Provides
    fun provideBarCodeScanner(context: Context, options: GmsBarcodeScannerOptions): GmsBarcodeScanner {
        return GmsBarcodeScanning.getClient(context, options)
    }

    @Provides
    fun provideBarCodeScannerRepository(scanner: GmsBarcodeScanner, playModule: ModuleInstallClient): QRCodeScanner {
        return QRCodeScannerImpl(scanner, playModule)
    }
}

注意:代码中包含注释和链接,这些部分没有翻译。

英文:

You could try out Google Code Scanner Library
https://developers.google.com/ml-kit/vision/barcode-scanning/code-scanner

below implementation might help you.

QRCodeScanner.kt
-----------------
import kotlinx.coroutines.flow.Flow
interface QRCodeScanner {
fun startScanning(): Flow&lt;String?&gt;
}
QRCodeScannerImpl.kt
--------------------
import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.android.gms.common.moduleinstall.ModuleInstallRequest
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import timber.log.Timber
class QRCodeScannerImpl(
private val scanner: GmsBarcodeScanner,
private val playModule: ModuleInstallClient,
) : QRCodeScanner {
init {
/** Checking does ScannerModule is installed on the device otherwise,
install using ModuleClientAPI, for more visit 
https://developers.google.com/android/guides/module-install-apis **/
playModule
.areModulesAvailable(scanner)
.addOnSuccessListener {
if (!it.areModulesAvailable()) {
Timber.d(&quot;Downloading QR Code Module&quot;)
// Modules are not present on the device install...
//                    playModule.deferredInstall(scanner)
val newRequest = ModuleInstallRequest.newBuilder().addApi(scanner).build()
playModule.installModules(newRequest)
}
}.addOnFailureListener {
Timber.d(&quot;Failed to install QRCodeScanner Module&quot;)
}
}
override fun startScanning() : Flow&lt;String?&gt; {
return callbackFlow {
scanner.startScan()
.addOnSuccessListener {
launch {
send(getDetails(it))
}
}.addOnFailureListener {
launch {
send(null)
}
}
awaitClose {  }
}
}
private fun getDetails(barcode : Barcode) : String? {
return when (barcode.valueType) {
Barcode.TYPE_WIFI -&gt; {
val ssid = barcode.wifi!!.ssid
val password = barcode.wifi!!.password
val type = barcode.wifi!!.encryptionType
&quot;ssid : $ssid, password : $password, type : $type&quot;
}
Barcode.TYPE_URL -&gt; {
&quot;${barcode.url?.url}&quot;
}
Barcode.TYPE_PRODUCT -&gt; {
barcode.displayValue
}
Barcode.TYPE_EMAIL -&gt; {
&quot;${barcode.email?.address}&quot;
}
Barcode.TYPE_CONTACT_INFO -&gt; {
&quot;${barcode.contactInfo?.name?.formattedName}&quot;
}
Barcode.TYPE_PHONE -&gt; {
&quot;${barcode.phone?.number}&quot;
}
Barcode.TYPE_CALENDAR_EVENT -&gt; {
&quot;${barcode.calendarEvent?.description}&quot;
}
Barcode.TYPE_GEO -&gt; {
&quot;${barcode.geoPoint?.lat} ${barcode.geoPoint?.lng}&quot;
}
Barcode.TYPE_ISBN -&gt; {
barcode.displayValue
}
Barcode.TYPE_DRIVER_LICENSE -&gt; {
&quot;${barcode.driverLicense?.firstName} ${barcode.driverLicense?.lastName }${barcode.driverLicense?.lastName}&quot;
}
Barcode.TYPE_SMS -&gt; {
&quot;${barcode.sms}&quot;
}
Barcode.TYPE_TEXT -&gt; {
barcode.rawValue
}
Barcode.TYPE_UNKNOWN -&gt; {
&quot;${barcode.rawValue}&quot;
}
else -&gt; {
null
}
}
}
}
ScannerModule.kt
import android.app.Application
import android.content.Context
import com.google.android.gms.common.moduleinstall.ModuleInstall
import com.google.android.gms.common.moduleinstall.ModuleInstallClient
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
import com.niyaj.popos.features.qrcode_scanner.data.QRCodeScannerImpl
import com.niyaj.popos.features.qrcode_scanner.domain.repository.QRCodeScanner
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object ScannerModule {
@Provides
fun provideContext(app: Application):Context{
return app.applicationContext
}
@Provides
fun provideBarCodeOptions() : GmsBarcodeScannerOptions {
return GmsBarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
}
@Provides
fun provideGooglePlayModule(context: Context) : ModuleInstallClient {
return ModuleInstall.getClient(context)
}
@Provides
fun provideBarCodeScanner(context: Context, options: GmsBarcodeScannerOptions): GmsBarcodeScanner {
return GmsBarcodeScanning.getClient(context, options)
}
@Provides
fun provideBarCodeScannerRepository(scanner : GmsBarcodeScanner, playModule : ModuleInstallClient): QRCodeScanner {
return QRCodeScannerImpl(scanner, playModule)
}
}

huangapple
  • 本文由 发表于 2023年7月20日 14:32:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76727242.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定