package com.js.photosdk.operate; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.view.MotionEvent; import android.view.View; public class OperateView extends View { private List<ImageObject> imgLists = new ArrayList<ImageObject>(); private Rect mCanvasLimits; private Bitmap bgBmp; private Paint paint = new Paint(); // private Context mContext; private boolean isMultiAdd;// true 代表可以添加多个水印图片(或文字),false 代表只可添加单个水印图片(或文字) private float picScale = 0.4f; /** * 设置水印图片初始化大小 * @param picScale */ public void setPicScale(float picScale) { this.picScale = picScale; } /** * 设置是否可以添加多个图片或者文字对象 * * @param isMultiAdd * true 代表可以添加多个水印图片(或文字),false 代表只可添加单个水印图片(或文字) */ public void setMultiAdd(boolean isMultiAdd) { this.isMultiAdd = isMultiAdd; } public OperateView(Context context, Bitmap resizeBmp) { super(context); // this.mContext = context; bgBmp = resizeBmp; int width = bgBmp.getWidth(); int height = bgBmp.getHeight(); mCanvasLimits = new Rect(0, 0, width, height); } /** * 将图片对象添加到View中 * * @param imgObj * 图片对象 */ public void addItem(ImageObject imgObj) { if (imgObj == null) { return; } if (!isMultiAdd && imgLists != null) { imgLists.clear(); } imgObj.setSelected(true); if (!imgObj.isTextObject) { imgObj.setScale(picScale); } ImageObject tempImgObj = null; for (int i = 0; i < imgLists.size(); i++) { tempImgObj = imgLists.get(i); tempImgObj.setSelected(false); } imgLists.add(imgObj); invalidate(); } /** * 画出容器内所有的图像 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int sc = canvas.save(); canvas.clipRect(mCanvasLimits); canvas.drawBitmap(bgBmp, 0, 0, paint); drawImages(canvas); canvas.restoreToCount(sc); for (ImageObject ad : imgLists) { if (ad != null && ad.isSelected()) { ad.drawIcon(canvas); } } } public void save() { ImageObject io = getSelected(); if (io != null) { io.setSelected(false); } invalidate(); } /** * 根据触控点重绘View */ @Override public boolean onTouchEvent(MotionEvent event) { if (event.getPointerCount() == 1) { handleSingleTouchManipulateEvent(event); } else { handleMultiTouchManipulateEvent(event); } invalidate(); super.onTouchEvent(event); return true; } private boolean mMovedSinceDown = false; private boolean mResizeAndRotateSinceDown = false; private float mStartDistance = 0.0f; private float mStartScale = 0.0f; private float mStartRot = 0.0f; private float mPrevRot = 0.0f; static public final double ROTATION_STEP = 2.0; static public final double ZOOM_STEP = 0.01; static public final float CANVAS_SCALE_MIN = 0.25f; static public final float CANVAS_SCALE_MAX = 3.0f; private Point mPreviousPos = new Point(0, 0); // single touch events float diff; float rot; /** * 多点触控操作 * * @param event */ private void handleMultiTouchManipulateEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_POINTER_UP : break; case MotionEvent.ACTION_POINTER_DOWN : float x1 = event.getX(0); float x2 = event.getX(1); float y1 = event.getY(0); float y2 = event.getY(1); float delX = (x2 - x1); float delY = (y2 - y1); diff = (float) Math.sqrt((delX * delX + delY * delY)); mStartDistance = diff; // float q = (delX / delY); mPrevRot = (float) Math.toDegrees(Math.atan2(delX, delY)); for (ImageObject io : imgLists) { if (io.isSelected()) { mStartScale = io.getScale(); mStartRot = io.getRotation(); break; } } break; case MotionEvent.ACTION_MOVE : x1 = event.getX(0); x2 = event.getX(1); y1 = event.getY(0); y2 = event.getY(1); delX = (x2 - x1); delY = (y2 - y1); diff = (float) Math.sqrt((delX * delX + delY * delY)); float scale = diff / mStartDistance; float newscale = mStartScale * scale; rot = (float) Math.toDegrees(Math.atan2(delX, delY)); float rotdiff = mPrevRot - rot; for (ImageObject io : imgLists) { if (io.isSelected() && newscale < 10.0f && newscale > 0.1f) { float newrot = Math.round((mStartRot + rotdiff) / 1.0f); if (Math.abs((newscale - io.getScale()) * ROTATION_STEP) > Math .abs(newrot - io.getRotation())) { io.setScale(newscale); } else { io.setRotation(newrot % 360); } break; } } break; } } /** * 获取选中的对象ImageObject * * @return */ private ImageObject getSelected() { for (ImageObject ibj : imgLists) { if (ibj.isSelected()) { return ibj; } } return null; } private long selectTime = 0; /** * 单点触控操作 * * @param event */ private void handleSingleTouchManipulateEvent(MotionEvent event) { long currentTime = 0; switch (event.getAction()) { case MotionEvent.ACTION_DOWN : mMovedSinceDown = false; mResizeAndRotateSinceDown = false; int selectedId = -1; for (int i = imgLists.size() - 1; i >= 0; --i) { ImageObject io = imgLists.get(i); if (io.contains(event.getX(), event.getY()) || io.pointOnCorner(event.getX(), event.getY(), OperateConstants.RIGHTBOTTOM) || io.pointOnCorner(event.getX(), event.getY(), OperateConstants.LEFTTOP)) { io.setSelected(true); imgLists.remove(i); imgLists.add(io); selectedId = imgLists.size() - 1; currentTime = System.currentTimeMillis(); if (currentTime - selectTime < 300) { if (myListener != null) { if (getSelected().isTextObject()) { myListener .onClick((TextObject) getSelected()); } } } selectTime = currentTime; break; } } if (selectedId < 0) { for (int i = imgLists.size() - 1; i >= 0; --i) { ImageObject io = imgLists.get(i); if (io.contains(event.getX(), event.getY()) || io.pointOnCorner(event.getX(), event.getY(), OperateConstants.RIGHTBOTTOM) || io.pointOnCorner(event.getX(), event.getY(), OperateConstants.LEFTTOP)) { io.setSelected(true); imgLists.remove(i); imgLists.add(io); selectedId = imgLists.size() - 1; break; } } } for (int i = 0; i < imgLists.size(); ++i) { ImageObject io = imgLists.get(i); if (i != selectedId) { io.setSelected(false); } } ImageObject io = getSelected(); if (io != null) { if (io.pointOnCorner(event.getX(), event.getY(), OperateConstants.LEFTTOP)) { imgLists.remove(io); } else if (io.pointOnCorner(event.getX(), event.getY(), OperateConstants.RIGHTBOTTOM)) { mResizeAndRotateSinceDown = true; float x = event.getX(); float y = event.getY(); float delX = x - io.getPoint().x; float delY = y - io.getPoint().y; diff = (float) Math.sqrt((delX * delX + delY * delY)); mStartDistance = diff; mPrevRot = (float) Math.toDegrees(Math .atan2(delX, delY)); mStartScale = io.getScale(); mStartRot = io.getRotation(); } else if (io.contains(event.getX(), event.getY())) { mMovedSinceDown = true; mPreviousPos.x = (int) event.getX(); mPreviousPos.y = (int) event.getY(); } } break; case MotionEvent.ACTION_UP : mMovedSinceDown = false; mResizeAndRotateSinceDown = false; break; case MotionEvent.ACTION_MOVE : // Log.i("jarlen"," 移动了"); // 移动 if (mMovedSinceDown) { int curX = (int) event.getX(); int curY = (int) event.getY(); int diffX = curX - mPreviousPos.x; int diffY = curY - mPreviousPos.y; mPreviousPos.x = curX; mPreviousPos.y = curY; io = getSelected(); Point p = io.getPosition(); int x = p.x + diffX; int y = p.y + diffY; if (p.x + diffX >= mCanvasLimits.left && p.x + diffX <= mCanvasLimits.right && p.y + diffY >= mCanvasLimits.top && p.y + diffY <= mCanvasLimits.bottom) io.moveBy((int) (diffX), (int) (diffY)); } // 旋转和缩放 if (mResizeAndRotateSinceDown) { io = getSelected(); float x = event.getX(); float y = event.getY(); float delX = x - io.getPoint().x; float delY = y - io.getPoint().y; diff = (float) Math.sqrt((delX * delX + delY * delY)); float scale = diff / mStartDistance; float newscale = mStartScale * scale; rot = (float) Math.toDegrees(Math.atan2(delX, delY)); float rotdiff = mPrevRot - rot; if (newscale < 10.0f && newscale > 0.1f) { float newrot = Math.round((mStartRot + rotdiff) / 1.0f); if (Math.abs((newscale - io.getScale()) * ROTATION_STEP) > Math .abs(newrot - io.getRotation())) { io.setScale(newscale); } else { io.setRotation(newrot % 360); } } } break; } cancelLongPress(); } /** * 循环画图像 * * @param canvas */ private void drawImages(Canvas canvas) { for (ImageObject ad : imgLists) { if (ad != null) { ad.draw(canvas); } } } /** * 向外部提供双击监听事件(双击弹出自定义对话框编辑文字) */ MyListener myListener; public void setOnListener(MyListener myListener) { this.myListener = myListener; } public interface MyListener { public void onClick(TextObject tObject); } }