第3.3.4节 创建高级图形之surfaceView(一)

Android视图框架对于创建复杂布局非常方便。然而,这种便利是以性能为代价的。当性能至关重要的时候,Android提供了几种更强大的图形处理能力,当然难度也是随之上升了。在本节中,我将介绍:

(1)SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结

合,得到比标准视图更好的性能;

(2)新得RenderScript框架可以被用于创建独立结构的图形渲染;

(3)OpenGL可用于一些严格的图形工作和游戏。

1、SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结

合,得到比标准视图更好的性能;

与普通视图不同,所有在SurfaceView上的绘图都发生在一个独立的线程上。要想在SurfaceView上绘图,你必须调用SurfaceHolder的lockCanvas方法,这将返回一个Canvas对象。lockCanvas方法阻止SurfaceView更新底层界面(阻止它删除你先前画的),直到你调用响应的unlockCanvasAndPost方法为止。这消除了对界面改变同步的需求(尽管你仍然需要在进程之间同步一些字段)。你应该把对SurfaceView所有的绘制包装进lockCanvas和unlockCanvasAndPost模块中。下面我提供了两种绘制SurfaceView的方法,主要来演示lockCanvas的重要作用:

1.1 创建自己的工程,将contentView设置为自己的类(继承surfaceView)

public class MainActivity extends Activity{	
	private static final String TAG = "MainActivity";
	private int Y_center,X_center;	//Y轴的一半
	private int X_width;		//X轴的点数
	private int Y_point[];//曲线所需要的Y轴点数
	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setContentView(new exampleSurfaceView(this));
		
	}

这里我已经将下面将要使用的变量列出,setContentView(new exampleSurfaceView(this)); 接下来我们要定义自己的新类了,继承surfaceView,这里不再使用视图了。

1.2 编写自己的exampleSurfaceView类继承surfaceView

public class exampleSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
		DrawingThread mThread;
		private SurfaceHolder holder;
		/********************************************************************************
		 * 获得holder对象,实例化mThread,计算屏幕大小取出Y轴的中心高度
		 * 
		 * @param context
		 */
		public exampleSurfaceView(Context context){
			super(context);
			holder = getHolder();
			holder.addCallback(this);
			mThread = new DrawingThread(holder);
			DisplayMetrics dm = new DisplayMetrics();
			getWindowManager().getDefaultDisplay().getMetrics(dm);
			Y_center = dm.heightPixels/2;
			X_width = dm.widthPixels;
			X_center = X_width/2;
			Log.i(TAG, "屏幕的一半高度为:"+Y_center+"屏幕的一半宽度为:"+X_center);
			Y_point = new int[X_width];
			for(int i=0; i<Y_point.length; i++){
				Y_point[i] = Y_center-(int) (100 * Math.sin(i * 2 * Math.PI / 180)); 
			}
		}
		//创建三角形
		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
			// TODO Auto-generated method stub
			Log.i(TAG, "this is changeed format:"+arg1+"width:"+arg2+"height:"+arg3);
			
		}
		//更新surface,并起动
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			mThread.keepRunning = true;
			mThread.start();
		}
		//终止线程,回收空间
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			mThread.keepRunning = false;
			boolean retry=true;
			while(retry){
				try{
					mThread.join();
					retry = false;
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
		}		
	}

这里我们在surfaceView创建的时候开启线程,在surfaceView销毁的时候,回收线程,最后我们在把线程内容给出。

1.3 通过线程实现绘制图形。

	public class DrawingThread extends Thread {
		boolean keepRunning=true;
		private SurfaceHolder holder;
		
		public DrawingThread(SurfaceHolder holder) {
			// TODO Auto-generated constructor stub
			this.holder =holder; 			
		}
		@Override
		public void run(){
			Canvas c;
			int count = 0;
			int X_old,Y_old,X_new,Y_new;
			X_old = 0;
			Y_old = Y_point[X_old];
			while(keepRunning){
				c = null;
				try{					
					synchronized(holder){//synchronized锁的永远是对象,获得holder对象
						c = holder.lockCanvas();
						c.drawColor(Color.BLACK);
						Paint mPaint = new Paint(); //创建画笔
						mPaint.setStrokeWidth(5);						
						mPaint.setColor(Color.RED);
						X_new = X_old+1;
						Y_new = Y_point[X_new];
						c.drawLine(X_old, Y_old, X_new, Y_new, mPaint);
						c.drawText("这是第"+(count++)+"秒", X_center, Y_center, mPaint);
						X_old++;
						Y_old = Y_point[X_old];
						if(X_old == X_width-1){
							Log.i(TAG, "game over");
							X_old = 1;
							Y_old = Y_point[X_old];
						}
						
						Thread.sleep(10);
					}
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					if(c != null){
						holder.unlockCanvasAndPost(c);
					}
				}
			}
		}
	}


这里就实现了正弦波的绘制。图片如下:

这两个图是上面程序绘制的,不断的调用c.drawColor(Color.BLACK);来清除图层

不使用c.drawColor(Color.BLACK);

我这里是线程多次执行,绘制出来的,当然也可一在线程执行一次的时候直接绘制完毕,这里可以自己微微改动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值