您的位置:首页 > 其它

涂鸦,Canvas绘图

2016-03-16 10:42 441 查看
    公司的项目里有一个功能是,用户有个涂鸦签字的功能,需要再白色面板上涂鸦,然后上传到又拍云,把又拍云返回的图片url通过post请求上传到服务器。摸索了一段时间,完成了这个功能,并且实现的不错。下面贴出截图跟部分demo:

   

    


上传到又拍云的那部分demo就不贴了,涉及到很多图片url定义规则还有项目隐私的东西,只贴到 保存图片到本地的,后面上传图片就是很简单啦!

1.自定义的ImageTextView.class

<span style="font-size:14px;">public class ImageEditTextView extends EditText {

private Paint mPaint;
private Rect mRect;
private Context mContext;

public ImageEditTextView(Context context) {
super(context);

mContext = context;

}

public ImageEditTextView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);

mContext = context;

}
public ImageEditTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub

mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);

mContext = context;
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
System.out.println("left:"+left+".top:"+top+".right:"+right+".bottom:"+bottom);
super.onLayout(changed, left, top, right, bottom);
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int windowWidth = wm.getDefaultDisplay().getWidth();
int windowHeight = wm.getDefaultDisplay().getHeight();

Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLACK);
paint.setColor(Color.WHITE);

int paddingTop    = getPaddingTop();
int paddingBottom = getPaddingBottom();

int scrollY       = getScrollY();  		//
int scrollX       = getScrollX()+windowWidth;
int innerHeight   = scrollY + getHeight() - paddingTop - paddingBottom;
int lineHeight    = getLineHeight();
int baseLine      = scrollY + (lineHeight - (scrollY % lineHeight));
int x = 8;
while (baseLine < innerHeight) {
//canvas.drawBitmap(line, x, baseLine + paddingTop, paint);

canvas.drawLine(x, baseLine + paddingTop,scrollX, baseLine + paddingTop, paint);
baseLine += lineHeight;
}
}

}</span>
2.自定义HandTouchView.class

public class HandTouchView extends View {
public Handler mbitmaphHandler;
public Handler getMbitmaphHandler() {
return mbitmaphHandler;
}
public void setMbitmaphHandler(Handler mbitmaphHandler) {
this.mbitmaphHandler = mbitmaphHandler;
}

private DisplayMetrics dm;
private Bitmap bitmap=null;
private Bitmap mBitmap=null;
private Bitmap myBitmap ;
private Paint mPaint=null;
private Canvas mCanvas=null;
private Paint mBitmapPaint=null;
private Timer timer=null;
private savePath sPath;
private List<savePath> lists =null;
private FingerMatrix fingerMatrix=null;
private float Xi,Yi;
private Path path=null;
public HandTouchView(Context context) {
super(context);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);

}

public HandTouchView(Context context, AttributeSet attrs) {
super(context, attrs);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);

}

public HandTouchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);

}

/**
* 初始化
* @param w
* @param h
*/
public void inter(int w,int h){
mBitmap =Bitmap.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(FingerMatrix.colorValue);
lists = new ArrayList<HandTouchView.savePath>();
fingerMatrix = new FingerMatrix();
timer = new Timer(true);				//定时器来截取字
}

public void minter(int w,int h){
mBitmap =Bitmap.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(FingerMatrix.colorValue);
lists = new ArrayList<HandTouchView.savePath>();
fingerMatrix = new FingerMatrix();
timer = new Timer(true);
}

public void RefreshPaint(){
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形 状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(Color.BLACK);
}

protected void onDraw(Canvas canvas) {
// 设置canvas画布背景为白色
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (path!=null) {
canvas.drawPath(path, mPaint);
}
super.onDraw(canvas);
}

