Mega Code Archive

 
Categories / Android / UI
 

Demonstrates how to take over the Surface from a window to do direct drawing to it (without going through the view hierarchy)

/*  * Copyright (C) 2008 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */   package app.test; import android.app.Activity; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; /**  * Demonstrates how to take over the Surface from a window to do direct  * drawing to it (without going through the view hierarchy).  */ public class WindowSurface extends Activity implements SurfaceHolder.Callback2 {     DrawingThread mDrawingThread;          @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);                  // Tell the activity's window that we want to do our own drawing         // to its surface.  This prevents the view hierarchy from drawing to         // it, though we can still add views to capture input if desired.         getWindow().takeSurface(this);                  // This is the thread that will be drawing to our surface.         mDrawingThread = new DrawingThread();         mDrawingThread.start();     }     @Override     protected void onPause() {         super.onPause();                  // Make sure the drawing thread is not running while we are paused.         synchronized (mDrawingThread) {             mDrawingThread.mRunning = false;             mDrawingThread.notify();         }     }     @Override     protected void onResume() {         super.onResume();                  // Let the drawing thread resume running.         synchronized (mDrawingThread) {             mDrawingThread.mRunning = true;             mDrawingThread.notify();         }     }     @Override     protected void onDestroy() {         super.onDestroy();                  // Make sure the drawing thread goes away.         synchronized (mDrawingThread) {             mDrawingThread.mQuit = true;             mDrawingThread.notify();         }     }     public void surfaceCreated(SurfaceHolder holder) {         // Tell the drawing thread that a surface is available.         synchronized (mDrawingThread) {             mDrawingThread.mSurface = holder;             mDrawingThread.notify();         }     }     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {         // Don't need to do anything here; the drawing thread will pick up         // new sizes from the canvas.     }     public void surfaceRedrawNeeded(SurfaceHolder holder) {     }     public void surfaceDestroyed(SurfaceHolder holder) {         // We need to tell the drawing thread to stop, and block until         // it has done so.         synchronized (mDrawingThread) {             mDrawingThread.mSurface = holder;             mDrawingThread.notify();             while (mDrawingThread.mActive) {                 try {                     mDrawingThread.wait();                 } catch (InterruptedException e) {                     e.printStackTrace();                 }             }         }     }     // Tracking of a single point that is moving on the screen.     static final class MovingPoint {         float x, y, dx, dy;                  void init(int width, int height, float minStep) {             x = (float)((width-1)*Math.random());             y = (float)((height-1)*Math.random());             dx = (float)(Math.random()*minStep*2) + 1;             dy = (float)(Math.random()*minStep*2) + 1;         }                  float adjDelta(float cur, float minStep, float maxStep) {             cur += (Math.random()*minStep) - (minStep/2);             if (cur < 0 && cur > -minStep) cur = -minStep;             if (cur >= 0 && cur < minStep) cur = minStep;             if (cur > maxStep) cur = maxStep;             if (cur < -maxStep) cur = -maxStep;             return cur;         }                  void step(int width, int height, float minStep, float maxStep) {             x += dx;             if (x <= 0 || x >= (width-1)) {                 if (x <= 0) x = 0;                 else if (x >= (width-1)) x = width-1;                 dx = adjDelta(-dx, minStep, maxStep);             }             y += dy;             if (y <= 0 || y >= (height-1)) {                 if (y <= 0) y = 0;                 else if (y >= (height-1)) y = height-1;                 dy = adjDelta(-dy, minStep, maxStep);             }         }     }          /**      * This is a thread that will be running a loop, drawing into the      * window's surface.      */     class DrawingThread extends Thread {         // These are protected by the Thread's lock.         SurfaceHolder mSurface;         boolean mRunning;         boolean mActive;         boolean mQuit;                  // Internal state.         int mLineWidth;         float mMinStep;         float mMaxStep;                  boolean mInitialized;         final MovingPoint mPoint1 = new MovingPoint();         final MovingPoint mPoint2 = new MovingPoint();                  static final int NUM_OLD = 100;         int mNumOld = 0;         final float[] mOld = new float[NUM_OLD*4];         final int[] mOldColor = new int[NUM_OLD];         int mBrightLine = 0;                  // X is red, Y is blue.         final MovingPoint mColor = new MovingPoint();                  final Paint mBackground = new Paint();         final Paint mForeground = new Paint();                  int makeGreen(int index) {             int dist = Math.abs(mBrightLine-index);             if (dist > 10) return 0;             return (255-(dist*(255/10))) << 8;         }                  @Override         public void run() {             mLineWidth = (int)(getResources().getDisplayMetrics().density * 1.5);             if (mLineWidth < 1) mLineWidth = 1;             mMinStep = mLineWidth * 2;             mMaxStep = mMinStep * 3;                          mBackground.setColor(0xff000000);             mForeground.setColor(0xff00ffff);             mForeground.setAntiAlias(false);             mForeground.setStrokeWidth(mLineWidth);                          while (true) {                 // Synchronize with activity: block until the activity is ready                 // and we have a surface; report whether we are active or inactive                 // at this point; exit thread when asked to quit.                 synchronized (this) {                     while (mSurface == null || !mRunning) {                         if (mActive) {                             mActive = false;                             notify();                         }                         if (mQuit) {                             return;                         }                         try {                             wait();                         } catch (InterruptedException e) {                         }                     }                                          if (!mActive) {                         mActive = true;                         notify();                     }                                          // Lock the canvas for drawing.                     Canvas canvas = mSurface.lockCanvas();                     if (canvas == null) {                         Log.i("WindowSurface", "Failure locking canvas");                         continue;                     }                                          // Update graphics.                     if (!mInitialized) {                         mInitialized = true;                         mPoint1.init(canvas.getWidth(), canvas.getHeight(), mMinStep);                         mPoint2.init(canvas.getWidth(), canvas.getHeight(), mMinStep);                         mColor.init(127, 127, 1);                     } else {                         mPoint1.step(canvas.getWidth(), canvas.getHeight(),                                 mMinStep, mMaxStep);                         mPoint2.step(canvas.getWidth(), canvas.getHeight(),                                 mMinStep, mMaxStep);                         mColor.step(127, 127, 1, 3);                     }                     mBrightLine+=2;                     if (mBrightLine > (NUM_OLD*2)) {                         mBrightLine = -2;                     }                                          // Clear background.                     canvas.drawColor(mBackground.getColor());                                          // Draw old lines.                     for (int i=mNumOld-1; i>=0; i--) {                         mForeground.setColor(mOldColor[i] | makeGreen(i));                         mForeground.setAlpha(((NUM_OLD-i) * 255) / NUM_OLD);                         int p = i*4;                         canvas.drawLine(mOld[p], mOld[p+1], mOld[p+2], mOld[p+3], mForeground);                     }                                          // Draw new line.                     int red = (int)mColor.x + 128;                     if (red > 255) red = 255;                     int blue = (int)mColor.y + 128;                     if (blue > 255) blue = 255;                     int color = 0xff000000 | (red<<16) | blue;                     mForeground.setColor(color | makeGreen(-2));                     canvas.drawLine(mPoint1.x, mPoint1.y, mPoint2.x, mPoint2.y, mForeground);                                          // Add in the new line.                     if (mNumOld > 1) {                         System.arraycopy(mOld, 0, mOld, 4, (mNumOld-1)*4);                         System.arraycopy(mOldColor, 0, mOldColor, 1, mNumOld-1);                     }                     if (mNumOld < NUM_OLD) mNumOld++;                     mOld[0] = mPoint1.x;                     mOld[1] = mPoint1.y;                     mOld[2] = mPoint2.x;                     mOld[3] = mPoint2.y;                     mOldColor[0] = color;                                          // All done!                     mSurface.unlockCanvasAndPost(canvas);                 }             }         }     } }