標籤:
一直對畫畫相關不感冒,但是Android的繪圖機制還是要硬著頭皮學
繪畫主要是使用paint(畫筆)在canvas(畫布)進行各種圖形的繪製,畫矩形、圓、三角形等點線構成的2維圖形
//矩形 drawRect (float left, float top, float right, float bottom, Paint paint) canvas.drawRect(50, 100, 200, 200, paint); //圓 drawCircle (float cx, float cy, float radius, Paint paint) canvas.drawCircle(width / 2, height / 2, 100, paint); //三角形(畫線) //執行個體化路徑 Path path = new Path(); path.moveTo(80, 300);// 此點為多邊形的起點 path.lineTo(120, 250); path.lineTo(80, 250); path.close(); // 使這些點構成封閉的多邊形 canvas.drawPath(path, paint); //扇形 RectF (float left, float top, float right, float bottom) RectF rectF = new RectF(160, 200, 400, 400); // drawArc (RectF oval, float startAngle 起始弧度, float sweepAngle 掃過的弧度, boolean useCenter, Paint paint) canvas.drawArc(rectF, 200, 130, true, paint); //橢圓 rectF = new RectF(300, 300, 600, 600); // set (float left, float top, float right, float bottom) rectF.set(210,100,450,200); // drawOval (RectF oval, Paint paint) canvas.drawOval(rectF, paint); //曲線 //設定空心 paint.setStyle(Paint.Style.STROKE); path = new Path(); path.moveTo(500, 500);//設定Path的起點 path.quadTo(550, 510, 670, 600); //設定路徑點和終點 canvas.drawPath(path, paint); //文字+ 圖片 paint.setTextSize(30); //文本 drawText (String text, float x, float y, Paint paint) canvas.drawText("slack", 350, 330, paint); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); //圖片 drawBitmap (Bitmap bitmap, float left, float top, Paint paint) canvas.drawBitmap(bitmap, 320, 360, paint);canvas有幾個重要的方法,畫圖時會使用到,類似ps裡的圖層,旋轉,位移的概念
/* * Canvas.save() 將之前的映像儲存起來,讓後續的操作能像在新的畫布一樣操作 * Canvas.restore() 合并圖層 * Canvas.translate() 平移 我們繪製的時候預設座標點事左上方的起始點,那麼我們調用translate(x,y)之後, 則將原點(0,0)移動到(x,y)之後的所有繪圖都是在這一點上執行的 * Canvas.roate() 旋轉 * */
畫一個時鐘,就把這些理解了
//畫時鐘 // 畫外圓 Paint paintCircle = new Paint(); paintCircle.setAntiAlias(true); paintCircle.setStyle(Paint.Style.STROKE); paintCircle.setStrokeWidth(5); canvas.drawCircle(width / 2, height / 2, width / 3, paintCircle); // 畫刻度 Paint paintDegree = new Paint(); paintDegree.setStrokeWidth(3); canvas.rotate(30, width / 2, height / 2); for (int i = 1; i <= 12; i++) { // 區別整點和非整點 if (i == 3 || i == 6 || i == 9 || i == 12 ) { paintDegree.setStrokeWidth(5); paintDegree.setTextSize(30); // drawLine (float startX, float startY, float stopX, float stopY, Paint paint) canvas.drawLine(width / 2, height / 2 - width / 3, width / 2, height / 2 - width / 3 + 60, paintDegree); String degree = String.valueOf(i); canvas.drawText(degree, width / 2 - paintDegree.measureText(degree) / 3, height / 2 - width / 3 + 90, paintDegree); } else { paintDegree.setStrokeWidth(3); paintDegree.setTextSize(15); // 圓上的一點(x = 螢幕寬一半, y = 螢幕的一半 - 半徑) canvas.drawLine(width / 2, height / 2 - width / 3, width / 2, height / 2 - width / 3 + 30, paintDegree); String degree = String.valueOf(i); canvas.drawText(degree, width / 2 - paintDegree.measureText(degree) / 3, height / 2 - width / 3 + 60, paintDegree); } // 通過旋轉畫布——實際上是旋轉了畫圖的座標軸 簡化座標運算 canvas.rotate(30, width / 2, height / 2); } canvas.save(); // 畫指標 Paint paintHour = new Paint(); paintHour.setStrokeWidth(15); Paint paintMinute = new Paint(); paintMinute.setStrokeWidth(10); //繪製的時候預設座標點事左上方的起始點,那麼我們調用translate(x,y)之後,則將原點(0,0)移動到(x,y)之後的所有繪圖都是在這一點上執行的 canvas.translate(width / 2, height / 2); canvas.drawPoint(0, 0, paintHour);//圓點 canvas.drawLine(0, 0, 100, 100, paintHour); canvas.drawLine(0, 0, 100, -200, paintMinute); canvas.restore();類比刮刮樂
// PorterDuffXfermode 刮刮樂 通過DST_IN.SRC_IN模式來實現將一個矩形變成圓角圖片的效果 mPaint = new Paint(); mPaint.setAlpha(0); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeWidth(50); mPaint.setStrokeCap(Paint.Cap.ROUND); mPath = new Path(); // createBitmap (int width, int height, Bitmap.Config config) mFgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mFgBitmap); mCanvas.drawColor(Color.GRAY);
/** * 觸摸事件 * 畫一條透明的線 曲線 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.reset(); lastX = event.getX(); lastY = event.getY(); mPath.moveTo(lastX, lastY);//起點 break; case MotionEvent.ACTION_UP: mPath.lineTo(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: //移動時,記錄這一次的點位置 mPath.quadTo(lastX, lastY, event.getX(), event.getY()); //設定曲線路徑點和終點 lastX = event.getX(); lastY = event.getY(); break; } mCanvas.drawPath(mPath, mPaint); invalidate(); return true; }
@Override public void draw(Canvas canvas) { super.draw(canvas); //刮刮樂 canvas.drawBitmap(mFgBitmap, 0, 0, null); }
SurfaceView主要用於頻繁重新整理處,做一個畫板
SurfaceView的簡單使用也簡單
public class SurfaView extends SurfaceView implements SurfaceHolder.Callback, Runnable
線上程裡處理繪畫的事件,貼上代碼
import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;/** * SurfaceView的使用 * Created by chenling on 2016/5/9. * 1.View主要用於自動更新的情況下,而surfaceVicw主要適用於被動更新,例如頻繁重新整理 * 2.View在主線程中重新整理,而surfaceView通常會通過一 個子線程來進行頁面重新整理。 * 3.View在繪製的時候沒有雙緩衝機制,而surfaceVicw在底層實現機制中就已經實現了雙緩衝機制; */public class SurfaView extends SurfaceView implements SurfaceHolder.Callback, Runnable { //SurfaceHolder private SurfaceHolder mHolder; //用於繪製的Canvas private Canvas mCanvas; //子線程標誌位 private boolean mIsDrawing; private float lastX,lastY; private Path mPath; private Paint mPaint; /** * 構造方法 * * @param context * @param attrs */ public SurfaView(Context context, AttributeSet attrs) { super(context, attrs); mPath = new Path(); mPaint = new Paint(); mPaint.setStrokeWidth(20); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mHolder = getHolder(); mHolder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); setKeepScreenOn(true); } // 建立 @Override public void surfaceCreated(SurfaceHolder holder) { mIsDrawing = true; new Thread(this).start(); } // 改變 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } //銷毀 @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDrawing = false; } @Override public void run() { while (mIsDrawing) { draw();// lastX += 1;// lastY = (int) (100 * Math.sin(lastX * 2 * Math.PI / 180) + 400);// mPath.lineTo(lastX, lastY); } } // 負責繪畫,頻繁重新整理 private void draw() { try { mCanvas = mHolder.lockCanvas(); mCanvas.drawColor(Color.WHITE); mCanvas.drawPath(mPath, mPaint); } catch (Exception e) { } finally { if (mCanvas != null) { //提交 mHolder.unlockCanvasAndPost(mCanvas); } } } /** * 觸摸事件 * * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { lastX = event.getX(); lastY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.moveTo(lastX, lastY); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(lastX,lastY); break; case MotionEvent.ACTION_UP: break; } return true; }}
附件:源碼:https://github.com/CL-window/android_paint
Android之繪圖