alexzhirkevich/custom-qr-generator

How to custom gradient color and select background, logo from devices

Closed this issue · 6 comments

  1. select logo and background from devices
  2. custom color gradient qr
  1. Logo is a default Android android.graphics.drawable.Drawable. You just need to resolve it from the file system like anywhere alse
val uri = // your uri resolved from file picker
val drawable = if (Build.VERSION.SDK_INT < 28)
    MediaStore.Images.Media
        .getBitmap(context.contentResolver, uri.toUri())
        .copy(Bitmap.Config.ARGB_8888, false)
        .toDrawable(context.resources)
else ImageDecoder
    .decodeBitmap(ImageDecoder.createSource(context.contentResolver, uri.toUri()))
    .copy(Bitmap.Config.ARGB_8888, false)
    .toDrawable(context.resources)
  1. I don't get what do you mean
  1. I want to like this pic. Can you guide me?
    image

Unfortunately this one was created using deprecated raster method (you can check this color).
I dont actualy know if it possible to do that with the new vector method. Probably using a custom shader. You can check how android implements default gradient shaders and try to implement a custom one.

I found this in your source code:

data class LinearGradient(
val colors: List<Pair<Float, Int>>,
val orientation: Orientation
) : QrVectorColor {

    enum class Orientation(
        val start: (Float, Float) -> Pair<Float, Float>,
        val end: (Float, Float) -> Pair<Float, Float>
    ) {
        Vertical({ w, _ -> w / 2 to 0f }, { w, h -> w / 2 to h }),
        Horizontal({ _, h -> 0f to h / 2 }, { w, h -> w to h / 2 }),
        LeftDiagonal({ _, _ -> 0f to 0f }, { w, h -> w to h }),
        RightDiagonal({ _, h -> 0f to h }, { w, _ -> w to 0f })
    }

    override fun createPaint(width: Float, height: Float): Paint {
        val (x0, y0) = orientation.start(width, height)
        val (x1, y1) = orientation.end(width, height)
        return Paint().apply {
            shader = android.graphics.LinearGradient(
                x0, y0, x1, y1,
                colors.map { it.second }.toIntArray(),
                colors.map { it.first }.toFloatArray(),
                Shader.TileMode.CLAMP
            )
        }
    }
}

data class RadialGradient(
val colors: List<Pair<Float, Int>>,
@FloatRange(from = 0.0)
val radius: Float = sqrt(2f),
) : QrVectorColor {
override fun createPaint(width: Float, height: Float): Paint = Paint().apply {
shader = android.graphics.RadialGradient(
width / 2, height / 2,
maxOf(width, height) / 2 * radius.coerceAtLeast(0f),
colors.map { it.second }.toIntArray(),
colors.map { it.first }.toFloatArray(),
Shader.TileMode.CLAMP
)
}
}

data 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()
        )
    }
}

but I don't know how to use them, can you give me specific examples in each item

QrVectorColor.LinearGradient(
    colors = listOf(
        0f to Color.RED,
        1f to Color.BLUE, 
    ),
    orientation = QrVectorColor.LinearGradient.Orientation.LeftDiagonal
)

Sweep gradient works the same but without orientation parameter

I did it, thank you so much