204 lines
6.3 KiB
Java
204 lines
6.3 KiB
Java
package com.soundcloud.android.crop;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Rect;
|
|
import android.util.AttributeSet;
|
|
import android.view.MotionEvent;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
public class CropImageView extends ImageViewTouchBase {
|
|
|
|
ArrayList<HighlightView> mHighlightViews = new ArrayList<HighlightView>();
|
|
HighlightView mMotionHighlightView;
|
|
float mLastX, mLastY;
|
|
int mMotionEdge;
|
|
|
|
Context mContext;
|
|
|
|
@SuppressWarnings("UnusedDeclaration")
|
|
public CropImageView(Context context) {
|
|
super(context);
|
|
}
|
|
|
|
@SuppressWarnings("UnusedDeclaration")
|
|
public CropImageView(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
@SuppressWarnings("UnusedDeclaration")
|
|
public CropImageView(Context context, AttributeSet attrs, int defStyle) {
|
|
super(context, attrs, defStyle);
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
super.onLayout(changed, left, top, right, bottom);
|
|
if (mBitmapDisplayed.getBitmap() != null) {
|
|
for (HighlightView hv : mHighlightViews) {
|
|
|
|
hv.mMatrix.set(getUnrotatedMatrix());
|
|
hv.invalidate();
|
|
if (hv.hasFocus()) {
|
|
centerBasedOnHighlightView(hv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void zoomTo(float scale, float centerX, float centerY) {
|
|
super.zoomTo(scale, centerX, centerY);
|
|
for (HighlightView hv : mHighlightViews) {
|
|
hv.mMatrix.set(getUnrotatedMatrix());
|
|
hv.invalidate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void zoomIn() {
|
|
super.zoomIn();
|
|
for (HighlightView hv : mHighlightViews) {
|
|
hv.mMatrix.set(getUnrotatedMatrix());
|
|
hv.invalidate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void zoomOut() {
|
|
super.zoomOut();
|
|
for (HighlightView hv : mHighlightViews) {
|
|
hv.mMatrix.set(getUnrotatedMatrix());
|
|
hv.invalidate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void postTranslate(float deltaX, float deltaY) {
|
|
super.postTranslate(deltaX, deltaY);
|
|
for (HighlightView hv : mHighlightViews) {
|
|
hv.mMatrix.postTranslate(deltaX, deltaY);
|
|
hv.invalidate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
CropImageActivity cropImageActivity = (CropImageActivity) mContext;
|
|
if (cropImageActivity.isSaving()) {
|
|
return false;
|
|
}
|
|
|
|
switch (event.getAction()) {
|
|
case MotionEvent.ACTION_DOWN:
|
|
for (HighlightView hv : mHighlightViews) {
|
|
int edge = hv.getHit(event.getX(), event.getY());
|
|
if (edge != HighlightView.GROW_NONE) {
|
|
mMotionEdge = edge;
|
|
mMotionHighlightView = hv;
|
|
mLastX = event.getX();
|
|
mLastY = event.getY();
|
|
mMotionHighlightView
|
|
.setMode((edge == HighlightView.MOVE) ? HighlightView.ModifyMode.Move
|
|
: HighlightView.ModifyMode.Grow);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case MotionEvent.ACTION_UP:
|
|
if (mMotionHighlightView != null) {
|
|
centerBasedOnHighlightView(mMotionHighlightView);
|
|
mMotionHighlightView.setMode(HighlightView.ModifyMode.None);
|
|
}
|
|
mMotionHighlightView = null;
|
|
break;
|
|
case MotionEvent.ACTION_MOVE:
|
|
if (mMotionHighlightView != null) {
|
|
mMotionHighlightView.handleMotion(mMotionEdge, event.getX()
|
|
- mLastX, event.getY() - mLastY);
|
|
mLastX = event.getX();
|
|
mLastY = event.getY();
|
|
ensureVisible(mMotionHighlightView);
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch (event.getAction()) {
|
|
case MotionEvent.ACTION_UP:
|
|
center(true, true);
|
|
break;
|
|
case MotionEvent.ACTION_MOVE:
|
|
// if we're not zoomed then there's no point in even allowing
|
|
// the user to move the image around. This call to center puts
|
|
// it back to the normalized location (with false meaning don't
|
|
// animate).
|
|
if (getScale() == 1F) {
|
|
center(true, true);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Pan the displayed image to make sure the cropping rectangle is visible.
|
|
private void ensureVisible(HighlightView hv) {
|
|
Rect r = hv.mDrawRect;
|
|
|
|
int panDeltaX1 = Math.max(0, getLeft() - r.left);
|
|
int panDeltaX2 = Math.min(0, getRight() - r.right);
|
|
|
|
int panDeltaY1 = Math.max(0, getTop() - r.top);
|
|
int panDeltaY2 = Math.min(0, getBottom() - r.bottom);
|
|
|
|
int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
|
|
int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;
|
|
|
|
if (panDeltaX != 0 || panDeltaY != 0) {
|
|
panBy(panDeltaX, panDeltaY);
|
|
}
|
|
}
|
|
|
|
// If the cropping rectangle's size changed significantly, change the
|
|
// view's center and scale according to the cropping rectangle.
|
|
private void centerBasedOnHighlightView(HighlightView hv) {
|
|
Rect drawRect = hv.mDrawRect;
|
|
|
|
float width = drawRect.width();
|
|
float height = drawRect.height();
|
|
|
|
float thisWidth = getWidth();
|
|
float thisHeight = getHeight();
|
|
|
|
float z1 = thisWidth / width * .6F;
|
|
float z2 = thisHeight / height * .6F;
|
|
|
|
float zoom = Math.min(z1, z2);
|
|
zoom = zoom * this.getScale();
|
|
zoom = Math.max(1F, zoom);
|
|
|
|
if ((Math.abs(zoom - getScale()) / zoom) > .1) {
|
|
float[] coordinates = new float[] { hv.mCropRect.centerX(),
|
|
hv.mCropRect.centerY() };
|
|
getUnrotatedMatrix().mapPoints(coordinates);
|
|
zoomTo(zoom, coordinates[0], coordinates[1], 300F);
|
|
}
|
|
|
|
ensureVisible(hv);
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
super.onDraw(canvas);
|
|
for (HighlightView mHighlightView : mHighlightViews) {
|
|
mHighlightView.draw(canvas);
|
|
}
|
|
}
|
|
|
|
public void add(HighlightView hv) {
|
|
mHighlightViews.add(hv);
|
|
invalidate();
|
|
}
|
|
}
|