Android 中隨機畫線


       在剛收到這個任務是,我就想起了Bitmap Canvas Paint這些類。並且發現畫線的長短,顏色都是隨機的,這也說明了
每次畫線時顏色和長短都要隨機生成;而線的長短則是由座標控制的,並且啓始座標是手機屏幕中心。所以我在onCreate()
中使用
        WindowManager wm = this.getWindowManager();
        int width = wm.getDefaultDisplay().getWidth();
        int height = wm.getDefaultDisplay().getHeight();
獲取得到手機屏幕的寬和高,所以接下來隨機長短就可以以創建Random對象調用nextInt(width)/nextInt(height)來確定線的長度

繪圖所必須的3個類使用方法自己總結了一下:
             Bitmap :@1 創建mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 確定保存繪製內容的範圍
                         @2  bitmap有保存繪製內容的作用

             Paint    :@1 主要就是創建一個畫筆Paint mpaint = new Paint();
                          @2 設置paint的顏色setColor()    設置paint的寬度

             Canvas :@1 主要是繪製圖畫創建一個canvas = new Canvas(mBitmap);【這步作用:把繪製內容保存入mBitmap中】
                          @2 canvas調用drawLine(startX,startY,stopX,stopY,paint);來劃線

但是在編寫程序過程中還是遇到了很多問題:
   1、在oncreate()中進行操做:首先,在onCreate()中隨機畫一條先線,OK。於是在onCreate()中循環畫10條線,問題出現,apk界面
顯示UI需要等幾秒中開始更新。因爲沒有無限循環所以,暫時沒有出現問題,只是UI更新慢了點。
    於是在onCreate()中創建一個線程,實現循環,問題還是存在。
    
    2、使用SurfaceView: 上網查找問題,看到了surfaceView繪製動畫,於是使用了一下發現當每次劃線都會更新一次,不是想要的效果。

    3、自定義空間 :看了一下師傅做的,發現他是使用自定義控件,由於沒有自定義過控件。自己試着自定義後,去使用發現總是報Binary xml file line # Error inflating class” 查找原因後是沒有重寫View構造函數的原因,具體在“Android運行時異常“Binary XML file line # : Error inflating class” “博客中有相關的介紹。調整之後發現可以使用,也可以成功。
    4、眼高手底: 在定義變量後,在畫圖中沒有使用或者是在使用paint時忘了創建對象等等,導致NULLPointerException異常的出現
 
    5、子線程更新UI會發生android.view.ViewRoot$CalledFromWrongThreadException,這個問題是因爲沒有處理好耗時操作,所以我創建了Hander的子類在執行run()方法是發送一條消息,在子類中接收消息去調用畫圖方法。
                                                                                                                                                                                              _    _
在學習師傅方法的同時去改進自己的方法,我把好的他的思路和方法結合我的思路,通過實踐完成了小組任務,感覺學到了很多。~(@.@)~
                                                                                                                                                                                                |    |
  

下面是使用兩種方式做的畫線apk

傳不上資源庫,直接貼代碼:
【Draw是使用自定義控件畫線】

控件類MyView 繼承了View類
<span style="font-size:14px;">package com.example.view;

import java.util.Random;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {
	private Bitmap bitmap ;				//保存繪製結果
	private Canvas tempCanvas;		//創建畫布	
	private Paint paint = new Paint();
	private int width;	//畫布的寬度
	private int height;	//畫布的高度
	private int startX;		//畫線的開始X座標
	private int startY;		//畫線的開始Y座標
	private int stopX;		//畫線結束的X座標
	private int stopY;		//畫線結束的Y座標
	private int paintColor;		//畫筆的顏色
	private Random paintRL = new Random();	//創建隨機對象
	private int[] paintColors = new int[] { Color.RED, Color.BLUE,
			Color.YELLOW, Color.GREEN, Color.CYAN };

	/*
	 * 自定義控件必須實現的3個方法
	 * */
	public MyView(Context context) {
		super(context);
	}
	public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}
	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	//當線程調用時把bitmap清空
	public void clear(){
		bitmap = null;
	}
	@Override
	protected void onDraw(Canvas canvas) {
		//canvas.drawColor(Color.BLACK);
		width = canvas.getWidth();
		height = canvas.getHeight();
	
			paintColor = paintColors[paintRL.nextInt(5)];
			paint.setColor(paintColor);
			paint.setStrokeWidth(5);
			
			startX = width/2;
			startY = height/2;
			stopX = paintRL.nextInt(width);
			stopY = paintRL.nextInt(height);
			
			if(bitmap == null)//如果bitmap爲空,重新創建新的Bitmap.
			{
				bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
				canvas.drawBitmap(bitmap, 0, 0, paint);
			}else
			{	//把線先存放到bitmap中
				tempCanvas = new Canvas(bitmap);
				tempCanvas.drawLine(startX, startY, stopX, stopY, paint);
				//把bitmap中所有的先重新繪製
				canvas.drawBitmap(bitmap, 0, 0, paint);
			}		
	}
}</span>

