当拖动右下角区域时执行围绕图像中心旋转,缩放的操作,拖动其他区域执行平移。

采用Matrix变换实现,最后可以保存在文件。

效果如下:



View的代码如下:

package com.hu.imagepro;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.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.PaintFlagsDrawFilter;import android.graphics.PointF;import android.graphics.RectF;import android.os.Environment;import android.view.MotionEvent;import android.view.View;import com.example.imageprocess.R;public class ProcessView extends View{Context context = null;Matrix matrixPaint = null;Bitmap bmpMotion = null;Bitmap bmpRotate = null;Bitmap bmpBack = null;RectF rectMotionPre = null;RectF rectMotion = null;RectF rectRotateMark = null;RectF rectRotatePre = null;RectF rectRotate = null;Paint paint = null;PaintFlagsDrawFilter paintFilter = null;ViewStatus status = ViewStatus.STATUS_MOVE;PointF pointMotionMid = null;PointF prePoint = null;PointF curPoint = null;PointF rotateCenterP = null;String savePath = null;enum ViewStatus{STATUS_ROTATE,STATUS_MOVE,}public ProcessView(Context context) {super(context);// TODO Auto-generated constructor stubthis.context = context;//创建变幻图形用的MatrixmatrixPaint = new Matrix();//创建画笔paint = new Paint();//画笔抗锯齿paint.setAntiAlias(true);paint.setColor(Color.BLUE);//设置画笔绘制空心图形paint.setStyle(Style.STROKE);try {//加载相应的图片资源bmpMotion = BitmapFactory.decodeStream(context.getAssets().open("wenzi_14.png"));bmpBack = BitmapFactory.decodeStream(context.getAssets().open("background.png"));bmpRotate = BitmapFactory.decodeResource(getResources(), R.drawable.btn_rotate_a);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}//记录表情最初的矩形rectMotionPre = new RectF(0, 0, bmpMotion.getWidth(), bmpMotion.getHeight());//记录表情当前的矩形rectMotion = new RectF(rectMotionPre);//标记旋转图标位置的矩形rectRotateMark = new RectF(rectMotion.right - bmpRotate.getWidth() / 2,rectMotion.bottom - bmpRotate.getHeight() / 2,rectMotion.right + bmpRotate.getWidth() / 2,rectMotion.bottom + bmpRotate.getHeight() / 2);//记录旋转图标矩形最初的矩形rectRotatePre = new RectF(rectRotateMark);//记录当前旋转图标位置的矩形rectRotate = new RectF(rectRotateMark);//记录表情矩形的中点pointMotionMid = new PointF(bmpMotion.getWidth() / 2, bmpMotion.getHeight() / 2);//记录上次动作的坐标prePoint = new PointF();//记录当前动作的坐标curPoint = new PointF();//记录旋转图标中点rotateCenterP = new PointF(rectMotion.right, rectMotion.bottom);//画布参数paintFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test123.png";}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubcanvas.setDrawFilter(paintFilter);canvas.drawBitmap(bmpBack, 0, 0, paint);canvas.drawBitmap(bmpMotion, matrixPaint, null);canvas.drawBitmap(bmpRotate, null, rectRotate, null);//canvas.drawRect(rectPaint, paint);//canvas.drawRect(rectRotate, paint);//canvas.drawCircle(picMidPoint.x, picMidPoint.y, 5, paint);super.onDraw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubfloat x = event.getX();float y = event.getY();switch (event.getAction()) {//手指按下的时候case MotionEvent.ACTION_DOWN:prePoint.x = x;prePoint.y = y;//按到了旋转图标上if(isInRect(x, y, rectRotate)){status = ViewStatus.STATUS_ROTATE;}else{status = ViewStatus.STATUS_MOVE;}break;case MotionEvent.ACTION_UP:if(status == ViewStatus.STATUS_ROTATE){saveBitmap();}break;case MotionEvent.ACTION_MOVE:curPoint.x = x;curPoint.y = y;if(status == ViewStatus.STATUS_ROTATE){rectRotateMark.set(x - bmpRotate.getWidth() / 2,y - bmpRotate.getHeight() / 2,x + bmpRotate.getWidth() / 2,y + bmpRotate.getHeight() / 2);//获取旋转的角度float de = getPointsDegree(prePoint, pointMotionMid, curPoint);//获取缩放的比例float re = getPointsDistance(pointMotionMid, curPoint) / getPointsDistance(pointMotionMid, prePoint);if(re > 0.0001){//对Matrix进行缩放matrixPaint.postScale(re, re, pointMotionMid.x, pointMotionMid.y);}if(de > 0.0001 || de < -0.0001){//对Matrix进行旋转matrixPaint.postRotate(de, pointMotionMid.x, pointMotionMid.y);}}else if(status == ViewStatus.STATUS_MOVE){//对Matrix进行移位matrixPaint.postTranslate(x - prePoint.x, y - prePoint.y);}prePoint.x = x;prePoint.y = y;//将矩阵map到表情矩形上matrixPaint.mapRect(rectMotion, rectMotionPre);matrixPaint.mapRect(rectRotateMark, rectRotatePre);getRectCenter(rectRotateMark, rotateCenterP);getRectCenter(rectMotion, pointMotionMid);rectRotate.set(rotateCenterP.x - bmpRotate.getWidth() / 2, rotateCenterP.y - bmpRotate.getHeight() / 2,rotateCenterP.x + bmpRotate.getWidth() / 2, rotateCenterP.y + bmpRotate.getHeight() / 2);postInvalidate();break;default:break;}return true;}/** * 将当前表情合并到背景并保存 */private void saveBitmap() {File f = new File(savePath);//使用背景图的宽高创建一张bitmapBitmap bmpSave = Bitmap.createBitmap(bmpBack.getWidth(), bmpBack.getHeight(), Bitmap.Config.ARGB_8888);//创建canvasCanvas canvas = new Canvas(bmpSave);//将背景图和表情画在bitmap上canvas.drawBitmap(bmpBack, 0, 0, paint);canvas.drawBitmap(bmpMotion, matrixPaint, paint);//保存bitmap//canvas.save(Canvas.ALL_SAVE_FLAG); //canvas.restore(); try{FileOutputStream out = new FileOutputStream(f);bmpSave.compress(Bitmap.CompressFormat.PNG, 100, out);out.flush();out.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}bmpBack.recycle();bmpBack = bmpSave;//重置MatrixmatrixPaint.reset();//充值旋转图标rectRotate.set(rectRotatePre);}//根据矩形获取中心点private void getRectCenter(RectF rect, PointF p){p.x = rect.left + (rect.right - rect.left) / 2;p.y = rect.top + (rect.bottom - rect.top) / 2;}//判断点是否在矩形内private boolean isInRect(float x, float y, RectF rect){boolean ret = false;if(x > rect.left && x < rect.right && y > rect.top && y < rect.bottom){ret = true;}return ret;}//求两点间距离private float getPointsDistance(PointF p1, PointF p2) {float ret = (float) Math.sqrt(Math.abs((p1.x - p2.x) * (p1.x - p2.x)+ (p1.y - p2.y) * (p1.y - p2.y)));return ret;}//求角ABCprivate float getPointsDegree(PointF a, PointF b, PointF c){if(Math.abs(a.x - c.x) < 2 && Math.abs(a.y - c.y) < 2){return 0.0f;}float ret = (float) (  Math.toDegrees(Math.atan2(c.y - b.y, c.x - b.x) - Math.atan2(a.y - b.y, a.x - b.x)));return ret;}}

更多相关文章

  1. 【Frida Hook 学习记录】Frida Hook Android(安卓)常用方法
  2. Android通讯录管理(获取联系人、通话记录、短信消息)(二)
  3. 新浪微博Android客户端学习记录三:完成登录界面和授权界面
  4. 天天记录 - Android抓包 - 抓取HTTP,TCP协议数据
  5. Android——Canvas类的使用
  6. Android(安卓)自定义View -- 圆形进度条,文字旋转
  7. 搭建eclipse android开发环境的一点记录
  8. Android异常记录-HttpClient中文名称乱码
  9. 动画---放缩,旋转,移动,渐变

随机推荐

  1. 第九篇 ANDROID包管理服务机制与架构
  2. Android 4.0 中的Camera
  3. Flutter 的 TensorFlow Lite 插件 - tfli
  4. android多线程编程详解,关于Handler ,Loop
  5. android将线程绑定在指定CPU
  6. 使用Struts2服务端与android交互
  7. Android点击监听事件
  8. android基本的数据库创建和使用
  9. 你知道 Android 的 MessageQueue.IdleHan
  10. Android开发错误Unable to execute dex: