Android Kotlin - How to draw dotted line on a Canvas
This code demonstrates how to draw a dotted line on a canvas in an Android app written in Kotlin. It utilizes an ImageView to display the line and a SeekBar to control the width of the dots.
Explanation:
MainActivity.kt:
- The
onCreatemethod sets up the UI elements, including theImageViewandSeekBar. - It calls the
drawDottedLinefunction with the initial dot width (progress + 10) to create a bitmap with the dotted line. This bitmap is then set to theImageView. - A
SeekBar.OnSeekBarChangeListeneris implemented to update the dotted line whenever the user adjusts the seekbar. The listener retrieves the new progress value, generates a new bitmap with the updated dot width, and sets it back to theImageView.
- The
drawDottedLine function:
- This function takes an optional
dotWidthparameter (default 25f) and creates a new bitmap with a specified size and ARGB_8888 config (supports transparency). - It creates a
Canvasobject from the bitmap and sets a background color. - A
Paintobject is configured with anti-aliasing, desired color, stroke width, round stroke cap, and aDashPathEffectto create the dotted line pattern. TheDashPathEffecttakes an array of floats defining the lengths of on and off segments for the dotted line. Here, it creates a nearly rounded dot by setting on segment to one-twelfth of the dot width and the off segment to twice the dot width. - A
Pathobject defines the line path. It starts at a point and uses a quadratic bezier curve to draw a curved line across the canvas. - Finally, the
drawPathmethod on the canvas draws the defined path with the configured paint, resulting in the dotted line on the bitmap.
- This function takes an optional
activity_main.xml:
- This layout file defines the user interface for the activity. It uses a ConstraintLayout to position the
ImageViewandSeekBarelements. TheImageViewfills the width of the screen and wraps its height to fit the content. TheSeekBaris placed below theImageViewand allows the user to adjust the dot width within a range of 0 to 200.
- This layout file defines the user interface for the activity. It uses a ConstraintLayout to position the
MainActivity.kt
package com.cfsuman.kotlintutorials
import android.app.Activity
import android.graphics.*
import android.os.Bundle
import android.widget.ImageView
import android.widget.SeekBar
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// get the widgets reference from XML layout
val imageView = findViewById<ImageView>(R.id.imageView)
val seekBar = findViewById<SeekBar>(R.id.seekBar)
// show initial drawing on image view
imageView.setImageBitmap(
drawDottedLine(seekBar.progress + 10F)
)
// update drawing on seek bar change
seekBar.setOnSeekBarChangeListener(object :
SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(
seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
val bitmap = drawDottedLine(progress + 10F)
imageView.setImageBitmap(bitmap)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
}
}
// function to draw dotted line on canvas
fun drawDottedLine(
dotWidth : Float = 25F
):Bitmap?{
val bitmap = Bitmap.createBitmap(
1500,
850,
Bitmap.Config.ARGB_8888
)
// canvas for drawing
val canvas = Canvas(bitmap).apply {
drawColor(Color.parseColor("#A2A2D0"))
}
// paint to draw dotted line
val paint = Paint().apply {
isAntiAlias = true
color = Color.parseColor("#333399")
strokeWidth = dotWidth
style = Paint.Style.STROKE
strokeCap = Paint.Cap.ROUND
pathEffect = DashPathEffect(
// try to make nearly rounded shape / dot
floatArrayOf
(dotWidth / 12,
dotWidth * 2
),
0F // phase
)
}
// draw a line path
val path = Path().apply {
// move to line starting point
moveTo(100F,canvas.height / 2F)
// draw line
// add a quadratic bezier
quadTo(
100F, // x1
canvas.height / 2F, // y1
canvas.width - 100F, // x2
canvas.height / 2F // y2
)
}
// finally, draw the path (dotted line) on canvas
canvas.drawPath(path, paint)
return bitmap
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#DCDCDC"
android:padding="24dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/seekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:max="200"
android:progress="20"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
- android kotlin - RadioButton circle color programmatically
- android kotlin - TextView margin programmatically
- android kotlin - Create TextView programmatically
- android kotlin - TextView add border programmatically
- android kotlin - Coroutines get html from url
- android kotlin - Coroutines JSON from URL
- android kotlin - Coroutines with LiveData
- android kotlin - Coroutines async await all
- android kotlin - Coroutines cancel job
- android kotlin - Coroutines start undispatched
- android kotlin - Coroutines delay
- android kotlin - Canvas draw dashed line
- android kotlin - Canvas draw point
- android kotlin - Canvas erase drawing
- android kotlin - Canvas draw text shadow