Skip to content

Instantly share code, notes, and snippets.

@ardakazanci
Created January 1, 2024 16:55
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ardakazanci/22290e6c4f69dd5274e3edf9690c118d to your computer and use it in GitHub Desktop.
Save ardakazanci/22290e6c4f69dd5274e3edf9690c118d to your computer and use it in GitHub Desktop.
Scratch Effect - Jetpack Compose
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
SampleUiDesignForCartTheme {
ScratchCardView()
}
}
}
}
@Composable
fun ScratchCardView() {
val context = LocalContext.current
var touchPoints by remember { mutableStateOf(listOf<Offset>()) }
var bitmap by remember { mutableStateOf<ImageBitmap?>(null) }
LaunchedEffect(Unit) {
val originalBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.fill).copy(Bitmap.Config.ARGB_8888, true)
bitmap = originalBitmap.asImageBitmap()
}
Box(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
contentAlignment = Alignment.Center
) {
// Scratch Image
Image(
bitmap = ImageBitmap.imageResource(R.drawable.scratch),
contentDescription = "Scratch Image",
modifier = Modifier
.fillMaxWidth()
.height(250.dp)
)
// Fill Image Canvas
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(250.dp)
.pointerInput(Unit) {
detectDragGestures { change, _ ->
touchPoints = touchPoints + change.position
bitmap?.let {
val modifiedBitmap = erase(it.asAndroidBitmap(), touchPoints, 30F)
bitmap = modifiedBitmap.asImageBitmap()
}
}
}
) {
bitmap?.let {
drawImage(it, dstSize = IntSize(this.size.width.roundToInt(), this.size.height.roundToInt()) )
}
}
}
}
// Brush Effect for Erase
fun erase(bitmap: Bitmap, touchPoints: List<Offset>, radius: Float): Bitmap {
val paint = Paint().apply {
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
isAntiAlias = true
strokeWidth = radius
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
}
val canvas = Canvas(bitmap)
val path = Path()
touchPoints.forEachIndexed { index, point ->
val adjustedX = point.x - bitmap.width / 4
val adjustedY = point.y - bitmap.width / 4
if (index == 0) {
path.moveTo(adjustedX, adjustedY)
} else {
path.lineTo(adjustedX, adjustedY)
}
}
canvas.drawPath(path, paint)
return bitmap
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment