android 仿qq手写板涂鸦

时间:2022-04-24
本文章向大家介绍android 仿qq手写板涂鸦,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

以前博客的链接:点击打开链接

附上关键代码:

MainView.java

package com.tszy.views;  
 
import java.io.File;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
 
import android.content.Context;  
import android.graphics.Bitmap;  
import android.graphics.Bitmap.CompressFormat;  
import android.graphics.Bitmap.Config;  
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.View;  
 
public class MainView extends View {  
 private Paint paint;  
 private Canvas cacheCanvas;  
 private Bitmap cachebBitmap;  
 private Path path;  
 
 private int clr_bg, clr_fg;  
 
 
 public MainView(Context context, AttributeSet attrs) {  
 super(context, attrs);  
 
        clr_bg = Color.WHITE;  
        clr_fg = Color.CYAN;  
 
        paint = new Paint();  
        paint.setAntiAlias(true); // 抗锯齿 
        paint.setStrokeWidth(3); // 线条宽度 
        paint.setStyle(Paint.Style.STROKE); // 画轮廓 
        paint.setColor(clr_fg); // 颜色 
 
        path = new Path();  
 // 创建一张屏幕大小的位图,作为缓冲 
        cachebBitmap = Bitmap.createBitmap(480, 800, Config.ARGB_8888);  
        cacheCanvas = new Canvas(cachebBitmap);  
        cacheCanvas.drawColor(clr_bg);  
    }  
 
 public MainView(Context context) {  
 super(context);  
    }  
 
 @Override 
 protected void onDraw(Canvas canvas) {  
        canvas.drawColor(clr_bg);  
 
 // 绘制上一次的,否则不连贯 
        canvas.drawBitmap(cachebBitmap, 0, 0, null);  
        canvas.drawPath(path, paint);         
    }  
 
 /** 
     * 清空画布 
     */ 
 public void clear() {  
        path.reset();  
        cacheCanvas.drawColor(clr_bg);  
        invalidate();  
    }  
 
 /** 
     * 将画布的内容保存到文件 
     * @param filename 
     * @throws FileNotFoundException 
     */ 
 public void saveToFile(String filename) throws FileNotFoundException {  
        File f = new File(filename);  
 if(f.exists())  
 throw new RuntimeException("文件:" + filename + " 已存在!");  
 
        FileOutputStream fos = new FileOutputStream(new File(filename));  
 //将 bitmap 压缩成其他格式的图片数据 
        cachebBitmap.compress(CompressFormat.PNG, 50, fos);  
 try {  
            fos.close();  
        } catch (IOException e) {  
 // TODO Auto-generated catch block 
            e.printStackTrace();  
        }  
    }  
 
 private float cur_x, cur_y;  
 private boolean isMoving;  
 @Override 
 public boolean onTouchEvent(MotionEvent event) {  
 // TODO Auto-generated method stub 
 float x = event.getX();  
 float y = event.getY();  
 
 switch (event.getAction()) {  
 case MotionEvent.ACTION_DOWN : {  
                cur_x = x;  
                cur_y = y;  
                path.moveTo(cur_x, cur_y);  
                isMoving = true;  
 break;  
            }  
 
 case MotionEvent.ACTION_MOVE : {  
 if (!isMoving)  
 break;  
 
 // 二次曲线方式绘制 
                path.quadTo(cur_x, cur_y, x, y);  
 // 下面这个方法貌似跟上面一样 
 // path.lineTo(x, y); 
                cur_x = x;  
                cur_y = y;  
 break;  
            }  
 
 case MotionEvent.ACTION_UP : {  
 // 鼠标弹起保存最后状态 
                cacheCanvas.drawPath(path, paint);  
                path.reset();  
                isMoving = false;  
 break;  
            }  
        }  
 
 // 通知刷新界面 
        invalidate();  
 
 return true;  
    }  
 
}  

Activity 代码:

@Override 
 public void onClick(View v) {  
 // TODO Auto-generated method stub 
 switch (v.getId()) {  
 case R.id.iv_btn_clear :  
                view.clear();  
 break;  
 
 case R.id.iv_btn_save : {  
 try {  
                    String sdState = Environment.getExternalStorageState(); // 判断sd卡是否存在 
 
 // 检查SD卡是否可用 
 if (!sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {  
                        Toast.makeText(this, "SD卡未准备好!", Toast.LENGTH_SHORT).show();  
 break;  
                    }  
 
 //获取系统图片存储路径 
                    File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);  
 // Make sure the Pictures directory exists. 
                    path.mkdirs();  
 
 //根据当前时间生成图片名称 
                    Calendar c = Calendar.getInstance();  
                    String name = "" 
                            + c.get(Calendar.YEAR) + c.get(Calendar.MONTH) + c.get(Calendar.DAY_OF_MONTH)   
                            + c.get(Calendar.HOUR_OF_DAY) + c.get(Calendar.MINUTE) + c.get(Calendar.SECOND)  
                             + ".png";  
 
 //合成完整路径,注意 / 分隔符 
                    String string = path.getPath() + "/" + name;  
                    view.saveToFile(string);  
                    Toast.makeText(this, "保存成功!n文件保存在:" + string, Toast.LENGTH_LONG).show();  
                } catch (FileNotFoundException e) {  
                    Toast.makeText(this, "保存失败!n" + e, Toast.LENGTH_LONG).show();  
                }  
 break;  
            }  
        }  
    }  

没什么难度,主要是将Bitmap转PNG图片那里,找了一会发现 Canvas 没有直接或间接保存的方法,刚好这里我使用了双缓冲,另一块画布的内容位图自己创建的,很自然想到将这个画布的位图保存为文件即可。

再查看 Bitmap 有个 compress(CompressFormat format, int quality,OutputStream stream) 方法,很明显将文件输出流传给这个方法就OK

@Override 
 public void onClick(View v) {  
 // TODO Auto-generated method stub 
 switch (v.getId()) {  
 case R.id.iv_btn_clear :  
                view.clear();  
 break;  
 
 case R.id.iv_btn_save : {  
 try {  
                    String sdState = Environment.getExternalStorageState(); // 判断sd卡是否存在 
 
 // 检查SD卡是否可用 
 if (!sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {  
                        Toast.makeText(this, "SD卡未准备好!", Toast.LENGTH_SHORT).show();  
 break;  
                    }  
 
 //获取系统图片存储路径 
                    File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);  
 // Make sure the Pictures directory exists. 
                    path.mkdirs();  
 
 //根据当前时间生成图片名称 
                    Calendar c = Calendar.getInstance();  
                    String name = "" 
                            + c.get(Calendar.YEAR) + c.get(Calendar.MONTH) + c.get(Calendar.DAY_OF_MONTH)   
                            + c.get(Calendar.HOUR_OF_DAY) + c.get(Calendar.MINUTE) + c.get(Calendar.SECOND)  
                             + ".png";  
 
 //合成完整路径,注意 / 分隔符 
                    String string = path.getPath() + "/" + name;  
                    view.saveToFile(string);  
                    Toast.makeText(this, "保存成功!n文件保存在:" + string, Toast.LENGTH_LONG).show();  
                } catch (FileNotFoundException e) {  
                    Toast.makeText(this, "保存失败!n" + e, Toast.LENGTH_LONG).show();  
                }  
 break;  
            }  
        }  
    }