Surface View Tutorial
This tuturial guides in using surface view at a very basic level . The code presented in this tutorial creates a simple view with a image using a surface view instead of conventianal View object.
Create New Project & Activity
Lets create a new android project using ecilpse. Lets name it SurfaceExample and our activity name as SurfaceExampleActivity.
Add another class which will extend surface view. Lets name this class SurfacePanel.
The SurfacePanel class extends the surface view .
public class SurfacePanel extends SurfaceView { /** parameterized constructor for surface panel class**/ public SurfacePanel(Context context, AttributeSet attrSet) { super(context, attrSet); } } Creating Xml with surface view class Lets modify our main.xml layout file , and add surfacePanel class as its child.
As shown in the above xml file, we have added our surface view class as part of xml file.
Now run the application . It gives a blank black screen.
Inorder to do some drawing in our surface view class , we can not use its onDraw function because even if we override the onDraw function then also the output will be same blank black screen.
This is because the onDraw function is not getting called itself.
To resolve this we will implement SurfaceHandler.Callback interface.This interface provides three methods related to surface creation, change and deletion.
To register the class itself as callback we will add the this pointer in add callback method in the constructor of our SurfacePanel class.
SurfaceView with callback interface
public class SurfacePanel extends SurfaceView implements SurfaceHolder.Callback { public SurfacePanel(Context ctx, AttributeSet attrSet) { super(ctx, attrSet); context = ctx; //the bitmap we wish to draw mbitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.logintab_off); SurfaceHolder holder = getHolder(); holder.addCallback(this); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { }
We will provide implementation for these surface methods a little later. For now will implement a thread which will call our drawing method periodically.
Lets call it MyThread.
publicclass MyThread extends Thread { booleanmRun; Canvas mcanvas; SurfaceHolder surfaceHolder; Context context; SurfacePanel msurfacePanel; public MyThread(SurfaceHolder sholder, Context ctx, SurfacePanel spanel) { surfaceHolder = sholder; context = ctx; mRun = false; msurfacePanel = spanel; } void setRunning(boolean bRun) { mRun = bRun; } @Override publicvoid run() { super.run(); while(mRun) { mcanvas = surfaceHolder.lockCanvas(); if(mcanvas != null) { msurfacePanel.doDraw(mcanvas); surfaceHolder.unlockCanvasAndPost(mcanvas); } } } }
In this class, we extends Thread class and have overriden run method.
In run method , we check if the thread is running, then call our own draw method on the canvas obtained from the holder.By not calling onDraw method (we call our own implementation doDraw) , we ensure that android system will not invalidate our panel.
Since android system calls onDraw which in this case does nothing.
Back to our surface view class .. lets provide implementation for the callback methods and our own doDraw method.
@Override publicvoid surfaceCreated(SurfaceHolder holder) { mythread = new MyThread(holder, context,this); mythread.setRunning(true); mythread.start(); } @Override publicvoid surfaceDestroyed(SurfaceHolder holder) { mythread.setRunning(false); boolean retry = true; while(retry) { try { mythread.join(); retry = false; } catch(Exception e) { Log.v("Exception Occured", e.getMessage()); } } } void doDraw(Canvas canvas) { canvas.drawColor(Color.GREEN); canvas.drawBitmap(mbitmap, 50, 50, null); }
Currently we have nothing to do in surface changed function so its not implemented.
SurfaceCreated()-> Called as soon as the surface gets created. We create our thread class object and run it.
SurfaceDestroyed() -> Called as soon as the surface is destroyed(hidden) from the screen. We destroy the thread object created by calling its join() function.
DoDraw() -> Our drawing function which draws on the canvas obtained from surface holder.
When we run this application, we will get the output as a result of operation performed in doDraw() function with using View object.