Android library for creating QR-codes with logo, custom pixel/eyes shapes, background image. Powered by ZXing.
![]() |
![]() |
![]() |
Try library features on live app example
I'll be glad, if you leave a positive review for it in Google Play 😊
Library is also available for:
To get a Git project into your build:
Step 1. Add the JitPack repository to your build file
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Or for gradle 7+ to settings.gradle file:
dependencyResolutionManagement {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency.
dependencies {
implementation 'com.github.alexzhirkevich:custom-qr-generator:1.6.2'
// or new v2.0 alpha
implementation 'com.github.alexzhirkevich:custom-qr-generator:2.0.0-alpha01'
}
There are 2 types of QR code image - raster (deprecated) image and vector image.
Raster (deprecated). Will be removed in v2.0 since all the available features were migrated to vector |
Vector | |
---|---|---|
Output image type | android.graphics.Bitmap |
android.graphics.drawable.Drawable |
Size | ❌ Fixed | ✅ Dynamic. Based on View size |
Speed | ❌ Slow (> 500 ms in average), so must be created in advance and only in background thread. Coroutines support included | ✅ Instant. All calculations performed during Drawable.setBounds , almost instantly |
You should use deprecated Raster QR codes only if you need extra customizability or special features like in this example.
Step 1. Create QR code data. There are multiple QR types: Plain Text, Url, Wi-Fi, Email, GeoPos, Profile Cards, Phone, etc.
val data = QrData.Url("https://example.com")
Step 2. Define styling options.
val options = createQrVectorOptions {
padding = .125f
background {
drawable = ContextCompat
.getDrawable(context, R.drawable.frame)
}
logo {
drawable = ContextCompat
.getDrawable(context, R.drawable.logo)
size = .25f
padding = QrVectorLogoPadding.Natural(.2f)
shape = QrVectorLogoShape
.Circle
}
colors {
dark = QrVectorColor
.Solid(Color(0xff345288))
ball = QrVectorColor.Solid(
ContextCompat.getColor(context, R.color.your_color)
)
frame = QrVectorColor.LinearGradient(
colors = listOf(
0f to android.graphics.Color.RED,
1f to android.graphics.Color.BLUE,
),
orientation = QrVectorColor.LinearGradient
.Orientation.LeftDiagonal
)
}
shapes {
darkPixel = QrVectorPixelShape
.RoundCorners(.5f)
ball = QrVectorBallShape
.RoundCorners(.25f)
frame = QrVectorFrameShape
.RoundCorners(.25f)
}
}
val options = QrVectorOptions.Builder()
.setPadding(.3f)
.setLogo(
QrVectorLogo(
drawable = ContextCompat
.getDrawable(context, R.drawable.logo),
size = .25f,
padding = QrVectorLogoPadding.Natural(.2f),
shape = QrVectorLogoShape
.Circle
)
)
.setBackground(
QrVectorBackground(
drawable = ContextCompat
.getDrawable(context, R.drawable.frame),
)
)
.setColors(
QrVectorColors(
dark = QrVectorColor
.Solid(Color(0xff345288)),
ball = QrVectorColor.Solid(
ContextCompat.getColor(context, R.color.your_color)
),
frame = QrVectorColor.LinearGradient(
colors = listOf(
0f to android.graphics.Color.RED,
1f to android.graphics.Color.BLUE,
),
orientation = QrVectorColor.LinearGradient
.Orientation.LeftDiagonal
)
)
)
.setShapes(
QrVectorShapes(
darkPixel = QrVectorPixelShape
.RoundCorners(.5f),
ball = QrVectorBallShape
.RoundCorners(.25f),
frame = QrVectorFrameShape
.RoundCorners(.25f),
)
)
.build()
Step 3. Create QR code drawable:
val drawable : Drawable = QrCodeDrawable(data, options)
To interop with Jetpack Compose, you can use this library (recommended) or convert Drawable
to Bitmap
(not recommended).
Step 4. Press ⭐ if you liked this lib
Shapes of QR code elements can be customized using android.graphics.Path
.
For example, this is an implementation of circle pixels:
object Circle : QrVectorPixelShape {
override fun createPath(size: Float, neighbors: Neighbors): Path = Path().apply {
addCircle(size/2f, size/2f, size/2, Path.Direction.CW)
}
}
Colors of QR code elements can be customized using android.graphics.Paint
.
For example, this is an implementation of sweep gradient:
class SweepGradient(
val colors: List<Pair<Float, Int>>
) : QrVectorColor {
override fun createPaint(width: Float, height: Float): Paint =
Paint().apply {
shader = android.graphics.SweepGradient(
width / 2, height / 2,
colors.map { it.second }.toIntArray(),
colors.map { it.first }.toFloatArray()
)
}
}
![]() |
```kotlin object Circle : QrPixelShape { override fun invoke( i: Int, j: Int, elementSize: Int, neighbors: Neighbors ): Boolean { val center = elementSize/2.0 return sqrt((center-i).pow(2) + (center-j).pow(2)) < center } } val options = createQrOptions(1024, .3f) { shapes { darkPixel = Circle } } ``` |
![]() |
```kotlin //It is not scannable. Don't create such colorful QR codes object Pride : QrColor { override fun invoke( i: Int, j: Int, width : Int, height : Int ): Int { return when(6f * j/height){ in 0f..1f -> Color.RED in 1f..2f-> Color(0xffffa500) in 2f..3f-> Color.YELLOW in 3f..4f-> Color(0xff00A300) in 4f..5f-> Color.BLUE else -> Color(0xff800080) } } } val options = createQrOptions(1024) { colors { ball = Pride } } ``` |
![]() |
```kotlin val options : QrOptions = createQrOptions(1024) { shapes { darkPixel = drawShape { canvas, drawPaint, erasePaint -> val cx = canvas.width/2f val cy = canvas.height/2f val radius = minOf(cx,cy) canvas.drawCircle(cx, cy, radius, drawPaint) canvas.drawCircle(cx, cy, radius*2/2.5f, erasePaint) canvas.drawCircle(cx, cy, radius/1.75f, drawPaint) } } } ``` |
![]() |
```kotlin object CanvasColor : QrCanvasColor { override fun draw(canvas: Canvas) = with(canvas) { withRotation(135f, width/2f, height/2f) { drawRect(-width / 2f, -height / 2f, 1.5f * width, height / 2f, Paint().apply { color = Color.BLACK } ) drawRect(-width / 2f, height / 2f, 1.5f * width.toFloat(), 1.5f * height.toFloat(), Paint().apply { color = Color.DKGRAY } ) } } } ``` |
errorCorrectionLevel
explicitly to QrErrorCorrectionLevel.High
See Issue #6
You just need to resolve Drawable form file system. See this
See Issue #13
See Issue #19