android.view.SurfaceView is a sub-class of android.view.View. It is used to create custom views in android game development. It does not have the onDraw method, but you can get and use the android.view.SurfaceHolder object to get and lock the view canvas, and then paint on it. This example will show you how to use it.
1. Android SurfaceView Example.
- In the example, when you click the Red Ball button, it will draw a red ball and the red ball will move after finger touch move.
- When you click the Green Rectangle button the red ball will be placed with a green rectangle.
- You can see this example demo video at the end of this article.
2. Android SurfaceView Example Source Code.
- The example core files are MainActivity.java, CustomSurfaceView.java, and activity_main.xml file.
2.1 Main Activity Java Class.
- MainActivity.java
package com.dev2qa.surfaceviewexample; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Layout; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; public class MainActivity extends AppCompatActivity implements View.OnTouchListener{ private Button redButton = null; private Button greenButton = null; private boolean drawBall = true; private LinearLayout canvasLayout = null; CustomSurfaceView customSurfaceView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("dev2qa.com - Android SurfaceView Drawing Example."); initControls(); // Hide the app title bar. getSupportActionBar().hide(); // Make app full screen to hide top status bar. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Create custom surfaceview object. customSurfaceView = new CustomSurfaceView(getApplicationContext()); // Set this as the onTouchListener to process custom surfaceview ontouch event. customSurfaceView.setOnTouchListener(this); // Add the custom surfaceview object to the layout. canvasLayout.addView(customSurfaceView); // Click this button to draw a red circle ball move after finger touch. redButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawBall = true; } }); // Click this button to draw a green rectangle move after finger touch. greenButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawBall = false; } }); } /* Initialise ui controls. */ private void initControls() { if(redButton == null) { redButton = (Button)findViewById(R.id.redButton); } if(greenButton == null) { greenButton = (Button)findViewById(R.id.greenButton); } // This layout is used to contain custom surfaceview object. if(canvasLayout == null) { canvasLayout = (LinearLayout)findViewById(R.id.customViewLayout); } } /* If user finger touch the surfaceview object. */ @Override public boolean onTouch(View view, MotionEvent motionEvent) { // If user touch the custom SurfaceView object. if(view instanceof SurfaceView) { float x = motionEvent.getX(); float y = motionEvent.getY(); customSurfaceView.setCircleX(x); customSurfaceView.setCircleY(y); if (drawBall) { // Create and set a red paint to custom surfaceview. Paint paint = new Paint(); paint.setColor(Color.RED); customSurfaceView.setPaint(paint); customSurfaceView.drawBall(); } else { // Create and set a green paint to custom surfaceview. Paint paint = new Paint(); paint.setColor(Color.GREEN); customSurfaceView.setPaint(paint); customSurfaceView.drawRect(); } // Tell android os the onTouch event has been processed. return true; }else { // Tell android os the onTouch event has not been processed. return false; } } }
2.2 Custom SurfaceView Java Class.
- The custom view must extend android.view.SurfaceView and implement android.view.SurfaceHolder.Callback interface.
- Then it should override Callback‘s surfaceCreated, surfaceChanged and surfaceDestroyed method.
- CustomSurfaceView.java
package com.dev2qa.surfaceviewexample; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.view.SurfaceView; import android.view.SurfaceHolder; public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder surfaceHolder = null; private Paint paint = null; private float circleX = 0; private float circleY = 0; public CustomSurfaceView(Context context) { super(context); setFocusable(true); if(surfaceHolder == null) { // Get surfaceHolder object. surfaceHolder = getHolder(); // Add this as surfaceHolder callback object. surfaceHolder.addCallback(this); } if(paint == null) { paint = new Paint(); paint.setColor(Color.RED); } // Set the parent view background color. This can not set surfaceview background color. this.setBackgroundColor(Color.BLUE); // Set current surfaceview at top of the view tree. this.setZOrderOnTop(true); this.getHolder().setFormat(PixelFormat.TRANSLUCENT); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { drawBall(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { } /* This method will be invoked to draw a circle in canvas. */ public void drawBall() { // Get and lock canvas object from surfaceHolder. Canvas canvas = surfaceHolder.lockCanvas(); Paint surfaceBackground = new Paint(); // Set the surfaceview background color. surfaceBackground.setColor(Color.CYAN); // Draw the surfaceview background color. canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), surfaceBackground); // Draw the circle. canvas.drawCircle(circleX, circleY, 100, paint); // Unlock the canvas object and post the new draw. surfaceHolder.unlockCanvasAndPost(canvas); } /* This method will be invoked to draw a circle in canvas. */ public void drawRect() { Canvas canvas = surfaceHolder.lockCanvas(); Paint surfaceBackground = new Paint(); // Set the surfaceview background color. surfaceBackground.setColor(Color.BLUE); // Draw the surfaceview background color. canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), surfaceBackground); // Draw the rectangle. canvas.drawRect(circleX, circleY, circleX + 200, circleY + 200, paint); surfaceHolder.unlockCanvasAndPost(canvas); } public float getCircleX() { return circleX; } public void setCircleX(float circleX) { this.circleX = circleX; } public float getCircleY() { return circleY; } public void setCircleY(float circleY) { this.circleY = circleY; } public Paint getPaint() { return paint; } public void setPaint(Paint paint) { this.paint = paint; } }
2.3 Main Activity Layout Xml File.
- app/res/layout/activity_main.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/redButton" android:layout_width="1dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Red Ball" android:textAllCaps="false" android:textSize="20dp" /> <Button android:id="@+id/greenButton" android:layout_width="1dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Green Rectangle" android:textAllCaps="false" android:textSize="20dp" /> </LinearLayout> <LinearLayout android:id="@+id/customViewLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> </LinearLayout> </LinearLayout>
- You can see this example demo video on URL https://youtube.com/shorts/JTlehIslzgQ?feature=share.