Custom View in Android

Sourav Saikia
4 min readMay 3, 2022

Let’s just make a simple Emoji Face programmatically on Android. In the end of the tutorial, you will learn to make the following view programmatically.

Before starting let’s first understand how a view is drawn in Android. Android draws the layout hierarchy in 3 layers:

  1. Measuring stage: each view must measure itself.
  2. Layout stage: each ViewGroup finds the right position for its children on the screen by using the child size and also by following the layout rules.
  3. Drawing stage: after measuring and positioning all of the views, each view happily draws itself.

Let’s get started. First of all create an Android project with Kotlin.

Create a Kotlin class named EmotionalFaceView. This class should inherit View class of Android.

class EmotionalFaceView : View

When you do this, IDE will show error . To resolve this, you will have to inherit any one of the constructors of View class to start making your custom view. Choose the second one. It helps to a create a new view from XML layout.

  1. constructor(context: Context)
    To create a new View instance from Kotlin code, it needs the Activity context.
  2. constructor(context: Context, attrs: AttributeSet)
    To create a new View instance from XML.
  3. constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int)
    To create a new view instance from XML with a style from theme attribute.
  4. constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int)
    To create a new view instance from XML with a style from theme attribute and/or style resource.

Now declare this EmotionalFaceView in your activity XML file.

<com.example.customui.EmotionalFaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/face_id"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintRight_toLeftOf="parent"/>

So if you run your app now, it will run. Now let’s do some customisation on our view.

Drawing on Canvas

At first, let’s prepare our colours for making the custom view.


private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

private var faceColor = Color.YELLOW
private var eyesColor = Color.BLACK
private var mouthColor = Color.BLACK

private var size = 320
private val mouthPath = Path()

Let’s start drawing by overriding the onDraw() method from View class. This method passes a canvas to draw our view. We have separated our logic for drawing the face background, drawing the eyes and drawing the mouth.

override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)

drawFaceBackground(canvas)
drawEyes(canvas)
drawMouth(canvas)
}

Let’s make the function for drawing the background for the face.

private fun drawFaceBackground(canvas: Canvas?) {
paint.color = faceColor
paint.style = Paint.Style.FILL

val rad = size / 2f

canvas?.drawCircle(rad, rad, rad, paint)

}

Here, we have given (x,y) coordinates for the circle along with the radius and paint for drawing the circle.

Run your app, you will see this on the app.

Let’s make the function for drawing the eyes for the emoji.

private fun drawEyes(canvas: Canvas?) {
paint.color = mouthColor
paint.style = Paint.Style.FILL

val leftEyeRect = RectF(size * 0.25f, size * 0.25f, size * 0.40f, size * 0.5f)
canvas?.drawOval(leftEyeRect, paint)

val rightEyeRect = RectF(size * 0.60f, size * 0.25f, size * 0.75f, size * 0.5f)
canvas?.drawOval(rightEyeRect, paint)

}

Here, we draw an oval with the given coordinates for left, top, right and bottom.

Once you run the app, you will see this on the app.

Let’s make the function for drawing the mouth for the emoji face.

private fun drawMouth(canvas: Canvas?) {
mouthPath.reset()

mouthPath.moveTo(size * 0.15f, size * 0.65f)
mouthPath.quadTo(size * 0.5f, size * 0.75f, size * 0.85f, size * 0.65f)
mouthPath.quadTo(size * 0.5f, size * 0.98f, size * 0.15f, size * 0.65f)
paint.color = mouthColor
paint.style = Paint.Style.FILL

canvas?.drawPath(mouthPath, paint)

}

Here, in the mouthPath.moveTo(x,y) method, you place the drawing cursor at the given coordinates. Then from that point with mouthPath.quadTo(a,b,c,d), you draw a path from (x,y) to (c,d) through (a,b).

Here is the result for you.

In the next tutorial, we will see how to make a custom rating bar.

Keep exploring custom views. Happy Learning…

--

--