MainActivity
<span style="font-size:14px;">package com.dewav.draw;

import com.example.view.MyView;

import android.app.Activity;
import android.os.Bundle;


public class MainActivity extends Activity {
	public MyView myView ;
	boolean closeActivity ;
	int  count=1;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		onDrawLine();
	}

	public void onDrawLine()
	{
		myView = (MyView) findViewById(R.id.myView);
		new Thread(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				while(true)
				{
					if(count>100){
						myView.clear();
						count = 1;
					}
					myView.postInvalidate();
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					count ++;
					if(closeActivity)
					{
						return ;
					}
				}
			}
			
		}.start();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		closeActivity = true;
	}
	
	
}</span>
main_layout:

<span style="font-size:14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.dewav.draw.MainActivity" >

   <com.example.view.MyView 
        android:id="@+id/myView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
       />

</RelativeLayout></span>

【archerDrewline使用的是控件imageView畫線】

mainActivity:
package com.example.archerdrawline;

import java.util.Random;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.ImageView;


public class MainActivity extends Activity {
	 boolean isQuit = false;
	 boolean clearBitmap = false;
	 int width;
	 int height;
	 int paintColor;
	 int[] paintColors = new int[]{Color.RED,Color.BLUE,Color.YELLOW,Color.GREEN,Color.CYAN};
	 ImageView mImageView;
	 Paint paint;				//畫筆
	 Bitmap mBitmap; //保存所有繪畫
	 Canvas mCanvas;	//用於畫線的畫布
	 Random paintRL = new Random();
	 private Handler messageHandler;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mImageView = (ImageView) findViewById(R.id.imageV);
		WindowManager wm = this.getWindowManager();
		width = wm.getDefaultDisplay().getWidth();
		height = wm.getDefaultDisplay().getHeight();
		
		//得到當前線程的Looper實例,由於當前線程是UI線程也可以通過Looper.getMainLooper()得到
		Looper looper = Looper.myLooper();
		 //此處甚至可以不需要設置Looper,因爲 Handler默認就使用當前線程的Looper
		messageHandler = new MessageHandler(looper);
		init();
	}
	
	public void init()
	{
		new Thread(){

			@Override
			public void run() {
				super.run();
				int count =0;
				while (true) {
					count++;
					if (count > 1000) {
						// 清屏重新畫
						//mBitmap.isRecycled();
						clearBitmap = true;
						count = 0;
					}
					messageHandler.sendEmptyMessage(0);
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//如果退出了 結束線程
					if (isQuit) {
						break;
					}
				}
			}
		}.start();
	}
	
	//創建畫圖
	public void doDraw(){

		if(clearBitmap)
		{
			mBitmap = null;
			clearBitmap= false;
		}
		//開始點在屏幕中心(get center coordinates)
				float startX = width/2;
				float startY = height/2;
				float stopX = paintRL.nextInt(width);
				float stopY = paintRL.nextInt(height);
		if(mBitmap ==null)
		{
			//創建一個位圖用來存放		
			mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
			mImageView.setImageBitmap(mBitmap);
		}else{
			paint = new Paint();//由於沒有創建畫筆對象,總是報null object reference
			paintColor = paintColors[paintRL.nextInt(5)];
			paint.setColor(paintColor);
			paint.setStrokeWidth(5);
			
			//把線畫到bitmap上
			mCanvas = new Canvas(mBitmap);
			mCanvas.drawLine(startX, startY, stopX, stopY, paint);
		}
		//再把bitmap畫到canvas上
		mImageView.setImageBitmap(mBitmap);
		/*Message message = Message.obtain();
		message.obj = mBitmap;
		messageHandler.sendMessage(message);*/
	}

	class MessageHandler extends Handler{

		
		public MessageHandler(Looper looper) {
			super(looper);
			// TODO Auto-generated constructor stub
		}

		@Override
		public void handleMessage(Message msg) {
			//mImageView.setImageBitmap((Bitmap)msg.obj);
			doDraw();
		}
		
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		isQuit = true;
	}

}

main_layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.archerdrawline.MainActivity" >

<ImageView
    android:id="@+id/imageV"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:background="@drawable/bg"
    />

</RelativeLayout>




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章