| 目錄(?)[+] |
Android Framework 提供了一些2D 畫圖的 API,android.graphics 包就是其中之一。
為了畫一些東西,需要4個(gè)元素(或稱組件)協(xié)同來完成:
位圖:Bitmap 來保持(hold)那些像素
畫布:Canvas 來響應(yīng)畫畫(draw)的調(diào)用(并將其寫入 bitmap)
畫筆:paint 描述畫畫的顏色和樣式等
而這其中 Canvas 是比較重要的一環(huán),今天就來演示 Canvas 的基本使用方法。
android.graphics.Canvas 類提供了很多“畫“的方法,讓這塊畫布具有了豐富多彩的畫畫能力。比如:畫點(diǎn)、線、矩形、橢圓、圓、文字等等。下面的例子演示了這些方法的使用。
先來建一個(gè)類,繼承自 View。讓畫布鋪在 View 上而顯示出來(這也是自定義 UI 組件的路子)。
重載 onDraw 方法,讓這些畫畫的步驟在 onDraw 中完成。
源碼如下:
package com.lazytech.canvasdemo;
public class PaintBoard extends View {
public PaintBoard(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//paint a circle
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
canvas.drawCircle(120, 80, 60, paint);
//paint string
paint = new Paint();
paint.setColor(Color.YELLOW);
paint.setTextSize(20);
canvas.drawText("My name is Linc!",245,140,paint);
//draw line
paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawLine(245,145,500,145,paint);
}
}
只要在 Activity 的布局文件中加上這個(gè) view 就可以了。如下:
<com.lazytech.canvasdemo.PaintBoard
android:id="@+id/paint_board"
android:layout_width="match_parent"
android:layout_below="@id/text"
android:layout_height="200dp"
android:background="@android:color/holo_green_light"
/>
有了上面的基礎(chǔ),我們就可以發(fā)揮一下,寫一個(gè)畫板的 demo。隨著手指的滑動(dòng),屏幕上留下了你藝術(shù)的痕跡。那么這個(gè)畫板要如何實(shí)現(xiàn)呢?
有幾個(gè)點(diǎn)要抓?。?
捕捉你手指的滑動(dòng)軌跡。重載 onTouchEvent 方法來實(shí)現(xiàn)。
實(shí)時(shí)更新你的畫圖。用 invalidate 方法來通知 onDraw 重繪。
有了上述要點(diǎn)整理,我們開始工作吧。首先還是建一個(gè)畫板類 PaintBoard2繼承自 View。三個(gè)重要元素作為類成員并在構(gòu)造函數(shù)中做初始化。
public class PaintBoard2 extends View {
private Paint mPaint = null;
private Bitmap mBitmap = null;
private Canvas mBitmapCanvas = null;
public PaintBoard2(Context context, AttributeSet attrs) {
super(context, attrs);
mBitmap = Bitmap.createBitmap(500,200, Bitmap.Config.ARGB_8888);
mBitmapCanvas = new Canvas(mBitmap);
mBitmapCanvas.drawColor(Color.GRAY);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(6);
}
隨著手指滑動(dòng)去畫線:
private float startX;
private float startY ;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float stopX = event.getX();
float stopY = event.getY();
Log.e(TAG,"onTouchEvent-ACTION_MOVE\nstartX is "+startX+
" startY is "+startY+" stopX is "+stopX+ " stopY is "+stopY);
mBitmapCanvas.drawLine(startX, startY, stopX, stopY, mPaint);
startX = event.getX();
startY = event.getY();
invalidate();//call onDraw()
break;
}
return true;
}
在 onDraw 時(shí)畫 bitmap:
@Override
protected void onDraw(Canvas canvas) {
if(mBitmap != null) {
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
}
提供一個(gè)將 bitmap 存入 OutputStream 的方法供保存位圖做準(zhǔn)備。
public void saveBitmap(OutputStream stream) {
if (mBitmap != null) {
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
}
}
它是如何在 Activity 中調(diào)用的呢?
activity 的 layout:
<com.lazytech.canvasdemo.PaintBoard2
android:id="@+id/paint_board2"
android:layout_below="@id/paint_board"
android:layout_width="match_parent"
android:layout_height="200dp" />
<Button
android:id="@+id/btn_save"
android:text="Save"
android:layout_below="@id/paint_board2"
android:onClick="OnSaveClicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
定義 PaintBoard2 作為 Activity 的成員,并在 onCreate 初始化:
private PaintBoard2 paintBoard2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
paintBoard2 = (PaintBoard2)findViewById(R.id.paint_board2);
}
點(diǎn)擊保存按鈕的處理:
public void OnSaveClicked(View view) {
try {
File file = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
OutputStream stream = new FileOutputStream(file);
paintBoard2.saveBitmap(stream);
stream.close();
// send broadcast to Media to update data
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment
.getExternalStorageDirectory()));
sendBroadcast(intent);
Toast.makeText(this, "save success", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "save failed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
截圖風(fēng)采:
http://wiki.jikexueyuan.com/project/android-actual-combat-skills/images/29-1.png" alt="fig.1" />
完成源碼參考我的開源 demo 項(xiàng)目:
https://code.csdn.net/lincyang/androidwidgetdemo
參考:
http://www.cnblogs.com/menlsh/archive/2012/11/18/2776003.html