DEV Community

Cover image for QRKit — QRCode Generator in Compose Multiplatform for Android and iOS
Mobile innovation Network
Mobile innovation Network

Posted on

1

QRKit — QRCode Generator in Compose Multiplatform for Android and iOS

QRKit is a Kotlin Multiplatform library for Qr Generator in your Android or iOS App.

Installation

Add the dependency to your build.gradle.kts file:

commonMain.dependencies {
    implementation("network.chaintech:qr-kit:1.0.2")
}
Enter fullscreen mode Exit fullscreen mode

Example

QRCodeImage(
    url: String,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null,
    filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
    onSuccess: (ImageBitmap) -> Unit = { qrImage -> },
    onFailure: (String) -> Unit = { message -> }
)
Enter fullscreen mode Exit fullscreen mode
  • url: The URL of the QR code image to be displayed.
  • contentDescription: A textual description of the image content for accessibility purposes. It's optional.
  • modifier: Modifier for modifying the layout of the QR code image.
  • alignment: Alignment of the QR code image within its layout bounds. Default is Alignment.Center.
  • contentScale: The scale strategy for fitting the QR code image content within its layout bounds. Default is ContentScale.Fit.
  • alpha: The opacity of the QR code image, ranging from 0.0 (fully transparent) to 1.0 (fully opaque). Default is DefaultAlpha.
  • colorFilter: A color filter to apply to the QR code image. Default is null.
  • filterQuality: The quality of the filtering applied to the QR code image. Default is DrawScope.DefaultFilterQuality.
  • onSuccess: Callback invoked when the QR code image is successfully loaded and decoded, passing the decoded ImageBitmap as a parameter.
  • onFailure: Callback invoked when there's a failure during loading or decoding the QR code image, passing an error message as a parameter.

Usage

@Composable
fun QrGeneratorCompose(paddingValues: PaddingValues) {
    val scope = rememberCoroutineScope()
    var inputText by rememberSaveable { mutableStateOf("") }
    var isInputTextError by rememberSaveable { mutableStateOf(false) }
    val generatedQRCode = remember { mutableStateOf<ImageBitmap?>(null) }
    val focusManager = LocalFocusManager.current
    val snackBarHostState = LocalSnackBarHostState.current

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxSize()
            .padding(paddingValues)
            .padding(horizontal = 16.dp)
            .padding(top = 22.dp)
            .verticalScroll(rememberScrollState())
    ) {
        QRCodeImage(
            url = "https://www.google.com/",
            contentScale = ContentScale.Fit,
            contentDescription = "QR Code",
            modifier = Modifier
                .size(150.dp),
            onSuccess = { qrImage ->

            },
            onFailure = {
                scope.launch {
                    snackBarHostState.showSnackbar("Something went wrong")
                }
            }
        )

        OutlinedTextField(
            value = inputText,
            onValueChange = {
                inputText = it
                isInputTextError = inputText.isBlank()
            },
            label = { Text("Please enter text", style = MaterialTheme.typography.titleMedium) },
            textStyle = MaterialTheme.typography.bodyLarge,
            singleLine = false,
            isError = isInputTextError,
            modifier = Modifier.padding(top = 14.dp).fillMaxWidth(),
            shape = RoundedCornerShape(10),
            trailingIcon = {
                if (isInputTextError) {
                    Icon(
                        imageVector = Icons.Default.Error,
                        contentDescription = "Error",
                        tint = Color.Red
                    )
                }
            }
        )
        Spacer(modifier = Modifier.height(22.dp))
        Button(
            onClick = {
                if (inputText.isBlank()) {
                    isInputTextError = true
                    return@Button
                } else {
                    focusManager.clearFocus()
                    generateQrCode(
                        inputText,
                        onSuccess = { info, qrCode ->
                            generatedQRCode.value = qrCode
                        },
                        onFailure = {
                            scope.launch {
                                snackBarHostState.showSnackbar("Something went wrong")
                            }
                        }
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .height(54.dp),
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF007AFF)),
            shape = RoundedCornerShape(25)
        ) {
            Text(
                text = "Generate code",
                style = MaterialTheme.typography.bodyLarge,
                color = Color.White
            )
        }
        generatedQRCode.value?.let { qrCode ->
            QRCodeViewer(qrCode)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
@Composable
fun QRCodeViewer(qrCode: ImageBitmap) {
    var isLoading by rememberSaveable { mutableStateOf(true) }
    LaunchedEffect(Unit) {
        delay(500)
        isLoading = false
    }

    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize()
            .padding(vertical = 22.dp),
    ) {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .background(Color.White)
                .border(BorderStroke(3.dp, Color.Black))
                .size(250.dp)
        ) {
            if (isLoading) {
                QRCodeShimmer()
                return@Column
            }

            Image(
                bitmap = qrCode,
                contentScale = ContentScale.Fit,
                contentDescription = "QR Code",
                modifier = Modifier
                    .fillMaxSize(1f)
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
@Composable
fun QRCodeShimmer() {
    val shimmerColorShades = listOf(
        Color.Gray.copy(0.5f),
        Color.LightGray.copy(0.2f),
        Color.Gray.copy(0.5f),
    )

    val transition = rememberInfiniteTransition()
    val transitionAnim by transition.animateFloat(
        initialValue = 0f,
        targetValue = 1000f,
        animationSpec = infiniteRepeatable(
            tween(durationMillis = 1200, easing = FastOutSlowInEasing),
            RepeatMode.Reverse
        )
    )

    val brush = Brush.linearGradient(
        colors = shimmerColorShades,
        start = Offset(10f, 10f),
        end = Offset(transitionAnim, transitionAnim)
    )

    Surface(
        color = Color.Transparent,
        modifier = Modifier.alpha(.3f)
    ) {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier.size(300.dp)
        ) {
            Spacer(
                modifier = Modifier
                    .fillMaxSize()
                    .background(brush = brush)
            )
            Spacer(
                modifier = Modifier
                    .fillMaxSize(.8f)
                    .background(brush = brush)
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Final Demo:

QRKit

Conclusion

Integrating a QR code generator library enhances functionality, streamlines processes, and improves user experience in your application.

https://github.com/ChainTechNetwork/QRKitComposeMultiplatform.git

Happy coding ❤

Connect with us 👇

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs