How to Create a Signature Draw View in Jetpack Compose and Save It as a Drawable
Jetpack Compose makes building UIs for Android simpler and more efficient. One interesting UI component you might need is a signature draw view, where users can sign on the screen. In this article, we’ll walk through creating a signature box using Jetpack Compose and show how to save the signature as a drawable.
Screenshot of Final view
Prerequisites
- Basic understanding of Jetpack Compose
- Familiarity with StateFlow and Jetpack Compose
State
- Basic knowledge of drawing on Canvas using Compose
Step 1: Setting up the Signature Box Composable
We start by creating the SignatureBox
composable function, which contains a Canvas
for capturing the user’s signature along with other UI elements.
@Composable
fun SignatureBox(
) {
val path by remember { mutableStateOf(Path()) }
var saveBitmap by remember { mutableStateOf(false) }
var isSigned by remember { mutableStateOf(false) }
var currentPosition by remember { mutableStateOf(Offset.Unspecified) }
val density = LocalDensity.current
val canvasHeight = 300.dp
var bitmap by remember { mutableStateOf<Bitmap?>(null) }
Explanation
- We define a
Path
to capture the signature strokes and usemutableStateOf
to manage states likesaveBitmap
,isSigned
, bitmap, andcurrentPosition
.
Step 2: Creating the Signature Drawing Canvas
Here, we set up the UI and include the Canvas
component to allow users to draw their signatures using touch gestures.
Scaffold(
topBar = {
//your App bar here
}
) {
Column(
Modifier
.padding(it)
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp)
.verticalScroll(state = rememberScrollState(), enabled = true)
) {
Text(
text = stringResource(R.string.please_sign_in_the_box_below),
style = MaterialTheme.typography.titleMedium
)
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(canvasHeight)
.background(AppColors.whiteColor, RoundedCornerShape(4.dp))
.border(1.dp, AppColors.grayCommonColor, RoundedCornerShape(4.dp))
.clipToBounds()
.pointerInput(true) {
detectDragGestures(
onDragStart = { offset ->
path.moveTo(offset.x, offset.y)
isSigned = true
currentPosition = offset
},
onDrag = { change, _ ->
path.lineTo(change.position.x, change.position.y)
currentPosition = change.position
isSigned = true
}
)
}
) {
if (currentPosition != Offset.Unspecified) {
drawPath(
path = path,
color = AppColors.onPrimaryColor,
style = Stroke(
width = 4.dp.toPx(),
cap = StrokeCap.Round,
join = StrokeJoin.Round
)
)
}
if (saveBitmap) {
// create and save bitmap in remeber variable
onEvent(
bitmap = createSignatureBitmap(
path,
size.width,
with(density) { canvasHeight.toPx() }.toInt()
)
)
saveBitmap = false
}
}
RoundedBorderCenteredContentCorneredButton(buttonText = stringResource(id = R.string.done)) {
if (isSigned) saveBitmap = true
// Custom Button, you can create your own button here
}
Explanation
- Canvas: A
Canvas
with a defined size is used to draw the signature. - pointerInput: The
pointerInput
modifier captures the user's touch gestures to draw the path. onDragStart
initializes thePath
at the touch's starting point.onDrag
draws lines as the user's finger moves, creating the signature.- drawPath: The path is drawn on the canvas whenever the user interacts with it.
- Save Bitmap: If
saveBitmap
istrue
, the signature is converted into a bitmap using thecreateSignatureBitmap
function.
Step 3: Create Signature Bitmap
private fun createSignatureBitmap(
path: Path,
width: Float,
height: Int,
): Bitmap {
val bitmap = Bitmap.createBitmap(
width.roundToInt(),
height,
Bitmap.Config.ARGB_8888
)
// Create a Canvas to draw on the Bitmap
val canvas = android.graphics.Canvas(bitmap)
canvas.drawColor(android.graphics.Color.WHITE)
// Set up paint for the drawing
val paint = Paint().apply {
color = android.graphics.Color.BLACK
style = Paint.Style.STROKE
strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND
}
// Draw the signature path onto the Android Canvas
canvas.drawPath(path.asAndroidPath(), paint)
return bitmap
}
Explanation
- Creates a blank bitmap with the specified width and height.
- Initializes a
Canvas
for drawing on the bitmap. - Sets up a
Paint
object to define the stroke color and style. - Uses
drawPath
to render the signature on the canvas. - Returns the bitmap containing the drawn signature.
Wrapping Up
In this article, we covered how to create a signature draw view using Jetpack Compose’s Canvas
and gestures. Additionally, we demonstrated how to convert the drawn signature into a Bitmap
that can be uploaded or saved locally.
This SignatureBox
component can be further customized and integrated into various applications, such as accepting terms and conditions or signing waivers in fitness apps. Happy coding!