Surface View vs View — the differences

Elye

In this article, I’ll share with you what is SurfaceView and the differences with normal View in term of implementing it.

Background

We knew we could create animated drawing on a view as per in my tutorial below

However, when we use onDraw to perform all the animation calculation, we are doing it on the UI thread. If we also need to handle user interaction, this will be a challenge, as the animation calculation has taken up all the processing time, this will make the user interaction unresponsive.

I’m providing a simple illustration below, where I put my animated view in a scroll view, and I explicitly sleep 0.5s for each animation (simulating slow processing).

canvas.drawRect(...)
Thread.sleep(500)
moveRectRight()

When I scroll the view up and down, look at how slow the view response to it.

In knowing that, Google has provided something called SurfaceView that we could use. It’s there since long but not much mentioned about it lately. But if you really want to do game programming natively, this is something not to miss.

In SurfaceView, with the same constraint above (0.5s for each animation drawing, wrapped in a scroll view), I could still scroll it smoothly as below.

Wow, isn’t that good, the computation of animation logic doesn’t interfere the User Interaction on it.

What’s SurfaceView?

Well, it is documented below, so I’m not writing about that.

How to implement something with it, you could find two examples below

The differences with normal view

There are several places state about their differences

But they are not to the detail in term of implementing encountered differences. This is what I’ll be sharing here.

The animation code used

I have a simple drawing that animate the red rectangle from left to right as below

class DrawAnimate(private val height: Int, private val width: Int) {

private var startPoint = 0f
private val strokePaint = Paint()
.apply { color = Color.RED }
.apply { strokeWidth = 16f }


companion object {
private const val SIZE = 50f
private const val SLEEP = 500L
}

fun draw(canvas: Canvas) {
canvas.drawRect(startPoint, height/2 - SIZE/2,
startPoint + SIZE, height/2 + SIZE/2, strokePaint)
Thread.sleep(SLEEP)
startPoint += SIZE
if (startPoint > width) { startPoint = 0f }

}
}

With the above logic, I add a gradient background to the view.

    <com.elyeproj.surfaceviewexplore.<SurfaceView/NormalView>
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_vertical"
android:minHeight="@dimen/custom_view_height" />

With this when I execute on normal View, it looks as below

However, when I execute on SurfaceView, it looks as below

Can you spot all the differences? They are further elaborated below. Anyway, to test it out, you could get the code from

The differences to handle in implementation

Having seen the above, let me extract each of the Implementation differences. This would be helpful if you’re transferring your normal View drawing to SurfaceView.

1. Background color

For normal view, the Background color is actually at the back of the drawing view. So you could see the red dot in always drawn on top of the green gradient color (which is the background color)

However for SurfaceView, the Background color (gradient green) is actually in front of the drawing surface. So whatever that is drawn will be place in front of the surface canvas. With that if it is not transparent, it will cover over what is drawn (i.e. the red dot).

So in short, for SurfaceView, don’t put a background color thinking that it will be the view background.

2. Color of view

For normal view, the color of the view is actually transparent. It is seen white, as it is the background of the window view, so white is seen.

For surfaceView, it is black in nature, as it is behind the window view. There’s no background color whatsoever. Read some of the above links for the reason why.

With that, if you would like to have a non black background color, you’ll need to do some trick to it. One way is as below

  • Set background color (that you like) to it initially.
  • When the surface is setup, use canvas.drawColor(YourColorBackground)
  • Then remove the background color (or set as transparent)

3. Canvas drawing

For normal view, as the canvas is drawn, on every invalidation, it is cleared, so new rectangle need to be drawn, but the old rectangle doesn’t need to be cleared, as it has been cleared.

For surfaceView however, the drawn canvas retain what it has been drawn. This is not that clearly seen initially as there seems to have 3 layers of Canvas

I read there are double buffer of Canvas, but from my experience of program above, there are 3 canvas layer. If you observe carefully, after the 3 drawing, the previous drawn canvas resurface, and this continue on until it form the entire new line.

So for surfaceView, every previously drawn canvas, if no longer needed, needs to be explicitly cleared.

4. Onbackground behavior

This would not be observed from the above GIF shown.

For normal View, when onBackground and back, the drawing is retain and continue on (with the exception if the Fragment/Activity is destroyed).

For for surfaceView, when onBackground, the surface is Destroyed, and recreated. So the surface canvas will be reset. Hence this needs to be tackle accordingly.


With the differences stated, hopefully it helps clear out some initial exploration of using SurfaceView.

There are more to be explored. Below are few to check out.

I hope this post is helpful to you. You could check out my other interesting topics here.

Follow me on medium, Twitter or Facebook for little tips and learning on Android, Kotlin etc related topics. ~Elye~

Elye

Written by

Elye

Learning and Sharing Android and iOS Development

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade