Untitled
unknown
plain_text
a year ago
20 kB
3
Indexable
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.DashPathEffect; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import androidx.annotation.Dimension; import androidx.appcompat.widget.AppCompatImageView; import androidx.core.content.ContextCompat; import androidx.core.view.MotionEventCompat; import com.happydev.wordoffice.R; public class StickerView extends AppCompatImageView { private static final String TAG = "StickerView"; private static long STICKER_ID = 0; private long stickerId = 0; private Bitmap deleteBitmap; private Bitmap flipVBitmap; private Bitmap topBitmap; private Bitmap resizeBitmap; private Bitmap mBitmap; private Rect dst_delete; private Rect dst_resize; private Rect dst_flipV; private Rect dst_top; private int deleteBitmapWidth; private int deleteBitmapHeight; private int resizeBitmapWidth; private int resizeBitmapHeight; private int flipVBitmapWidth; private int flipVBitmapHeight; private int topBitmapWidth, topBitmapHeight; private Paint localPaint; private int mScreenWidth, mScreenHeight; private PointF mid = new PointF(); private OperationListener operationListener; private float lastRotateDegree; private boolean isPointerDown = false; private float lastLength; private boolean isInResize = false; private Matrix matrix = new Matrix(); private boolean isInSide; private float lastX, lastY; private boolean isInEdit = true; private float MIN_SCALE = 0.5f; private float MAX_SCALE = 1.2f; private double halfDiagonalLength; private float originWidth = 0; private float oldDis; private DisplayMetrics dm; private boolean isHorizonMirror = false; private boolean touchEnable = true; public StickerView(Context context, AttributeSet attrs) { super(context, attrs); STICKER_ID++; init(); } public StickerView(Context context) { super(context); STICKER_ID++; init(); } public StickerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); STICKER_ID++; init(); } private void init() { stickerId = STICKER_ID; dst_delete = new Rect(); dst_resize = new Rect(); dst_flipV = new Rect(); dst_top = new Rect(); localPaint = new Paint(); localPaint.setColor(ContextCompat.getColor(this.getContext(), R.color.blue)); localPaint.setAntiAlias(true); localPaint.setDither(true); localPaint.setStyle(Paint.Style.STROKE); localPaint.setStrokeJoin(Paint.Join.ROUND); localPaint.setPathEffect(new DashPathEffect(new float[]{30f, 15f}, 0f)); localPaint.setStrokeWidth(6f); dm = getResources().getDisplayMetrics(); mScreenWidth = dm.widthPixels; mScreenHeight = dm.heightPixels; } @Override protected void onDraw(Canvas canvas) { if (mBitmap != null) { float[] arrayOfFloat = new float[9]; matrix.getValues(arrayOfFloat); float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2]; float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5]; float f3 = arrayOfFloat[0] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[1] + arrayOfFloat[2]; float f4 = arrayOfFloat[3] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[4] + arrayOfFloat[5]; float f5 = 0.0F * arrayOfFloat[0] + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2]; float f6 = 0.0F * arrayOfFloat[3] + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5]; float f7 = arrayOfFloat[0] * this.mBitmap.getWidth() + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2]; float f8 = arrayOfFloat[3] * this.mBitmap.getWidth() + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5]; canvas.save(); canvas.drawBitmap(mBitmap, matrix, null); dst_delete.left = (int) (f1 - deleteBitmapWidth / 2); dst_delete.right = (int) (f1 + deleteBitmapWidth / 2); dst_delete.top = (int) (f2 - deleteBitmapHeight / 2); dst_delete.bottom = (int) (f2 + deleteBitmapHeight / 2); dst_resize.left = (int) (f7 - resizeBitmapWidth / 2); dst_resize.right = (int) (f7 + resizeBitmapWidth / 2); dst_resize.top = (int) (f8 - resizeBitmapHeight / 2); dst_resize.bottom = (int) (f8 + resizeBitmapHeight / 2); dst_top.left = (int) (f5 - flipVBitmapWidth / 2); dst_top.right = (int) (f5 + flipVBitmapWidth / 2); dst_top.top = (int) (f6 - flipVBitmapHeight / 2); dst_top.bottom = (int) (f6 + flipVBitmapHeight / 2); dst_flipV.left = (int) (f3 - flipVBitmapWidth / 2); dst_flipV.right = (int) (f3 + flipVBitmapWidth / 2); dst_flipV.top = (int) (f4 - flipVBitmapHeight / 2); dst_flipV.bottom = (int) (f4 + flipVBitmapHeight / 2); if (isInEdit) { canvas.drawLine(f1, f2, f3, f4, localPaint); canvas.drawLine(f3, f4, f7, f8, localPaint); canvas.drawLine(f5, f6, f7, f8, localPaint); canvas.drawLine(f5, f6, f1, f2, localPaint); canvas.drawBitmap(deleteBitmap, null, dst_delete, null); canvas.drawBitmap(resizeBitmap, null, dst_resize, null); canvas.drawBitmap(flipVBitmap, null, dst_flipV, null); canvas.drawBitmap(topBitmap, null, dst_top, null); } canvas.restore(); } } @Override public void setImageResource(int resId) { setBitmap(BitmapFactory.decodeResource(getResources(), resId)); } public void setBitmap(Bitmap bitmap) { matrix.reset(); mBitmap = bitmap; setDiagonalLength(); initBitmaps(); int w = mBitmap.getWidth(); int h = mBitmap.getHeight(); originWidth = w; float initScale = (MIN_SCALE + MAX_SCALE) / 2; matrix.postScale(initScale, initScale, w / 2f, h / 2f); matrix.postTranslate((mScreenWidth - w) / 2f, (mScreenWidth - h) / 2f); invalidate(); } private void setDiagonalLength() { halfDiagonalLength = Math.hypot(mBitmap.getWidth(), mBitmap.getHeight()) / 2; } private void initBitmaps() { if (mBitmap.getWidth() >= mBitmap.getHeight()) { float minWidth = mScreenWidth / 8f; if (mBitmap.getWidth() < minWidth) { MIN_SCALE = 1f; } else { MIN_SCALE = minWidth / mBitmap.getWidth(); } if (mBitmap.getWidth() > mScreenWidth) { MAX_SCALE = 1; } else { MAX_SCALE = 1.0f * mScreenWidth / mBitmap.getWidth(); } } else { float minHeight = mScreenWidth / 8f; if (mBitmap.getHeight() < minHeight) { MIN_SCALE = 1f; } else { MIN_SCALE = minHeight / mBitmap.getHeight(); } if (mBitmap.getHeight() > mScreenWidth) { MAX_SCALE = 1; } else { MAX_SCALE = 1.0f * mScreenWidth / mBitmap.getHeight(); } } topBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nothing); deleteBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sign_delete); flipVBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sign_rotate); resizeBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sign_resize); deleteBitmapWidth = dpToPx(getContext(), 48); deleteBitmapHeight = dpToPx(getContext(), 48); resizeBitmapWidth = dpToPx(getContext(), 48); resizeBitmapHeight = dpToPx(getContext(), 48); flipVBitmapWidth = dpToPx(getContext(), 48); flipVBitmapHeight = dpToPx(getContext(), 48); topBitmapWidth = dpToPx(getContext(), 0); topBitmapHeight = dpToPx(getContext(), 0); } public static int dpToPx(Context var0, @Dimension(unit = 0) int var1) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) var1, var0.getResources().getDisplayMetrics()); } @Override public boolean onTouchEvent(MotionEvent event) { if (!touchEnable) { return false; } int action = MotionEventCompat.getActionMasked(event); boolean handled = true; float pointerLimitDis = 20f; switch (action) { case MotionEvent.ACTION_DOWN: if (isInButton(event, dst_delete)) { if (operationListener != null) { operationListener.onDeleteClick(); } } else if (isInResize(event)) { isInResize = true; lastRotateDegree = rotationToStartPoint(event); midPointToStartPoint(event); lastLength = diagonalLength(event); } else if (isInButton(event, dst_flipV)) { PointF localPointF = new PointF(); midDiagonalPoint(localPointF); matrix.postScale(-1.0F, 1.0F, localPointF.x, localPointF.y); isHorizonMirror = !isHorizonMirror; invalidate(); } else if (isInButton(event, dst_top)) { bringToFront(); if (operationListener != null) { operationListener.onTop(this); } } else if (isInBitmap(event)) { isInSide = true; lastX = event.getX(0); lastY = event.getY(0); } else { handled = false; } break; case MotionEvent.ACTION_POINTER_DOWN: if (spacing(event) > pointerLimitDis) { oldDis = spacing(event); isPointerDown = true; midPointToStartPoint(event); } else { isPointerDown = false; } isInSide = false; isInResize = false; break; case MotionEvent.ACTION_MOVE: if (isPointerDown) { float scale; float disNew = spacing(event); if (disNew < pointerLimitDis) { scale = 1; } else { scale = disNew / oldDis; float pointerZoomCoEff = 0.09f; scale = (scale - 1) * pointerZoomCoEff + 1; } float scaleTemp = (scale * Math.abs(dst_flipV.left - dst_resize.left)) / originWidth; if (((scaleTemp <= MIN_SCALE)) && scale < 1 || (scaleTemp >= MAX_SCALE) && scale > 1) { scale = 1; } else { lastLength = diagonalLength(event); } matrix.postScale(scale, scale, mid.x, mid.y); invalidate(); } else if (isInResize) { matrix.postRotate((rotationToStartPoint(event) - lastRotateDegree) * 2, mid.x, mid.y); lastRotateDegree = rotationToStartPoint(event); float scale = diagonalLength(event) / lastLength; if (((diagonalLength(event) / halfDiagonalLength <= MIN_SCALE)) && scale < 1 || (diagonalLength(event) / halfDiagonalLength >= MAX_SCALE) && scale > 1) { scale = 1; if (!isInResize(event)) { isInResize = false; } } else { lastLength = diagonalLength(event); } matrix.postScale(scale, scale, mid.x, mid.y); invalidate(); } else if (isInSide) { float x = event.getX(0); float y = event.getY(0); matrix.postTranslate(x - lastX, y - lastY); lastX = x; lastY = y; invalidate(); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: isInResize = false; isInSide = false; isPointerDown = false; break; } if (handled && operationListener != null) { operationListener.onEdit(this); } return handled; } private boolean isInBitmap(MotionEvent event) { float[] arrayOfFloat1 = new float[9]; this.matrix.getValues(arrayOfFloat1); float f1 = 0.0F * arrayOfFloat1[0] + 0.0F * arrayOfFloat1[1] + arrayOfFloat1[2]; float f2 = 0.0F * arrayOfFloat1[3] + 0.0F * arrayOfFloat1[4] + arrayOfFloat1[5]; float f3 = arrayOfFloat1[0] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat1[1] + arrayOfFloat1[2]; float f4 = arrayOfFloat1[3] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat1[4] + arrayOfFloat1[5]; float f5 = 0.0F * arrayOfFloat1[0] + arrayOfFloat1[1] * this.mBitmap.getHeight() + arrayOfFloat1[2]; float f6 = 0.0F * arrayOfFloat1[3] + arrayOfFloat1[4] * this.mBitmap.getHeight() + arrayOfFloat1[5]; float f7 = arrayOfFloat1[0] * this.mBitmap.getWidth() + arrayOfFloat1[1] * this.mBitmap.getHeight() + arrayOfFloat1[2]; float f8 = arrayOfFloat1[3] * this.mBitmap.getWidth() + arrayOfFloat1[4] * this.mBitmap.getHeight() + arrayOfFloat1[5]; float[] arrayOfFloat2 = new float[4]; float[] arrayOfFloat3 = new float[4]; arrayOfFloat2[0] = f1; arrayOfFloat2[1] = f3; arrayOfFloat2[2] = f7; arrayOfFloat2[3] = f5; arrayOfFloat3[0] = f2; arrayOfFloat3[1] = f4; arrayOfFloat3[2] = f8; arrayOfFloat3[3] = f6; return pointInRect(arrayOfFloat2, arrayOfFloat3, event.getX(0), event.getY(0)); } private boolean pointInRect(float[] xRange, float[] yRange, float x, float y) { double a1 = Math.hypot(xRange[0] - xRange[1], yRange[0] - yRange[1]); double a2 = Math.hypot(xRange[1] - xRange[2], yRange[1] - yRange[2]); double a3 = Math.hypot(xRange[3] - xRange[2], yRange[3] - yRange[2]); double a4 = Math.hypot(xRange[0] - xRange[3], yRange[0] - yRange[3]); double b1 = Math.hypot(x - xRange[0], y - yRange[0]); double b2 = Math.hypot(x - xRange[1], y - yRange[1]); double b3 = Math.hypot(x - xRange[2], y - yRange[2]); double b4 = Math.hypot(x - xRange[3], y - yRange[3]); double u1 = (a1 + b1 + b2) / 2; double u2 = (a2 + b2 + b3) / 2; double u3 = (a3 + b3 + b4) / 2; double u4 = (a4 + b4 + b1) / 2; double s = a1 * a2; double ss = Math.sqrt(u1 * (u1 - a1) * (u1 - b1) * (u1 - b2)) + Math.sqrt(u2 * (u2 - a2) * (u2 - b2) * (u2 - b3)) + Math.sqrt(u3 * (u3 - a3) * (u3 - b3) * (u3 - b4)) + Math.sqrt(u4 * (u4 - a4) * (u4 - b4) * (u4 - b1)); return Math.abs(s - ss) < 0.5; } private boolean isInButton(MotionEvent event, Rect rect) { int left = rect.left; int right = rect.right; int top = rect.top; int bottom = rect.bottom; return event.getX(0) >= left && event.getX(0) <= right && event.getY(0) >= top && event.getY(0) <= bottom; } private boolean isInResize(MotionEvent event) { int left = -20 + this.dst_resize.left; int top = -20 + this.dst_resize.top; int right = 20 + this.dst_resize.right; int bottom = 20 + this.dst_resize.bottom; return event.getX(0) >= left && event.getX(0) <= right && event.getY(0) >= top && event.getY(0) <= bottom; } private void midPointToStartPoint(MotionEvent event) { float[] arrayOfFloat = new float[9]; matrix.getValues(arrayOfFloat); float f1 = 0.0f * arrayOfFloat[0] + 0.0f * arrayOfFloat[1] + arrayOfFloat[2]; float f2 = 0.0f * arrayOfFloat[3] + 0.0f * arrayOfFloat[4] + arrayOfFloat[5]; float f3 = f1 + event.getX(0); float f4 = f2 + event.getY(0); mid.set(f3 / 2, f4 / 2); } private void midDiagonalPoint(PointF paramPointF) { float[] arrayOfFloat = new float[9]; this.matrix.getValues(arrayOfFloat); float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2]; float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5]; float f3 = arrayOfFloat[0] * this.mBitmap.getWidth() + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2]; float f4 = arrayOfFloat[3] * this.mBitmap.getWidth() + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5]; float f5 = f1 + f3; float f6 = f2 + f4; paramPointF.set(f5 / 2.0F, f6 / 2.0F); } private float rotationToStartPoint(MotionEvent event) { float[] arrayOfFloat = new float[9]; matrix.getValues(arrayOfFloat); float x = 0.0f * arrayOfFloat[0] + 0.0f * arrayOfFloat[1] + arrayOfFloat[2]; float y = 0.0f * arrayOfFloat[3] + 0.0f * arrayOfFloat[4] + arrayOfFloat[5]; double arc = Math.atan2(event.getY(0) - y, event.getX(0) - x); return (float) Math.toDegrees(arc); } private float diagonalLength(MotionEvent event) { return (float) Math.hypot(event.getX(0) - mid.x, event.getY(0) - mid.y); } private float spacing(MotionEvent event) { if (event.getPointerCount() == 2) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } else { return 0; } } public long getStickerId() { return stickerId; } public interface OperationListener { void onDeleteClick(); void onEdit(StickerView stickerView); void onTop(StickerView stickerView); } public void setOperationListener(OperationListener operationListener) { this.operationListener = operationListener; } public boolean getIsInEdit() { return this.isInEdit; } public void setInEdit(boolean isInEdit) { this.isInEdit = isInEdit; touchEnable = isInEdit; invalidate(); } public Bitmap getResizeBitmap() { return Bitmap.createBitmap( this.mBitmap, 0, 0, this.mBitmap.getWidth(), this.mBitmap.getHeight(), matrix, true ); } public PointF getLastPos() { float[] arrayOfFloat = new float[9]; matrix.getValues(arrayOfFloat); float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2]; float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5]; return new PointF(f1, f2); } }
Editor is loading...
Leave a Comment