package org.edx.mobile.view.custom;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import org.edx.mobile.R;
import org.edx.mobile.third_party.subscaleview.SubsamplingScaleImageView;
public class CropImageView extends org.edx.mobile.third_party.subscaleview.SubsamplingScaleImageView {
private Paint borderPaint;
private Paint backgroundPaint;
final Path circleSelectionPath = new Path();
final RectF mRectF = new RectF();
private final float cropCirclePadding;
public CropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
cropCirclePadding = getResources().getDimension(R.dimen.crop_circle_padding);
setOrientation(ORIENTATION_USE_EXIF);
setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
borderPaint = new Paint();
borderPaint.setColor(getResources().getColor(R.color.crop_circle_border_color));
borderPaint.setStrokeWidth(getResources().getDimension(R.dimen.crop_circle_border_width));
borderPaint.setStyle(Paint.Style.STROKE);
backgroundPaint = new Paint();
backgroundPaint.setColor(getResources().getColor(R.color.crop_circle_overlay_color));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
final int horizontalPadding = (int) cropCirclePadding;
final int verticalPadding = (getHeight() - (getWidth() - horizontalPadding * 2)) / 2;
setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
setPanLimit(PAN_LIMIT_INSIDE); // This will call `fitToBounds` with the new padding
}
public CropImageView(Context context) {
this(context, null);
}
// Extend fitToBounds function to account for view padding
@Override
protected void fitToBounds(boolean center, ScaleAndTranslate sat) {
if (panLimit == PAN_LIMIT_OUTSIDE && isReady()) {
center = false;
}
PointF vTranslate = sat.vTranslate;
float scale = limitedScale(sat.scale);
float scaleWidth = scale * sWidth();
float scaleHeight = scale * sHeight();
if (panLimit == PAN_LIMIT_CENTER && isReady()) {
vTranslate.x = Math.max(vTranslate.x, getWidth() / 2 - scaleWidth);
vTranslate.y = Math.max(vTranslate.y, getHeight() / 2 - scaleHeight);
} else if (center) {
vTranslate.x = Math.max(vTranslate.x, getWidth() - scaleWidth - getPaddingRight());
vTranslate.y = Math.max(vTranslate.y, getHeight() - scaleHeight - getPaddingBottom());
} else {
vTranslate.x = Math.max(vTranslate.x, -scaleWidth);
vTranslate.y = Math.max(vTranslate.y, -scaleHeight);
}
float maxTx;
float maxTy;
if (panLimit == PAN_LIMIT_CENTER && isReady()) {
maxTx = Math.max(0, getWidth() / 2);
maxTy = Math.max(0, getHeight() / 2);
} else if (center) {
maxTx = Math.max(0, getPaddingLeft());
maxTy = Math.max(0, getPaddingTop());
} else {
maxTx = Math.max(0, getWidth());
maxTy = Math.max(0, getHeight());
}
vTranslate.x = Math.min(vTranslate.x, maxTx);
vTranslate.y = Math.min(vTranslate.y, maxTy);
sat.scale = scale;
}
@NonNull
public Rect getCropRect() {
final PointF topLeft = this.viewToSourceCoord(getPaddingLeft(), getPaddingTop());
final PointF bottomRight = this.viewToSourceCoord(getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
return new Rect((int) topLeft.x, (int) topLeft.y, (int) bottomRight.x, (int) bottomRight.y);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw background with transparent circular hole
final float radius = Math.min((float) canvas.getWidth(), canvas.getHeight()) / 2 - cropCirclePadding;
mRectF.set((float) canvas.getWidth() / 2 - radius, (float) canvas.getHeight() / 2 - radius, (float) canvas.getWidth() / 2 + radius, (float) canvas.getHeight() / 2 + radius);
circleSelectionPath.reset();
circleSelectionPath.addOval(mRectF, Path.Direction.CW);
canvas.clipPath(circleSelectionPath, Region.Op.XOR);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), backgroundPaint);
canvas.restore();
// Draw circle border
canvas.drawCircle((float) canvas.getWidth() / 2, (float) canvas.getHeight() / 2, radius, borderPaint);
}
}