/**
* 手指 移动事件
*/
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:			//按下屏幕时
mPaint.setColor(FingerMatrix.colorValue);
float x = event.getX();
float y = event.getY();
if (task!=null) {			//如果等于空
task.cancel();			//关闭定时器////将原任务从队列中移除
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);		//发给handler
}
};
}
//Log.i("线程", "触屏时的坐标"+x+"y坐标"+y);
if (fingerMatrix==null) {
fingerMatrix = new FingerMatrix();
//Log.i("线程", "<staRT>fingerMatrix等于空");
fingerMatrix.init(x, y);
}else {
fingerMatrix.getx(x);
//Log.i("线程", "<等于空>fingerMatrix等于空");
fingerMatrix.getY(y);
}
path = new Path();
sPath =new savePath();
sPath.paint = mPaint;		//保存路径
sPath.path = path;
path.moveTo(x, y);			//开始划线
Xi = x;
Yi = y;
invalidate();			//刷新
break;
case MotionEvent.ACTION_MOVE:			//移动中
float X1 = event.getX();
float Y1 = event.getY();
if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what=1;
handler.sendMessage(message);
}
};

}
if (fingerMatrix!=null) {
fingerMatrix.getx(X1);
fingerMatrix.getY(Y1);
//Log.i("线程", "fingerMatrix不等于空");
}
float j = Math.abs(X1-Xi);
float i = Math.abs(Yi-Y1);
if (j>=5||i>=5) {
path.quadTo(Xi, Yi, X1, Y1);
Xi = X1;
Yi = Y1;
}
invalidate();
break;
case MotionEvent.ACTION_UP:			//手指松下离开屏幕时
//一旦有在屏幕按下抬起操作时,就给SettleAccountActivity发送消息,告知已签字
Message message = new Message();
message.what=2;
message.arg1=1;
if (mbitmaphHandler!=null){
mbitmaphHandler.sendMessage(message);
}

float My = event.getX();		//手指离开屏幕时的坐标
float Mx = event.getY();
if (fingerMatrix!=null) {
fingerMatrix.getx(Mx);
//Log.i("线程", "离开"+Mx);
fingerMatrix.getY(My);
}
mCanvas.drawPath(path, mPaint);
lists.add(sPath);
invalidate();
if (timer!=null) {
if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
timer.schedule(task, 2200, 2200);				//2200秒后发送消息给handler更新Activity
}
}else {
timer = new Timer(true);
timer.schedule(task, 2200, 2200);					//2200秒后发送消息给handler更新Activity
}
break;
default:

if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
handler.sendEmptyMessage(0);
}
};

}
break;
}
return true;
}

/**
* 处理屏幕显示
*/
Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {			//handler告诉Activity处理数据
case 1:						//CUT_BITMAP_SEND_TO_ACTIVITY//切割图片发送给Activity处理
//Log.i("线程", "handler收到");
myBitmap = mBitmap;			//获取写好的图片
if (fingerMatrix!=null) {			//获取绘制的区域坐标
myBitmap = cutBitmap(myBitmap);					//切割Bitmap图片方法
}
fingerMatrix=null;
if (mbitmaphHandler!=null){

Matrix matrix = new Matrix();
matrix.postRotate(90); /*翻转90度*/
int width = myBitmap.getWidth();
int height =myBitmap.getHeight();
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, width, height, matrix, true);
saveBiamtImate(myBitmap);
}
Message message = new Message();
message.what=1;
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap",myBitmap);
message.setData(bundle);
if (mbitmaphHandler!=null){
mbitmaphHandler.sendMessage(message);
}
//RefreshCanvas();
break;
}
super.handleMessage(msg);
}
};

/**
* 发送消息给handler更新ACTIVITY
*/
TimerTask task = new TimerTask() {
public void run() {
Message message = new Message();
message.what=1;
//Log.i("线程", "来了");
handler.sendMessage(message);
}
};

/**
* 保存路径类
* @author Administrator
*/
class savePath{
Paint paint;
Path path;
}

