Android編程實現(xiàn)畫板功能的方法總結(jié)【附源碼下載】
本文實例講述了Android編程實現(xiàn)畫板功能的方法。分享給大家供大家參考,具體如下:
Android實現(xiàn)畫板主要有2種方式,一種是用自定義View實現(xiàn),另一種是通過Canvas類實現(xiàn)。當然自定義View內(nèi)部也是用的Canvas。第一種方式的思路是,創(chuàng)建一個自定義View(推薦SurfaceView),在自定義View里通過Path對象記錄手指滑動的路徑調(diào)用lineTo()繪制;第二種方式的思路是,先用Canvas繪制一張空的Bitmap,通過ImageView的setImageBitmap()方法加載這個Bitmap,然后該ImageView實現(xiàn)onTouch()監(jiān)聽事件,跟蹤用戶手指的移動調(diào)用drawLine()繪制線條。
我們先來看第一種的實現(xiàn)的方式吧。這里就用SurfaceView來實現(xiàn),在這里介紹一下關(guān)于SurfaceView的知識。SurfaceView繼承自View,兩者都可以實現(xiàn)繪圖功能,那么他們有什么不同呢。先說下Android繪制視圖的原理,View通過刷新來繪制視圖,Android系統(tǒng)則通過發(fā)出VSYNC信號進行屏幕繪制,玩游戲的朋友都應(yīng)該知道"垂直同步",VSYNC就是垂直同步,谷歌是在4.1之后引入VSYNC的,VSYNC是為了不讓畫面掉幀。為了不掉幀,View的繪制需要在16ms之內(nèi)完成。如果執(zhí)行耗時太長或者需要頻繁刷新,那么View就不合適了,影響用戶體驗和性能。用 SurfaceView就好辦了,它內(nèi)部是在子線程進行頁面刷新,使用了雙緩沖機制?,F(xiàn)在我們來使用它吧。
通常用法是創(chuàng)建一個View繼承自SurfaceView,并實現(xiàn)Callback和Runnable接口。
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback, Runnable {
// SurfaceHolder實例
private SurfaceHolder mSurfaceHolder;
// Canvas對象
private Canvas mCanvas;
// 控制子線程是否運行
private boolean startDraw;
// Path實例
private Path mPath = new Path();
// Paint實例
private Paint mpaint = new Paint();
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(); // 初始化
}
private void initView() {
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
// 設(shè)置可獲得焦點
setFocusable(true);
setFocusableInTouchMode(true);
// 設(shè)置常亮
this.setKeepScreenOn(true);
}
@Override
public void run() {
// 如果不停止就一直繪制
while (startDraw) {
// 繪制
draw();
}
}
/*
* 創(chuàng)建
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
startDraw = true;
new Thread(this).start();
}
/*
* 改變
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/*
* 銷毀
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
startDraw = false;
}
private void draw() {
try {
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeWidth(DensityUtil.px2dip(getContext(), 30));
mpaint.setColor(Color.BLACK);
mCanvas.drawPath(mPath, mpaint);
} catch (Exception e) {
} finally {
// 對畫布內(nèi)容進行提交
if (mCanvas != null) {
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX(); //獲取手指移動的x坐標
int y = (int) event.getY(); //獲取手指移動的y坐標
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
// 重置畫布
public void reset() {
mPath.reset();
}
}
我們在構(gòu)造方法里進行初始化,獲得SurfaceHolder實例,添加Callback接口實例,及獲得焦點等操作。重寫了SurfaceView的三個方法surfaceCreated,surfaceChanged,surfaceDestroyed。在surfaceCreated方法里開啟子線程,執(zhí)行draw方法。在surfaceDestroyed方法里關(guān)閉線程。在draw方法里,通過mSurfaceHolder.lockCanvas()獲取Canvas對象,設(shè)置樣式,顏色等,然后重寫onTouchEvent方法,監(jiān)聽用戶手指移動,調(diào)用mPath.lineTo(x, y)繪制線條,最后調(diào)用mSurfaceHolder.unlockCanvasAndPost(mCanvas)提交畫布內(nèi)容.這樣就完成了畫板的繪制。

我在代碼里添加了reset()方法,可以重置畫布,只需要在MainActivity獲取SurfaceView對象,調(diào)用SurfaceView.reset()就可以了。
private Button reset_btn;
private MySurfaceView mview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
mview = (MySurfaceView) findViewById(R.id.MySurfaceView);
reset_btn = (Button) findViewById(R.id.reset_btn);
reset_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//清除
mview.reset();
}
});
現(xiàn)在我們看下第二種方式吧,其實原理和第一種差不太多,我就不贅述了。直接貼上代碼吧。
public class SecondActivity extends Activity {
private ImageView img;
private Bitmap mBitmap;
private Canvas canvas;
private Paint paint;
// 重置按鈕
private Button reset_btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
img = (ImageView) findViewById(R.id.img);
reset_btn = (Button) findViewById(R.id.reset_btn);
reset_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
img.setImageBitmap(null);
showImage();
}
});
// 繪圖
showImage();
}
private void showImage() {
// 創(chuàng)建一張空白圖片
mBitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);
// 創(chuàng)建一張畫布
canvas = new Canvas(mBitmap);
// 畫布背景為白色
canvas.drawColor(Color.WHITE);
// 創(chuàng)建畫筆
paint = new Paint();
// 畫筆顏色為藍色
paint.setColor(Color.BLUE);
// 寬度5個像素
paint.setStrokeWidth(5);
// 先將白色背景畫上
canvas.drawBitmap(mBitmap, new Matrix(), paint);
img.setImageBitmap(mBitmap);
img.setOnTouchListener(new OnTouchListener() {
int startX;
int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 獲取手按下時的坐標
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
// 獲取手移動后的坐標
int endX = (int) event.getX();
int endY = (int) event.getY();
// 在開始和結(jié)束坐標間畫一條線
canvas.drawLine(startX, startY, endX, endY, paint);
// 刷新開始坐標
startX = (int) event.getX();
startY = (int) event.getY();
img.setImageBitmap(mBitmap);
break;
}
return true;
}
});
}
}
有人肯定要問,能不能把繪制的內(nèi)容保存下來,這當然可以。
加上如下代碼就行。
File file = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
OutputStream stream;
try {
stream = new FileOutputStream(file);
mBitmap.compress(CompressFormat.JPEG, 200, stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
附:完整實例代碼點擊此處本站下載。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開發(fā)動畫技巧匯總》、《Android開發(fā)入門與進階教程》、《Android視圖View技巧總結(jié)》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android文件操作技巧匯總》、《Android資源操作技巧匯總》及《Android控件用法總結(jié)》
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
android實現(xiàn)http中請求訪問添加cookie的方法
這篇文章主要介紹了android實現(xiàn)http中請求訪問添加cookie的方法,實例分析了兩種添加cookie的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10
Android仿微信和QQ多圖合并框架(類似群頭像)的實現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于Android仿微信和QQ多圖合并框架的相關(guān)資料,其實就是我們平時所見的群聊頭像,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-12-12
Android中SharedPreference使用實例講解
這篇文章主要介紹了Android中SharedPreference使用方法,實現(xiàn)登陸界面記住密碼功能,感興趣的小伙伴們可以參考一下2016-01-01

