Android 맞춤형 구성 요소 시리즈[12] – UI 스레드가 아닌 드로잉SurfaceView

1. SurfaceView 소개
앞에서 우리는 이미 뷰를 사용자 정의해서 canvas로 그림을 그릴 수 있지만, 뷰의 그림 그리기 메커니즘에 약간의 결함이 있다.
1. View는 이중 버퍼 메커니즘이 없습니다.
2. 프로그램은 전체 View에 표시된 그림을 다시 그려서 자원을 비교적 소모해야 한다.
3. UI 스레드가 아닌 경우 View 구성 요소를 업데이트할 수 없기 때문에 주 스레드 자원을 차지하고 주 스레드에서 논리를 처리해야 할 때 매우 느리다.
안드로이드에서 우리에게SurfaceView를 제공하여 뷰를 대체하여 도형을 그릴 수 있도록 했다. 일반적으로 게임 그림 그리기에 널리 응용되기 때문에 비교적 복잡한 그림이라면 SurfaceView를 사용하는 것을 권장한다.
2. SurfaceView의 드로잉 메커니즘
SurfaceView는 일반적으로 SurfaceHolder와 결합하여 사용되며, SurfaceHolder는 이와 관련된 SurfaceView에 그림을 그리는 데 사용되며, SurfaceView의 getHolder() 방법을 호출하면SurfaceView와 관련된 SurfaceHolder를 얻을 수 있습니다.
SurfaceHolder는 lockCanvas와 lockCanvas(Rect dirty)를 제공하여 그림 영역을 잠그고 그 영역의 캔버스(Canvas)를 가져옵니다. 이 캔버스를 통해 도형을 그릴 수 있습니다.
3. SurfaceView 사용 실례
1. 간단한 사용(UI 스레드에 그려짐)
4
package com.test.surfaceview;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;

import com.example.testsurfaceview.R;

public class MainActivity extends Activity{
	
	private SurfaceHolder holder;
	private Paint paint;
	private Rect rect;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		paint = new Paint();
		rect = new Rect();
		
		SurfaceView surface = (SurfaceView)findViewById(R.id.show);
		holder = surface.getHolder();
		
		//          
		holder.addCallback(new SurfaceHolder.Callback() {
			
			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
			}
			
			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				Canvas canvas = holder.lockCanvas();
				Bitmap bitmap = BitmapFactory.decodeResource(
						MainActivity.this.getResources(), R.drawable.ic_launcher);
				canvas.drawBitmap(bitmap, 0, 0, null);
				holder.unlockCanvasAndPost(canvas);
			}
			
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int width,
					int height) {
			}
		});
		
		//      
		surface.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if(event.getAction() == MotionEvent.ACTION_DOWN){
					int cx = (int)event.getX();
					int cy = (int)event.getY();
					
					rect.set(cx - 50, cy - 50, cx + 50, cy + 50);
					//           
					Canvas canvas = holder.lockCanvas(rect);
					//        
					canvas.save();
					//    
					canvas.rotate(30, cx, cy);
					paint.setColor(Color.RED);
					//    
					canvas.drawRect(cx - 40, cy - 40, cx, cy, paint);
					//    
					canvas.restore();
					paint.setColor(Color.GREEN);
					//    
					canvas.drawRect(cx, cy, cx + 40, cy + 40, paint);
					//    ,    ,    
					holder.unlockCanvasAndPost(canvas);
				}
				return false;
			}
		});
	}
}
2, 비 UI 스레드에서 그리기
package com.test.surfaceview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.example.testsurfaceview.R;

/**
 *      http://blog.csdn.net/dawanganban
 * 
 * @author Administrator
 * 
 */
public class MySurfaceView extends SurfaceView {

	private Context context;
	private Rect rect;
	private Paint paint;


	private AppStartDrawView appStartDrawView;

	public MySurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		rect = new Rect();
		paint = new Paint();
		appStartDrawView = new AppStartDrawView();
		this.getHolder().addCallback(appStartDrawView);
	}

	/**
	 *     
	 */
	public void stopAnim() {
		appStartDrawView.cancel(true);
	}

	private class AppStartDrawView extends AsyncTask<Void, Integer, Void> implements SurfaceHolder.Callback {
		private boolean isStarted = false;
		private SurfaceHolder holder;

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			this.holder = holder;
			
			//      
			Canvas canvas = holder.lockCanvas();
			Bitmap bitmap = BitmapFactory.decodeResource(
					context.getResources(), R.drawable.ic_launcher);
			canvas.drawBitmap(bitmap, 0, 0, null);
			holder.unlockCanvasAndPost(canvas);
			
			if (!isStarted) {
				this.execute();
				isStarted = true;
			}
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			this.holder = holder;
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			isStarted = false;
			holder = null;
		}
		

		@Override
		protected Void doInBackground(Void... params) {
			int cx = 0;
			int cy = 0;
			while(!isCancelled()){
				//    
				//TODO .....
				rect.set(cx - 50, cy - 50, cx + 50, cy + 50);
				//           
				Canvas canvas = holder.lockCanvas(rect);
				//        
				canvas.save();
				//    
				canvas.rotate(30, cx, cy);
				paint.setColor(Color.RED);
				//    
				canvas.drawRect(cx - 40, cy - 40, cx, cy, paint);
				//    
				canvas.restore();
				paint.setColor(Color.GREEN);
				//    
				canvas.drawRect(cx, cy, cx + 40, cy + 40, paint);
				//    ,    ,    
				holder.unlockCanvasAndPost(canvas);
				
				//TODO ....
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				cx += 60;
				cy += 60;
				
				if(cx  >= 400){
					stopAnim();
				}
			}
			return null;
		}

	}
}

좋은 웹페이지 즐겨찾기