使用SurfaceView绘制动态图像 图片看不了?点击切换HTTP 返回上层
实例 SurfaceViewDrawDemo 绘制的是一幅静态图像,而使用 SurfaceView 可以绘制动态图像。
绘制动态图像的过程应该在一个单独的线程中完成,而不应该在主线程中进行。实例 SurfaceViewDynDrawDemo 演示了使用 SurfaceView 组件绘制动态图像的过程。
该实例修改自 Android SDK 提供的实例,绘制的是类似于 Windows 中的变幻线屏保的效果,运行效果如图 1 所示。

图 1 实例 SurfaceViewDynDrawDemo 的运行效果
实例 SurfaceViewDynDrawDemo 的布局文件 main.xml 内容如下:
实例 SurfaceViewDynDrawDemo 的主 Activity 为 SurfaceViewDynDrawDemoActivity,其代码如下:
需要注意的是,就像前面所提到的,绘制动态图像的过程必须在一个单独的线程中完成,而不能在主线程中进行。在该实例中,绘图过程是在 DrawingThread 中完成的。
绘制动态图像的过程应该在一个单独的线程中完成,而不应该在主线程中进行。实例 SurfaceViewDynDrawDemo 演示了使用 SurfaceView 组件绘制动态图像的过程。
该实例修改自 Android SDK 提供的实例,绘制的是类似于 Windows 中的变幻线屏保的效果,运行效果如图 1 所示。

图 1 实例 SurfaceViewDynDrawDemo 的运行效果
实例 SurfaceViewDynDrawDemo 的布局文件 main.xml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TextView android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "@string/hello" /> <SurfaceView android:id= "@+id/surfaceViewl" android:layout_width= "fill_parent" android:layout_height= "fill_parent" /> </LinearLayout> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | import android.app.Activity; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android. view .SurfaceHolder; import android. view .SurfaceView; public class SurfaceViewDynDrawDemoActivity extends Activity { private SurfaceView mySurfaceView; private DrawingThread mDrawingThread; SurfaceHolder surfaceHolder; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mySurfaceView = (SurfaceView) findViewById(R.id.surfaceViewl); surfaceHolder = mySurfaceView.getHolder(); surfaceHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub mDrawingThread = new DrawingThread(); mDrawingThread.mSurface = surfaceHolder; mDrawingThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub mDrawingThread.mQuit = true ; } }); } 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); } } } 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 = false ; final MovingPoint mPoint1 = new MovingPoint(); final MovingPoint mPoint2 = new MovingPoint(); static final int NUM_OLD = 100; int mNum0ld = 0; final float [] m0ld = new float [NUM_OLD * 4]; final int [] m01dColor = 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 ) { if (mQuit) { return ; } // 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 = mNum0ld - 1; i >= 0; i --) { mForeground.setColor(m01dColor[i] | makeGreen(i)); mForeground.setAlpha(((NUM_OLD - i) * 255) / NUM_OLD); int p = i * 4; canvas.drawLine(m0ld[p], m0ld[p + 1], m0ld[p + 2], m0ld[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 (mNum0ld > 1) { System.arraycopy(m0ld, 0, m0ld, 4, (mNum0ld - 1) * 4); System.arraycopy(m01dColor, 0, m01dColor, 1, mNum0ld - 1); } if (mNum0ld < NUM_OLD) mNum0ld++; m0ld[0] = mPoint1.x; m0ld[1] = mPoint1.y; m0ld[2] = mPoint2.x; m0ld[3] = mPoint2.y; m01dColor[0] = color; // All done mSurface.unlockCanvasAndPost(canvas); } } } } |