android繪圖原理

1、分析繪圖用到的幾個類,如Paint、Bitmap、Canvas、Drawable、Rect等

1) Paint

Paint paint = new Paint();
paint.setTextSize(20f);
paint.setColor(Color.argb(255, 255, 0, 0));
paint.setStrokeWidth(2f);
paint.setTextAlign(Align.CENTER);
paint.setStyle(Style.STROKE);
Rect rect = new Rect();
paint.getTextBounds("中國", 0, 2, rect);
paint.ascent();
paint.descent();

2) 自定義Bitmap

Bitmap bitmap = Bitmap.createBitmap(48, 48, Config.ARGB_4444);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
canvas.drawText("hello", 10, 10, paint);
findViewById(R.id.img).setBackgroundDrawable(new BitmapDrawable(getResources(), bitmap));

3)求Bitmap大小

public static float getBitmapSize(Bitmap bitmap){
	if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){//19
		return bitmap.getAllocationByteCount()/1024f;
	}
	if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB_MR1){//12
		return bitmap.getByteCount()/1024f;
	}
	return (bitmap.getRowBytes()*bitmap.getHeight())/1024f;
}
2、SurfaceView的使用

1)SurfaceView原理

1)寫一個繼承SurfaceView的類MySurfaceView

2)寫一個繼承Thread的線程RenderThread,用於繪製界面

3)寫一個實現SurfaceHolder.Callback接口的類MyCallBack

4)在MySurfaceView構造器中獲得SurfaceHolder實例,併爲其添加MyCallBack回調

5)在surfaceCreated方法裏創建並啓動RenderThread線程

6)在Activity佈局文件裏添加MySurfaceView控件

2)事例代碼1:

MySurfaceView.java

public class MySurfaceView extends SurfaceView {
	private static final String TAG = MySurfaceView.class.getSimpleName();
	SurfaceHolder mHolder;
	Thread mThread;
	Paint mPaint;
	Context mContext;
	public MySurfaceView(Context context, AttributeSet attrs){
		this(context, attrs, 0);
	}
	public MySurfaceView(Context context, AttributeSet attrs, int defStyle){
		super(context,attrs,defStyle);
		mContext = context;
		init();
		Log.d(TAG, "MySurfaceView");
		mHolder = getHolder();
		mHolder.addCallback(new MyCallBack());
	}
	private void init(){
		mPaint = new Paint();
		mPaint.setColor(Color.argb(255, 255, 255, 0));
		mPaint.setTextSize(20 * mContext.getResources().getDisplayMetrics().density);
	}
	private class MyCallBack implements SurfaceHolder.Callback{
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			Log.d(TAG, "surfaceCreated-"+"width:"+getWidth()+";height:"+getHeight());
			mThread = new RenderThread();
			mThread.start();
		}

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

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			//摁home鍵調用,摁power鍵不調用
			//用華爲,聯想手機測過
			Log.d(TAG, "surfaceDestroyed");
		}
	}
	private class RenderThread extends Thread{
		@Override
		public void run() {
			super.run();
			Canvas c = mHolder.lockCanvas();
			c.drawText("By the way, how old are you?", 100, 100, mPaint);
			mHolder.unlockCanvasAndPost(c);
		}
	}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <com.qinuli.surfaceviewtest.MySurfaceView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
}
3)事例代碼2

public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	SurfaceView surfaceView;
	SurfaceHolder holder;
	//List.get(int)
	List<Integer> imgList = new ArrayList<Integer>();
	int imgWidth,imgHeight;
	//利用LinkedList.removeFirst()
	LinkedList<Bitmap> bmList = new LinkedList<Bitmap>();
	int imgIndex;
	Button btn1;
	Button btn2;
	//associate handler with looper for current thread
	Handler handler = new Handler();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn1 = (Button) findViewById(R.id.btn1);
		btn2 = (Button) findViewById(R.id.btn2);
		surfaceView = (SurfaceView) findViewById(R.id.surfaceview1);
		holder = surfaceView.getHolder();
		holder.addCallback(new MyCallback());
	}

	public void onClick(View v){
		switch (v.getId()) {
		case R.id.btn1:
			btn1.setClickable(false);
			new LoadAndDrawImage(0, 0).start();
			break;
		case R.id.btn2:
			btn2.setClickable(false);
			new LoadImage().start();
			new DrawImage(0, imgHeight+10).start();
		}
	}

	class MyCallback implements Callback2{
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			Log.println(Log.INFO, TAG, "surfaceCreated");
			Field[] fields = R.drawable.class.getDeclaredFields();
			for(Field field:fields){
				//prefix,suffix,toLowerCase(),toUpperCase(),toCharArray(),getBytes()
				if(field.getName().startsWith("b")){
					int index=0;
					try {
						index = field.getInt(R.drawable.class);
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					}
					imgList.add(index);
				}
			}
			Collections.sort(imgList);
			Collections.reverse(imgList);
			Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(0));
			imgWidth = bitmap.getWidth();
			imgHeight = bitmap.getHeight();
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			Log.println(Log.INFO, TAG, "surfaceChanged");
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			Log.println(Log.INFO, TAG, "surfaceDestroyed");
		}

		@Override
		public void surfaceRedrawNeeded(SurfaceHolder holder) {
			Log.println(Log.INFO, TAG, "surfaceRedrawNeeded");
		}
	}
	class LoadAndDrawImage extends Thread{
		int x,y;
		int imgIndex = 0;
		public LoadAndDrawImage(int x,int y){
			this.x = x;
			this.y = y;
		}
		@Override
		public void run() {
			super.run();
			while(true){
				Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(imgIndex));
				Canvas canvas = holder.lockCanvas(new Rect(x, y, x+imgWidth, y+imgHeight));
				canvas.drawBitmap(bitmap, x, y, new Paint());
				holder.unlockCanvasAndPost(canvas);
				imgIndex++;
				if(imgIndex == imgList.size()){
					break;
				}
			}
			//跟UI線程交互
			handler.post(new Runnable() {
				@Override
				public void run() {
					btn1.setClickable(true);
				}
			});
		}
	}
	class LoadImage extends Thread{
		@Override
		public void run() {
			super.run();
			imgIndex = 0;
			while(true){
				//從res/drawable加載jpg圖片
				Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(imgIndex),null);
				bmList.add(bitmap);
				imgIndex++;
				if(imgIndex == imgList.size()){
					break;
				}
			}
		}
	}
	class DrawImage extends Thread{
		int x,y;
		public DrawImage(int x,int y){
			this.x = x;
			this.y = y;
		}
		@Override
		public void run() {
			super.run();
			while(true){
				if(!bmList.isEmpty()){
					Canvas canvas = holder.lockCanvas(new Rect(x, y, x+imgWidth, y+imgHeight));
					long start = SystemClock.elapsedRealtime();
					canvas.drawBitmap(bmList.removeFirst(), x, y, new Paint());
					long last = SystemClock.elapsedRealtime()-start;
					if(last<100L){
						SystemClock.sleep(100L-last);
					}
					holder.unlockCanvasAndPost(canvas);
				}else if(imgIndex == imgList.size()){
					break;
				}
			}
			handler.post(new Runnable() {
				@Override
				public void run() {
					btn2.setClickable(true);
				}
			});
		}
	}
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Button 
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="單個獨立線程"/>
    <Button 
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="兩個獨立線程"/>
    <SurfaceView 
        android:id="@+id/surfaceview1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>
</LinearLayout>
發佈了56 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章