英文:
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<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 {
/** 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("Downloading QR Code Module")
// Modules are not present on the device install...
// 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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论