/**
* 切割图片方法和更新Activity
* @param bnBitmap
*/
public Bitmap cutBitmap(Bitmap bnBitmap){
//最小
float minx = fingerMatrix.getMinX();		//最小的x坐标
float miny = fingerMatrix.getMinY();		//最小的y坐标
//最大
float maxy = fingerMatrix.getMaxY();		//最大的Y坐标
float maxX = fingerMatrix.getMaxX();		//最大的x坐标
//Log.i("","矩阵的坐标信息为:-======最大X:"+maxX+"----====最大Y:"+maxy+"----====最小X:"+minx+"----====最小Y:"+miny);
int cutMinX = (int)(minx-15);		//切割的最小值
int cutMinY = (int)(miny-15);		//切割的最小值
int cutMaxX = (int)(maxX+15);
int cutMaxY = (int)(maxy+15);
if (cutMinX<=0) {
cutMinX=0;
}
if (cutMinY<=0) {
cutMinY=0;
}
if (cutMaxX>mBitmap.getWidth()) {			//如果X坐标大于图片的宽度
cutMaxX =  mBitmap.getWidth()-1;		//那就把图片的宽度付给X坐标 的最大值
}
if (cutMaxY>mBitmap.getHeight()) {			//如果Y坐标大于图片的宽度
cutMaxY = mBitmap.getHeight()-1;		//那就把图片的宽度付给Y坐标 的最大值
}

int width =(int)(cutMaxX - cutMinX);		//最大的x坐标减去最小的x坐标
int height =(int)(cutMaxY-cutMinY);			//最大的Y坐标减去最小的y坐标

Bitmap wBitmap =Bitmap.createBitmap(bnBitmap, cutMinX, cutMinY, width, height);		//这个步骤意思是在什么坐标位置创建一张图片
if (myBitmap!=null ) {
//myBitmap.recycle();
myBitmap= null;
}
//Log.i("线程", "剪切图片成功");
return wBitmap;
}

/**
* 保存图片
* @param bitmap1
*/
public boolean saveBiamtImate(Bitmap bitmap1){
Date localDate=new Date();
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AthenaImage";
File file=new File(path);
if (!file.exists()){
file.mkdirs();
}
//String fileUrl = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"AthenaImage"+ "/save.jpg";
String fileUrl ="save.png";

try {
FileOutputStream fos = new FileOutputStream(new File(file,fileUrl));
bitmap1.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
Log.i("TAG", "2成功!" + fileUrl);
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

/**
* 刷新画布
*/
public void RefreshCanvas(){
//Log.i("线程", "初始化数据并且 刷新画布");
if (lists!=null&&lists.size()>0) {
lists.remove(lists);
if (mBitmap!=null) {
mBitmap=null;
}
path=null;
//			inter(dm.widthPixels,dm.heightPixels);
inter(dm.widthPixels,dm.heightPixels);

//Log.i("线程", "初始化数据成功");
invalidate();
}
if (task!=null) {
task.cancel();
}
}
}
3.布局文件引用:

<FrameLayout
android:layout_below="@+id/tv2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/finger_layout"
android:background="@drawable/tv_border_thin"
android:layout_margin="@dimen/common_sw320dp_of_10"
>
<com.canvas.ImageEditTextView
android:id="@+id/main_image_edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="top|left"
android:paddingBottom="3dip"
android:paddingTop="3dip"
android:textSize="50dip" >
</com.canvas.ImageEditTextView>

<com.canvas.HandTouchView
android:id="@+id/hand_touch"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/transparent">
</com.canvas.HandTouchView>
</FrameLayout>
4.Activity:
private void initView() {

Display display = this.getWindowManager().getDefaultDisplay();
mWidth = display.getWidth();
mHeight = display.getHeight();

touchView=(HandTouchView) include2.findViewById(R.id.hand_touch);

imageEditTextView = (ImageEditTextView)include2.findViewById(R.id.main_image_edit);

}
public int mWidth,mHeight;
public HandTouchView touchView;
private Bitmap tempBitmap;
/**
* 图片处理方法
*/
Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Bundle bundle = new Bundle();
bundle = msg.getData();
tempBitmap = bundle.getParcelable("bitmap");			//获取图片
if (null!=tempBitmap) {

isGetBitmap=1;//0:未签字;1:已签字
Log.i("线程", "前台取到VIEW的值");
int w  = tempBitmap.getWidth();							//获取图片的宽度如果大就缩小如果小就不变
int h = tempBitmap.getHeight();
//取到当前的行高和行宽
int lineHeight =  (int) (mHeight/6f);
int lineWidth = (int) (mWidth/4f);
if(mHeight == 1280 && mWidth == 800){
lineHeight =  (int) (mHeight/5.4f);
lineWidth = (int) (mWidth/4f);
}
tempBitmap =BitmapAmplification(tempBitmap);
editInsertBitmap(tempBitmap);				//显示在EditText上
try {
EditTextSaveImage();
tv_submit_c.setEnabled(true);
Log.i("TAG","①图片已保存本地");

/*if (tv_submit_c.getText().toString().equals("保存")){
tv_submit_c.setEnabled(true);
Log.i("TAG","①图片已保存本地");
}*/

} catch (IOException e) {
e.printStackTrace();
}
}else {
if (dialog.isShowing()){
dialog.dismiss();
}
Toast.makeText(SettleAccountActivity.this,"提交前请先签字",Toast.LENGTH_SHORT).show();
}
break;
default:
isGetBitmap= msg.arg1;//0:未签字;1:已签字

break;
}

super.handleMessage(msg);
}

};
/**
* 将bitmap添加到自定义edittext中
* @param bitmap
*/
public void editInsertBitmap(Bitmap bitmap) {
SpannableString ss = new SpannableString("1");
ImageSpan span = new ImageSpan(bitmap, ImageSpan.ALIGN_BOTTOM);
ss.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
imageEditTextView.append(ss);
imageEditTextView.setPadding(0, 0, 0, 10);

}
/**
* 删除方法
*/
public void editImageDelete(){
Editable editable = imageEditTextView.getText();
int end = imageEditTextView.getSelectionEnd();		//删除最后的一个
if (end==1) {
imageEditTextView.setText("");
return;
}
if (end<=0) {
imageEditTextView.setText("");
return;
}
CharSequence sequence = editable.subSequence(0, end-1);
imageEditTextView.setText(sequence);
imageEditTextView.setSelection(end - 1);
}

Bitmap bp;
public Bitmap BitmapAmplification(Bitmap path) {
if (path!=null) {
if(bp!=null){
bp=null;
}
int w = path.getWidth();	//得到图片的宽度
int h = path.getHeight();//得到图片的高度
Log.v("nnn", "宽"+w+"高"+h);
float ww = ((float) 62) / w;
float hh = ((float) 45) / h;
Matrix matrix = new Matrix();
matrix.postScale(ww, hh);
Log.v("nnn", "可以www");
bp = Bitmap.createBitmap(path, 0, 0, w, h, matrix, true);
if (tempBitmap!=null ) {
tempBitmap=null;
}
return bp;
}
return null;
}
//private Bitmap savebitmap;

public void EditTextSaveImage() throws IOException {

//取本地图片
String fileUrl = Environment.getExternalStorageDirectory().getAbsoluteFile()+File.separator+"AthenaImage"+File.separator+"save.png";
//String fileUrl=Environment.getExternalStorageDirectory().getAbsoluteFile()+File.separator+"iv.jpg";
Log.i("TAG", "②取到本地图片地址:fileUrl:" + fileUrl);

if (!StringUtils.isEmpty(fileUrl)&&!hasSaved) {
saveUPYun(fileUrl);
}

}
</pre><pre name="code" class="java">
好了,写到这里,其实你的本地就已经存好了图片,剩下来的步骤就很简单啦
注意保存的图片格式是PNG,千万一定要用PNG,不要用JPG啊,因为JPG保存的图片背景是黑色的,有好长一段时间我都掉进了这个坑!具体什么原因,我也不清楚,欢迎交流学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  canvas 绘图