涂鸦,Canvas绘图
2016-03-16 10:42
441 查看
公司的项目里有一个功能是,用户有个涂鸦签字的功能,需要再白色面板上涂鸦,然后上传到又拍云,把又拍云返回的图片url通过post请求上传到服务器。摸索了一段时间,完成了这个功能,并且实现的不错。下面贴出截图跟部分demo:
上传到又拍云的那部分demo就不贴了,涉及到很多图片url定义规则还有项目隐私的东西,只贴到 保存图片到本地的,后面上传图片就是很简单啦!
1.自定义的ImageTextView.class
上传到又拍云的那部分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 在高清屏下绘制图片变模糊的解决方法
- VB实现鼠标绘图实例代码
- Windows窗体的.Net框架绘图技术实现方法
- 使用canvas实现仿新浪微博头像截取上传功能
- js+HTML5实现canvas多种颜色渐变效果的方法
- javascript+HTML5的Canvas实现Lab单车动画效果
- js+canvas绘制矩形的方法
- JavaScript+html5 canvas制作的百花齐放效果完整实例
- jQuery+canvas实现的球体平抛及颜色动态变换效果
- php绘图中显示不出图片的原因及解决
- html5 canvas js(数字时钟)实例代码
- JavaScript+canvas实现七色板效果实例
- javascript+canvas制作九宫格小程序
- 通过javascript把图片转化为字符画
- php绘图之生成饼状图的方法
- php绘图之加载外部图片的方法
- php绘图之在图片上写中文和英文的方法
- js+html5通过canvas指定开始和结束点绘制线条的方法
- JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例