Android 手繪 – 支持保存為圖片

畫瞭一個非常難看的機器人。。。

附上關鍵代碼:

MainView.java

001
package com.tszy.views;
002
 
003
import java.io.File;
004
import java.io.FileNotFoundException;
005
import java.io.FileOutputStream;
006
import java.io.IOException;
007
 
008
import android.content.Context;
009
import android.graphics.Bitmap;
010
import android.graphics.Bitmap.CompressFormat;
011
import android.graphics.Bitmap.Config;
012
import android.graphics.Canvas;
013
import android.graphics.Color;
014
import android.graphics.Paint;
015
import android.graphics.Path;
016
import android.util.AttributeSet;
017
import android.view.MotionEvent;
018
import android.view.View;
019
 
020
public class MainView extends View {
021
    private Paint paint;
022
    private Canvas cacheCanvas;
023
    private Bitmap cachebBitmap;
024
    private Path path;
025
    
026
    private int clr_bg, clr_fg;
027
 
028
    
029
    public MainView(Context context, AttributeSet attrs) {
030
        super(context, attrs);
031
        
032
        clr_bg = Color.WHITE;
033
        clr_fg = Color.CYAN;
034
        
035
        paint = new Paint();
036
        paint.setAntiAlias(true); // 抗鋸齒
037
        paint.setStrokeWidth(3); // 線條寬度
038
        paint.setStyle(Paint.Style.STROKE); // 畫輪廓
039
        paint.setColor(clr_fg); // 顏色
040
        
041
        path = new Path();
042
        // 創建一張屏幕大小的位圖,作為緩沖
043
        cachebBitmap = Bitmap.createBitmap(480, 800, Config.ARGB_8888);
044
        cacheCanvas = new Canvas(cachebBitmap);
045
        cacheCanvas.drawColor(clr_bg);
046
    }
047
 
048
    public MainView(Context context) {
049
        super(context);
050
    }
051
    
052
    @Override
053
    protected void onDraw(Canvas canvas) {
054
        canvas.drawColor(clr_bg);
055
 
056
        // 繪制上一次的,否則不連貫
057
        canvas.drawBitmap(cachebBitmap, 0, 0, null);
058
        canvas.drawPath(path, paint);     
059
    }
060
    
061
    /**
062
     * 清空畫佈
063
     */
064
    public void clear() {
065
        path.reset();
066
        cacheCanvas.drawColor(clr_bg);
067
        invalidate();
068
    }
069
    
070
    /**
071
     * 將畫佈的內容保存到文件
072
     * @param filename
073
     * @throws FileNotFoundException
074
     */
075
    public void saveToFile(String filename) throws FileNotFoundException {
076
        File f = new File(filename);
077
        if(f.exists())
078
            throw new RuntimeException("文件:" + filename + " 已存在!");
079
            
080
        FileOutputStream fos = new FileOutputStream(new File(filename));
081
        //將 bitmap 壓縮成其他格式的圖片數據
082
        cachebBitmap.compress(CompressFormat.PNG, 50, fos);
083
        try {
084
            fos.close();
085
        } catch (IOException e) {
086
            // TODO Auto-generated catch block
087
            e.printStackTrace();
088
        }
089
    }
090
 
091
    private float cur_x, cur_y;
092
    private boolean isMoving;
093
    @Override
094
    public boolean onTouchEvent(MotionEvent event) {
095
        // TODO Auto-generated method stub
096
        float x = event.getX();
097
        float y = event.getY();
098
 
099
        switch (event.getAction()) {
100
            case MotionEvent.ACTION_DOWN : {
101
                cur_x = x;
102
                cur_y = y;
103
                path.moveTo(cur_x, cur_y);
104
                isMoving = true;
105
                break;
106
            }
107
 
108
            case MotionEvent.ACTION_MOVE : {
109
                if (!isMoving)
110
                    break;
111
 
112
                // 二次曲線方式繪制
113
                path.quadTo(cur_x, cur_y, x, y);
114
                // 下面這個方法貌似跟上面一樣
115
                // path.lineTo(x, y);
116
                cur_x = x;
117
                cur_y = y;
118
                break;
119
            }
120
 
121
            case MotionEvent.ACTION_UP : {
122
                // 鼠標彈起保存最後狀態
123
                cacheCanvas.drawPath(path, paint);
124
                path.reset();
125
                isMoving = false;
126
                break;
127
            }
128
        }
129
 
130
        // 通知刷新界面
131
        invalidate();
132
 
133
        return true;
134
    }
135
 
136
}
Activity 代碼:

01
@Override
02
    public void onClick(View v) {
03
        // TODO Auto-generated method stub
04
        switch (v.getId()) {
05
            case R.id.iv_btn_clear :
06
                view.clear();
07
                break;
08
 
09
            case R.id.iv_btn_save : {
10
                try {
11
                    String sdState = Environment.getExternalStorageState(); // 判斷sd卡是否存在
12
 
13
                    // 檢查SD卡是否可用
14
                    if (!sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
15
                        Toast.makeText(this, "SD卡未準備好!", Toast.LENGTH_SHORT).show();
16
                        break;
17
                    }
18
 
19
                    //獲取系統圖片存儲路徑
20
                    File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
21
                    // Make sure the Pictures directory exists.
22
                    path.mkdirs();
23
                    
24
                    //根據當前時間生成圖片名稱
25
                    Calendar c = Calendar.getInstance();
26
                    String name = ""
27
                            + c.get(Calendar.YEAR) + c.get(Calendar.MONTH) + c.get(Calendar.DAY_OF_MONTH)
28
                            + c.get(Calendar.HOUR_OF_DAY) + c.get(Calendar.MINUTE) + c.get(Calendar.SECOND)
29
                             + ".png";
30
                    
31
                    //合成完整路徑,註意 / 分隔符
32
                    String string = path.getPath() + "/" + name;
33
                    view.saveToFile(string);
34
                    Toast.makeText(this, "保存成功!\n文件保存在:" + string, Toast.LENGTH_LONG).show();
35
                } catch (FileNotFoundException e) {
36
                    Toast.makeText(this, "保存失敗!\n" + e, Toast.LENGTH_LONG).show();
37
                }
38
                break;
39
            }
40
        }
41
    }
沒什麼難度,主要是將Bitmap轉PNG圖片那裡,找瞭一會發現 Canvas 沒有直接或間接保存的方法,剛好這裡我使用瞭雙緩沖,另一塊畫佈的內容位圖自己創建的,很自然想到將這個畫佈的位圖保存為文件即可。

再查看 Bitmap 有個 compress(CompressFormat format, int quality,OutputStream stream) 方法,很明顯將文件輸出流傳給這個方法就OK

You May Also Like