Skip to content

Instantly share code, notes, and snippets.

@tusharbapte
Forked from pookie13/CropImage.Java
Created November 16, 2017 07:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tusharbapte/4232e7ca97e8fbdce5b888b465d059a2 to your computer and use it in GitHub Desktop.
Save tusharbapte/4232e7ca97e8fbdce5b888b465d059a2 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.goparties.gpuser.CropImageActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<com.goparties.gpuser.util.CropImageView
android:id="@+id/cropImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:layout_marginTop="?attr/actionBarSize"
android:background="@color/black_trans"
android:paddingBottom="2dp"
android:paddingTop="2dp"
app:cropMode="circle"
app:frameColor="@color/colorPrimaryDark"
app:frameStrokeWeight="1dp"
app:guideColor="@color/orange"
app:guideShowMode="show_on_touch"
app:guideStrokeWeight="1dp"
app:handleColor="@color/orange"
app:handleShowMode="show_always"
app:handleSize="8dp"
app:minFrameSize="100dp"
app:overlayColor="@color/uncrop_color"
app:touchPadding="8dp" />
</android.support.design.widget.CoordinatorLayout>
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import com.goparties.gpuser.util.CropImageView;
import java.io.IOException;
import butterknife.Bind;
public class CropImageActivity extends GpBaseActivity {
@Bind(R.id.cropImageView)
CropImageView cropImageView;
private Bitmap bitmap;
@Override
public boolean hasParent() {
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop_image);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), getIntent().getData());
} catch (IOException e) {
e.printStackTrace();
}
cropImageView.setImageBitmap(bitmap);
if (getIntent().getBooleanExtra("isCircular", false)) {
cropImageView.setCropMode(CropImageView.CropMode.CIRCLE);
} else
cropImageView.setCropMode(CropImageView.CropMode.RATIO_FREE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_image_crop, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.crop_done) {
if (cropImageView.saveBitmapInToFolder()) {
Intent intent = new Intent();
intent.setData(cropImageView.getImageUri());
setResult(RESULT_OK, intent);
finish();
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ImageView;
import com.goparties.gpuser.R;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class CropImageView extends ImageView {
private static final String TAG = CropImageView.class.getSimpleName();
// Constants ///////////////////////////////////////////////////////////////////////////////////
private static final int HANDLE_SIZE_IN_DP = 16;
private static final int MIN_FRAME_SIZE_IN_DP = 50;
private static final int FRAME_STROKE_WEIGHT_IN_DP = 1;
private static final int GUIDE_STROKE_WEIGHT_IN_DP = 1;
private static final float DEFAULT_INITIAL_FRAME_SCALE = 0.75f;
private final int TRANSPARENT;
private final int TRANSLUCENT_WHITE = 0xBBFFFFFF;
private final int WHITE = 0xFFFFFFFF;
private final int TRANSLUCENT_BLACK = 0xBB000000;
// Member variables ////////////////////////////////////////////////////////////////////////////
private int mViewWidth = 0;
private int mViewHeight = 0;
private float mScale = 1.0f;
private float mAngle = 0.0f;
private float mImgWidth = 0.0f;
private float mImgHeight = 0.0f;
private boolean mIsInitialized = false;
private Matrix mMatrix = null;
private Paint mPaintTransparent;
private Paint mPaintFrame;
private Paint mPaintBitmap;
private RectF mFrameRect;
private RectF mImageRect;
private PointF mCenter = new PointF();
private float mLastX, mLastY;
// Instance variables for customizable attributes //////////////////////////////////////////////
private TouchArea mTouchArea = TouchArea.OUT_OF_BOUNDS;
private CropMode mCropMode = CropMode.RATIO_1_1;
private ShowMode mGuideShowMode = ShowMode.SHOW_ALWAYS;
private ShowMode mHandleShowMode = ShowMode.SHOW_ALWAYS;
private float mMinFrameSize;
private int mHandleSize;
private int mTouchPadding = 0;
private boolean mShowGuide = true;
private boolean mShowHandle = true;
private boolean mIsCropEnabled = true;
private boolean mIsEnabled = true;
private PointF mCustomRatio = new PointF(1.0f, 1.0f);
private float mFrameStrokeWeight = 3.0f;
private float mGuideStrokeWeight = 3.0f;
private int mBackgroundColor;
private int mOverlayColor;
private int mFrameColor;
private int mHandleColor;
private int mGuideColor;
private float mInitialFrameScale; // 0.01 ~ 1.0, 0.75 is default value
private String imageName;
// Constructor /////////////////////////////////////////////////////////////////////////////////
public CropImageView(Context context) {
this(context, null);
}
public CropImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CropImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TRANSPARENT = getResources().getColor(android.R.color.transparent);
float mDensity = getDensity();
mHandleSize = (int) (mDensity * HANDLE_SIZE_IN_DP);
mMinFrameSize = mDensity * MIN_FRAME_SIZE_IN_DP;
mFrameStrokeWeight = mDensity * FRAME_STROKE_WEIGHT_IN_DP;
mGuideStrokeWeight = mDensity * GUIDE_STROKE_WEIGHT_IN_DP;
mPaintFrame = new Paint();
mPaintTransparent = new Paint();
mPaintBitmap = new Paint();
mPaintBitmap.setFilterBitmap(true);
mMatrix = new Matrix();
mScale = 1.0f;
mBackgroundColor = TRANSPARENT;
mFrameColor = WHITE;
mOverlayColor = TRANSLUCENT_BLACK;
mHandleColor = WHITE;
mGuideColor = TRANSLUCENT_WHITE;
// handle Styleable
handleStyleable(context, attrs, defStyle, mDensity);
}
// Lifecycle methods ///////////////////////////////////////////////////////////////////////////
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
Bitmap bm = getBitmap();
ss.image = bm;
ss.mode = this.mCropMode;
ss.backgroundColor = this.mBackgroundColor;
ss.overlayColor = this.mOverlayColor;
ss.frameColor = this.mFrameColor;
ss.guideShowMode = this.mGuideShowMode;
ss.handleShowMode = this.mHandleShowMode;
ss.showGuide = this.mShowGuide;
ss.showHandle = this.mShowHandle;
ss.handleSize = this.mHandleSize;
ss.touchPadding = this.mTouchPadding;
ss.minFrameSize = this.mMinFrameSize;
ss.customRatioX = this.mCustomRatio.x;
ss.customRatioY = this.mCustomRatio.y;
ss.frameStrokeWeight = this.mFrameStrokeWeight;
ss.guideStrokeWeight = this.mGuideStrokeWeight;
ss.isCropEnabled = this.mIsCropEnabled;
ss.handleColor = this.mHandleColor;
ss.guideColor = this.mGuideColor;
ss.initialFrameScale = this.mInitialFrameScale;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
this.mCropMode = ss.mode;
this.mBackgroundColor = ss.backgroundColor;
this.mOverlayColor = ss.overlayColor;
this.mFrameColor = ss.frameColor;
this.mGuideShowMode = ss.guideShowMode;
this.mHandleShowMode = ss.handleShowMode;
this.mShowGuide = ss.showGuide;
this.mShowHandle = ss.showHandle;
this.mHandleSize = ss.handleSize;
this.mTouchPadding = ss.touchPadding;
this.mMinFrameSize = ss.minFrameSize;
this.mCustomRatio = new PointF(ss.customRatioX, ss.customRatioY);
this.mFrameStrokeWeight = ss.frameStrokeWeight;
this.mGuideStrokeWeight = ss.guideStrokeWeight;
this.mIsCropEnabled = ss.isCropEnabled;
this.mHandleColor = ss.handleColor;
this.mGuideColor = ss.guideColor;
this.mInitialFrameScale = ss.initialFrameScale;
setImageBitmap(ss.image);
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
final int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(viewWidth, viewHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mViewWidth = r - l - getPaddingLeft() - getPaddingRight();
mViewHeight = b - t - getPaddingTop() - getPaddingBottom();
if (getDrawable() != null) initLayout(mViewWidth, mViewHeight);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mIsInitialized) {
setMatrix();
Matrix localMatrix1 = new Matrix();
localMatrix1.postConcat(this.mMatrix);
Bitmap bm = getBitmap();
if (bm != null) {
canvas.drawBitmap(bm, localMatrix1, mPaintBitmap);
// draw edit frame
drawEditFrame(canvas);
}
}
}
// Handle styleable ////////////////////////////////////////////////////////////////////////////
private void handleStyleable(Context context, AttributeSet attrs, int defStyle,
float mDensity) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CropImageView, defStyle,
0);
Drawable drawable;
mCropMode = CropMode.RATIO_1_1;
try {
drawable = ta.getDrawable(R.styleable.CropImageView_imgSrc);
if (drawable != null) setImageDrawable(drawable);
for (CropMode mode : CropMode.values()) {
if (ta.getInt(R.styleable.CropImageView_cropMode, 3) == mode.getId()) {
mCropMode = mode;
break;
}
}
mBackgroundColor = ta.getColor(R.styleable.CropImageView_backgroundColor, TRANSPARENT);
super.setBackgroundColor(mBackgroundColor);
mOverlayColor = ta.getColor(R.styleable.CropImageView_overlayColor, TRANSLUCENT_BLACK);
mFrameColor = ta.getColor(R.styleable.CropImageView_frameColor, WHITE);
mHandleColor = ta.getColor(R.styleable.CropImageView_handleColor, WHITE);
mGuideColor = ta.getColor(R.styleable.CropImageView_guideColor, TRANSLUCENT_WHITE);
for (ShowMode mode : ShowMode.values()) {
if (ta.getInt(R.styleable.CropImageView_guideShowMode, 1) == mode.getId()) {
mGuideShowMode = mode;
break;
}
}
for (ShowMode mode : ShowMode.values()) {
if (ta.getInt(R.styleable.CropImageView_handleShowMode, 1) == mode.getId()) {
mHandleShowMode = mode;
break;
}
}
setGuideShowMode(mGuideShowMode);
setHandleShowMode(mHandleShowMode);
mHandleSize = ta.getDimensionPixelSize(R.styleable.CropImageView_handleSize,
(int) (HANDLE_SIZE_IN_DP * mDensity));
mTouchPadding = ta.getDimensionPixelSize(R.styleable.CropImageView_touchPadding, 0);
mMinFrameSize = ta.getDimensionPixelSize(R.styleable.CropImageView_minFrameSize,
(int) (MIN_FRAME_SIZE_IN_DP * mDensity));
mFrameStrokeWeight = ta.getDimensionPixelSize(
R.styleable.CropImageView_frameStrokeWeight,
(int) (FRAME_STROKE_WEIGHT_IN_DP * mDensity));
mGuideStrokeWeight = ta.getDimensionPixelSize(
R.styleable.CropImageView_guideStrokeWeight,
(int) (GUIDE_STROKE_WEIGHT_IN_DP * mDensity));
mIsCropEnabled = ta.getBoolean(R.styleable.CropImageView_cropEnabled, true);
mInitialFrameScale = constrain(ta.getFloat(R.styleable.CropImageView_initialFrameScale,
DEFAULT_INITIAL_FRAME_SCALE), 0.01f, 1.0f,
DEFAULT_INITIAL_FRAME_SCALE);
} catch (Exception e) {
e.printStackTrace();
} finally {
ta.recycle();
}
}
// Drawing method //////////////////////////////////////////////////////////////////////////////
private void drawEditFrame(Canvas canvas) {
if (!mIsCropEnabled) return;
if (mCropMode == CropMode.CIRCLE) {
mPaintTransparent.setFilterBitmap(true);
mPaintTransparent.setColor(mOverlayColor);
mPaintTransparent.setStyle(Paint.Style.FILL);
Path path = new Path();
path.addRect(mImageRect.left, mImageRect.top, mImageRect.right, mImageRect.bottom,
Path.Direction.CW);
path.addCircle((mFrameRect.left + mFrameRect.right) / 2,
(mFrameRect.top + mFrameRect.bottom) / 2,
(mFrameRect.right - mFrameRect.left) / 2, Path.Direction.CCW);
canvas.drawPath(path, mPaintTransparent);
} else {
mPaintTransparent.setFilterBitmap(true);
mPaintTransparent.setColor(mOverlayColor);
mPaintTransparent.setStyle(Paint.Style.FILL);
canvas.drawRect(mImageRect.left, mImageRect.top, mImageRect.right, mFrameRect.top,
mPaintTransparent);
canvas.drawRect(mImageRect.left, mFrameRect.bottom, mImageRect.right, mImageRect.bottom,
mPaintTransparent);
canvas.drawRect(mImageRect.left, mFrameRect.top, mFrameRect.left, mFrameRect.bottom,
mPaintTransparent);
canvas.drawRect(mFrameRect.right, mFrameRect.top, mImageRect.right, mFrameRect.bottom,
mPaintTransparent);
}
mPaintFrame.setAntiAlias(true);
mPaintFrame.setFilterBitmap(true);
mPaintFrame.setStyle(Paint.Style.STROKE);
mPaintFrame.setColor(mFrameColor);
mPaintFrame.setStrokeWidth(mFrameStrokeWeight);
canvas.drawRect(mFrameRect.left, mFrameRect.top, mFrameRect.right, mFrameRect.bottom,
mPaintFrame);
if (mShowGuide) {
mPaintFrame.setColor(mGuideColor);
mPaintFrame.setStrokeWidth(mGuideStrokeWeight);
float h1 = mFrameRect.left + (mFrameRect.right - mFrameRect.left) / 3.0f;
float h2 = mFrameRect.right - (mFrameRect.right - mFrameRect.left) / 3.0f;
float v1 = mFrameRect.top + (mFrameRect.bottom - mFrameRect.top) / 3.0f;
float v2 = mFrameRect.bottom - (mFrameRect.bottom - mFrameRect.top) / 3.0f;
canvas.drawLine(h1, mFrameRect.top, h1, mFrameRect.bottom, mPaintFrame);
canvas.drawLine(h2, mFrameRect.top, h2, mFrameRect.bottom, mPaintFrame);
canvas.drawLine(mFrameRect.left, v1, mFrameRect.right, v1, mPaintFrame);
canvas.drawLine(mFrameRect.left, v2, mFrameRect.right, v2, mPaintFrame);
}
if (mShowHandle) {
mPaintFrame.setStyle(Paint.Style.FILL);
mPaintFrame.setColor(mHandleColor);
canvas.drawCircle(mFrameRect.left, mFrameRect.top, mHandleSize, mPaintFrame);
canvas.drawCircle(mFrameRect.right, mFrameRect.top, mHandleSize, mPaintFrame);
canvas.drawCircle(mFrameRect.left, mFrameRect.bottom, mHandleSize, mPaintFrame);
canvas.drawCircle(mFrameRect.right, mFrameRect.bottom, mHandleSize, mPaintFrame);
}
}
private void setMatrix() {
mMatrix.reset();
mMatrix.setTranslate(mCenter.x - mImgWidth * 0.5f, mCenter.y - mImgHeight * 0.5f);
mMatrix.postScale(mScale, mScale, mCenter.x, mCenter.y);
mMatrix.postRotate(mAngle, mCenter.x, mCenter.y);
}
// Initializer /////////////////////////////////////////////////////////////////////////////////
private void initLayout(int viewW, int viewH) {
mImgWidth = getDrawable().getIntrinsicWidth();
mImgHeight = getDrawable().getIntrinsicHeight();
if (mImgWidth <= 0) mImgWidth = viewW;
if (mImgHeight <= 0) mImgHeight = viewH;
float w = (float) viewW;
float h = (float) viewH;
float viewRatio = w / h;
float imgRatio = mImgWidth / mImgHeight;
float scale = 1.0f;
if (imgRatio >= viewRatio) {
scale = w / mImgWidth;
} else if (imgRatio < viewRatio) {
scale = h / mImgHeight;
}
setCenter(new PointF(getPaddingLeft() + w * 0.5f, getPaddingTop() + h * 0.5f));
setScale(scale);
initCropFrame();
adjustRatio();
mIsInitialized = true;
}
private void initCropFrame() {
setMatrix();
float[] arrayOfFloat = new float[8];
arrayOfFloat[0] = 0.0f;
arrayOfFloat[1] = 0.0f;
arrayOfFloat[2] = 0.0f;
arrayOfFloat[3] = 10000;
arrayOfFloat[4] = 100000;
arrayOfFloat[5] = 0.0f;
arrayOfFloat[6] = mImgWidth;
arrayOfFloat[7] = mImgHeight;
mMatrix.mapPoints(arrayOfFloat);
float l = arrayOfFloat[0];
float t = arrayOfFloat[1];
float r = arrayOfFloat[6];
float b = arrayOfFloat[7];
mFrameRect = new RectF(l, t, r, b);
mImageRect = new RectF(l, t, r, b);
}
// Touch Event /////////////////////////////////////////////////////////////////////////////////
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mIsInitialized) return false;
if (!mIsCropEnabled) return false;
if (!mIsEnabled) return false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onDown(event);
return true;
case MotionEvent.ACTION_MOVE:
onMove(event);
if (mTouchArea != TouchArea.OUT_OF_BOUNDS) {
getParent().requestDisallowInterceptTouchEvent(true);
}
return true;
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);
onCancel();
return true;
case MotionEvent.ACTION_UP:
getParent().requestDisallowInterceptTouchEvent(false);
onUp(event);
return true;
}
return false;
}
private void onDown(MotionEvent e) {
invalidate();
mLastX = e.getX();
mLastY = e.getY();
checkTouchArea(e.getX(), e.getY());
}
private void onMove(MotionEvent e) {
float diffX = e.getX() - mLastX;
float diffY = e.getY() - mLastY;
switch (mTouchArea) {
case CENTER:
moveFrame(diffX, diffY);
break;
case LEFT_TOP:
moveHandleLT(diffX, diffY);
break;
case RIGHT_TOP:
moveHandleRT(diffX, diffY);
break;
case LEFT_BOTTOM:
moveHandleLB(diffX, diffY);
break;
case RIGHT_BOTTOM:
moveHandleRB(diffX, diffY);
break;
case OUT_OF_BOUNDS:
break;
}
invalidate();
mLastX = e.getX();
mLastY = e.getY();
}
private void onUp(MotionEvent e) {
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = false;
if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = false;
mTouchArea = TouchArea.OUT_OF_BOUNDS;
invalidate();
}
private void onCancel() {
mTouchArea = TouchArea.OUT_OF_BOUNDS;
invalidate();
}
// Hit test ////////////////////////////////////////////////////////////////////////////////////
private void checkTouchArea(float x, float y) {
if (isInsideCornerLeftTop(x, y)) {
mTouchArea = TouchArea.LEFT_TOP;
if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = true;
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = true;
return;
}
if (isInsideCornerRightTop(x, y)) {
mTouchArea = TouchArea.RIGHT_TOP;
if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = true;
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = true;
return;
}
if (isInsideCornerLeftBottom(x, y)) {
mTouchArea = TouchArea.LEFT_BOTTOM;
if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = true;
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = true;
return;
}
if (isInsideCornerRightBottom(x, y)) {
mTouchArea = TouchArea.RIGHT_BOTTOM;
if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = true;
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = true;
return;
}
if (isInsideFrame(x, y)) {
if (mGuideShowMode == ShowMode.SHOW_ON_TOUCH) mShowGuide = true;
mTouchArea = TouchArea.CENTER;
return;
}
mTouchArea = TouchArea.OUT_OF_BOUNDS;
}
private boolean isInsideFrame(float x, float y) {
if (mFrameRect.left <= x && mFrameRect.right >= x) {
if (mFrameRect.top <= y && mFrameRect.bottom >= y) {
mTouchArea = TouchArea.CENTER;
return true;
}
}
return false;
}
private boolean isInsideCornerLeftTop(float x, float y) {
float dx = x - mFrameRect.left;
float dy = y - mFrameRect.top;
float d = dx * dx + dy * dy;
return sq(mHandleSize + mTouchPadding) >= d;
}
private boolean isInsideCornerRightTop(float x, float y) {
float dx = x - mFrameRect.right;
float dy = y - mFrameRect.top;
float d = dx * dx + dy * dy;
return sq(mHandleSize + mTouchPadding) >= d;
}
private boolean isInsideCornerLeftBottom(float x, float y) {
float dx = x - mFrameRect.left;
float dy = y - mFrameRect.bottom;
float d = dx * dx + dy * dy;
return sq(mHandleSize + mTouchPadding) >= d;
}
private boolean isInsideCornerRightBottom(float x, float y) {
float dx = x - mFrameRect.right;
float dy = y - mFrameRect.bottom;
float d = dx * dx + dy * dy;
return sq(mHandleSize + mTouchPadding) >= d;
}
// Adjust frame ////////////////////////////////////////////////////////////////////////////////
private void moveFrame(float x, float y) {
mFrameRect.left += x;
mFrameRect.right += x;
mFrameRect.top += y;
mFrameRect.bottom += y;
checkMoveBounds();
}
private void moveHandleLT(float diffX, float diffY) {
if (mCropMode == CropMode.RATIO_FREE) {
mFrameRect.left += diffX;
mFrameRect.top += diffY;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.left -= offsetX;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.top -= offsetY;
}
checkScaleBounds();
} else {
float dx = diffX;
float dy = diffX * getRatioY() / getRatioX();
mFrameRect.left += dx;
mFrameRect.top += dy;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.left -= offsetX;
float offsetY = offsetX * getRatioY() / getRatioX();
mFrameRect.top -= offsetY;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.top -= offsetY;
float offsetX = offsetY * getRatioX() / getRatioY();
mFrameRect.left -= offsetX;
}
float ox, oy;
if (!isInsideHorizontal(mFrameRect.left)) {
ox = mImageRect.left - mFrameRect.left;
mFrameRect.left += ox;
oy = ox * getRatioY() / getRatioX();
mFrameRect.top += oy;
}
if (!isInsideVertical(mFrameRect.top)) {
oy = mImageRect.top - mFrameRect.top;
mFrameRect.top += oy;
ox = oy * getRatioX() / getRatioY();
mFrameRect.left += ox;
}
}
}
private void moveHandleRT(float diffX, float diffY) {
if (mCropMode == CropMode.RATIO_FREE) {
mFrameRect.right += diffX;
mFrameRect.top += diffY;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.right += offsetX;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.top -= offsetY;
}
checkScaleBounds();
} else {
float dx = diffX;
float dy = diffX * getRatioY() / getRatioX();
mFrameRect.right += dx;
mFrameRect.top -= dy;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.right += offsetX;
float offsetY = offsetX * getRatioY() / getRatioX();
mFrameRect.top -= offsetY;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.top -= offsetY;
float offsetX = offsetY * getRatioX() / getRatioY();
mFrameRect.right += offsetX;
}
float ox, oy;
if (!isInsideHorizontal(mFrameRect.right)) {
ox = mFrameRect.right - mImageRect.right;
mFrameRect.right -= ox;
oy = ox * getRatioY() / getRatioX();
mFrameRect.top += oy;
}
if (!isInsideVertical(mFrameRect.top)) {
oy = mImageRect.top - mFrameRect.top;
mFrameRect.top += oy;
ox = oy * getRatioX() / getRatioY();
mFrameRect.right -= ox;
}
}
}
private void moveHandleLB(float diffX, float diffY) {
if (mCropMode == CropMode.RATIO_FREE) {
mFrameRect.left += diffX;
mFrameRect.bottom += diffY;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.left -= offsetX;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.bottom += offsetY;
}
checkScaleBounds();
} else {
float dx = diffX;
float dy = diffX * getRatioY() / getRatioX();
mFrameRect.left += dx;
mFrameRect.bottom -= dy;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.left -= offsetX;
float offsetY = offsetX * getRatioY() / getRatioX();
mFrameRect.bottom += offsetY;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.bottom += offsetY;
float offsetX = offsetY * getRatioX() / getRatioY();
mFrameRect.left -= offsetX;
}
float ox, oy;
if (!isInsideHorizontal(mFrameRect.left)) {
ox = mImageRect.left - mFrameRect.left;
mFrameRect.left += ox;
oy = ox * getRatioY() / getRatioX();
mFrameRect.bottom -= oy;
}
if (!isInsideVertical(mFrameRect.bottom)) {
oy = mFrameRect.bottom - mImageRect.bottom;
mFrameRect.bottom -= oy;
ox = oy * getRatioX() / getRatioY();
mFrameRect.left += ox;
}
}
}
private void moveHandleRB(float diffX, float diffY) {
if (mCropMode == CropMode.RATIO_FREE) {
mFrameRect.right += diffX;
mFrameRect.bottom += diffY;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.right += offsetX;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.bottom += offsetY;
}
checkScaleBounds();
} else {
float dx = diffX;
float dy = diffX * getRatioY() / getRatioX();
mFrameRect.right += dx;
mFrameRect.bottom += dy;
if (isWidthTooSmall()) {
float offsetX = mMinFrameSize - getFrameW();
mFrameRect.right += offsetX;
float offsetY = offsetX * getRatioY() / getRatioX();
mFrameRect.bottom += offsetY;
}
if (isHeightTooSmall()) {
float offsetY = mMinFrameSize - getFrameH();
mFrameRect.bottom += offsetY;
float offsetX = offsetY * getRatioX() / getRatioY();
mFrameRect.right += offsetX;
}
float ox, oy;
if (!isInsideHorizontal(mFrameRect.right)) {
ox = mFrameRect.right - mImageRect.right;
mFrameRect.right -= ox;
oy = ox * getRatioY() / getRatioX();
mFrameRect.bottom -= oy;
}
if (!isInsideVertical(mFrameRect.bottom)) {
oy = mFrameRect.bottom - mImageRect.bottom;
mFrameRect.bottom -= oy;
ox = oy * getRatioX() / getRatioY();
mFrameRect.right -= ox;
}
}
}
// Frame position correction ///////////////////////////////////////////////////////////////////
private void checkScaleBounds() {
float lDiff = mFrameRect.left - mImageRect.left;
float rDiff = mFrameRect.right - mImageRect.right;
float tDiff = mFrameRect.top - mImageRect.top;
float bDiff = mFrameRect.bottom - mImageRect.bottom;
if (lDiff < 0) {
mFrameRect.left -= lDiff;
}
if (rDiff > 0) {
mFrameRect.right -= rDiff;
}
if (tDiff < 0) {
mFrameRect.top -= tDiff;
}
if (bDiff > 0) {
mFrameRect.bottom -= bDiff;
}
}
private void checkMoveBounds() {
float diff = mFrameRect.left - mImageRect.left;
if (diff < 0) {
mFrameRect.left -= diff;
mFrameRect.right -= diff;
}
diff = mFrameRect.right - mImageRect.right;
if (diff > 0) {
mFrameRect.left -= diff;
mFrameRect.right -= diff;
}
diff = mFrameRect.top - mImageRect.top;
if (diff < 0) {
mFrameRect.top -= diff;
mFrameRect.bottom -= diff;
}
diff = mFrameRect.bottom - mImageRect.bottom;
if (diff > 0) {
mFrameRect.top -= diff;
mFrameRect.bottom -= diff;
}
}
private boolean isInsideHorizontal(float x) {
return mImageRect.left <= x && mImageRect.right >= x;
}
private boolean isInsideVertical(float y) {
return mImageRect.top <= y && mImageRect.bottom >= y;
}
private boolean isWidthTooSmall() {
return getFrameW() < mMinFrameSize;
}
private boolean isHeightTooSmall() {
return getFrameH() < mMinFrameSize;
}
// Frame aspect ratio correction ///////////////////////////////////////////////////////////////
private void adjustRatio() {
if (mImageRect == null) return;
float imgW = mImageRect.right - mImageRect.left;
float imgH = mImageRect.bottom - mImageRect.top;
float frameW = getRatioX(imgW);
float frameH = getRatioY(imgH);
float imgRatio = imgW / imgH;
float frameRatio = frameW / frameH;
float l = mImageRect.left, t = mImageRect.top, r = mImageRect.right, b = mImageRect.bottom;
if (frameRatio >= imgRatio) {
l = mImageRect.left;
r = mImageRect.right;
float hy = (mImageRect.top + mImageRect.bottom) * 0.5f;
float hh = (imgW / frameRatio) * 0.5f;
t = hy - hh;
b = hy + hh;
} else if (frameRatio < imgRatio) {
t = mImageRect.top;
b = mImageRect.bottom;
float hx = (mImageRect.left + mImageRect.right) * 0.5f;
float hw = imgH * frameRatio * 0.5f;
l = hx - hw;
r = hx + hw;
}
float w = r - l;
float h = b - t;
float cx = l + w / 2;
float cy = t + h / 2;
float sw = w * mInitialFrameScale;
float sh = h * mInitialFrameScale;
mFrameRect = new RectF(cx - sw / 2, cy - sh / 2, cx + sw / 2, cy + sh / 2);
invalidate();
}
private float getRatioX(float w) {
switch (mCropMode) {
case RATIO_FIT_IMAGE:
return mImgWidth;
case RATIO_FREE:
return w;
case RATIO_4_3:
return 4.0f;
case RATIO_3_4:
return 3.0f;
case RATIO_16_9:
return 16.0f;
case RATIO_9_16:
return 9.0f;
case RATIO_1_1:
case CIRCLE:
return 1.0f;
case RATIO_CUSTOM:
return mCustomRatio.x;
default:
return w;
}
}
private float getRatioY(float h) {
switch (mCropMode) {
case RATIO_FIT_IMAGE:
return mImgHeight;
case RATIO_FREE:
return h;
case RATIO_4_3:
return 3.0f;
case RATIO_3_4:
return 4.0f;
case RATIO_16_9:
return 9.0f;
case RATIO_9_16:
return 16.0f;
case RATIO_1_1:
case CIRCLE:
return 1.0f;
case RATIO_CUSTOM:
return mCustomRatio.y;
default:
return h;
}
}
private float getRatioX() {
switch (mCropMode) {
case RATIO_FIT_IMAGE:
return mImgWidth;
case RATIO_4_3:
return 4.0f;
case RATIO_3_4:
return 3.0f;
case RATIO_16_9:
return 16.0f;
case RATIO_9_16:
return 9.0f;
case RATIO_1_1:
case CIRCLE:
return 1.0f;
case RATIO_CUSTOM:
return mCustomRatio.x;
default:
return 1.0f;
}
}
private float getRatioY() {
switch (mCropMode) {
case RATIO_FIT_IMAGE:
return mImgHeight;
case RATIO_4_3:
return 3.0f;
case RATIO_3_4:
return 4.0f;
case RATIO_16_9:
return 9.0f;
case RATIO_9_16:
return 16.0f;
case RATIO_1_1:
case CIRCLE:
return 1.0f;
case RATIO_CUSTOM:
return mCustomRatio.y;
default:
return 1.0f;
}
}
// Utility methods /////////////////////////////////////////////////////////////////////////////
private float getDensity() {
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getMetrics(displayMetrics);
return displayMetrics.density;
}
private float sq(float value) {
return value * value;
}
private float constrain(float val, float min, float max, float defaultVal) {
if (val < min || val > max) return defaultVal;
return val;
}
// Public methods //////////////////////////////////////////////////////////////////////////////
/**
* Get source image bitmap
*
* @return src bitmap
*/
public Bitmap getImageBitmap() {
return getBitmap();
}
/**
* Set source image bitmap
*
* @param bitmap src image bitmap
*/
@Override
public void setImageBitmap(Bitmap bitmap) {
mIsInitialized = false;
super.setImageBitmap(bitmap);
updateDrawableInfo();
}
/**
* Set source image resource id
*
* @param resId source image resource id
*/
@Override
public void setImageResource(int resId) {
mIsInitialized = false;
super.setImageResource(resId);
updateDrawableInfo();
}
/**
* Set image drawable.
*
* @param drawable
*/
@Override
public void setImageDrawable(Drawable drawable) {
mIsInitialized = false;
super.setImageDrawable(drawable);
updateDrawableInfo();
}
/**
* Set image uri
*
* @param uri
*/
@Override
public void setImageURI(Uri uri) {
mIsInitialized = false;
super.setImageURI(uri);
updateDrawableInfo();
}
@Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(ScaleType.FIT_XY);
}
private void updateDrawableInfo() {
Drawable d = getDrawable();
if (d != null) {
initLayout(mViewWidth, mViewHeight);
}
}
/**
* Rotate image.
*
* @param degrees angle of ration in degrees.
*/
public void rotateImage(RotateDegrees degrees) {
Bitmap source = getBitmap();
if (source == null) return;
int angle = degrees.getValue();
Matrix matrix = new Matrix();
matrix.postRotate(angle);
Bitmap rotated = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
setImageBitmap(rotated);
}
/**
* Saves the Bitmap as a PNG file at path 'fullPath'
*
* @return true if it successfully saved, false otherwise
* path in form of(Environment.getExternalStorageDirectory().toString() +"/" + "folderName";);
*/
public boolean saveBitmapInToFolder() {
if (getCroppedBitmap() == null)
return false;
boolean fileCreated = false;
boolean bitmapCompressed = false;
boolean streamClosed = false;
String filePath = Environment.getExternalStorageDirectory().toString() + "/" + "Goparites";
File fileMake = new File(filePath);
if (!fileMake.exists()) {
fileMake.mkdir();
}
imageName = filePath + "/" + "image" + System.currentTimeMillis() + ".png";
File imageFile = new File(imageName);
if (imageFile.exists())
if (!imageFile.delete())
return false;
try {
fileCreated = imageFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
try {
out = new FileOutputStream(imageFile);
bitmapCompressed = getCroppedBitmap().compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
bitmapCompressed = false;
} finally {
if (out != null) {
try {
out.flush();
out.close();
streamClosed = true;
} catch (IOException e) {
e.printStackTrace();
streamClosed = false;
}
}
}
return (fileCreated && bitmapCompressed && streamClosed);
}
public Uri getImageUri() {
Uri uri = Uri.fromFile(new File(imageName));
return uri;
}
/**
* Get cropped image bitmap
*
* @return cropped image bitmap
*/
public Bitmap getCroppedBitmap() {
Bitmap source = getBitmap();
if (source == null) return null;
int x, y, w, h;
float l = (mFrameRect.left / mScale);
float t = (mFrameRect.top / mScale);
float r = (mFrameRect.right / mScale);
float b = (mFrameRect.bottom / mScale);
x = Math.round(l - (mImageRect.left / mScale));
y = Math.round(t - (mImageRect.top / mScale));
w = Math.round(r - l);
h = Math.round(b - t);
if (x + w > source.getWidth()) {
w = source.getWidth() - x;
}
if (y + h > source.getHeight()) {
h = source.getHeight() - y;
}
Bitmap cropped = Bitmap.createBitmap(source, x, y, w, h, null, false);
if (mCropMode != CropMode.CIRCLE) return cropped;
return getCircularBitmap(cropped);
}
/**
* Get cropped rect image bitmap
* <p/>
* This method always returns rect image.
* (If you need a square image with CropMode.CIRCLE, you can use this method.)
*
* @return cropped image bitmap
*/
public Bitmap getRectBitmap() {
Bitmap source = getBitmap();
if (source == null) return null;
int x, y, w, h;
float l = (mFrameRect.left / mScale);
float t = (mFrameRect.top / mScale);
float r = (mFrameRect.right / mScale);
float b = (mFrameRect.bottom / mScale);
x = Math.round(l - (mImageRect.left / mScale));
y = Math.round(t - (mImageRect.top / mScale));
w = Math.round(r - l);
h = Math.round(b - t);
if (x + w > source.getWidth()) {
w = source.getWidth() - x;
}
if (y + h > source.getHeight()) {
h = source.getHeight() - y;
}
return Bitmap.createBitmap(source, x, y, w, h, null, false);
}
/**
* Crop the square image in a circular
*
* @param square image bitmap
* @return circular image bitmap
*/
public Bitmap getCircularBitmap(Bitmap square) {
if (square == null) return null;
Bitmap output = Bitmap.createBitmap(square.getWidth(), square.getHeight(),
Bitmap.Config.ARGB_8888);
final Rect rect = new Rect(0, 0, square.getWidth(), square.getHeight());
Canvas canvas = new Canvas(output);
int halfWidth = square.getWidth() / 2;
int halfHeight = square.getHeight() / 2;
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
canvas.drawCircle(halfWidth, halfHeight, Math.min(halfWidth, halfHeight), paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(square, rect, rect, paint);
return output;
}
private Bitmap getBitmap() {
Bitmap bm = null;
Drawable d = getDrawable();
if (d != null && d instanceof BitmapDrawable) bm = ((BitmapDrawable) d).getBitmap();
return bm;
}
/**
* Get frame position relative to the source bitmap.
*
* @return crop area boundaries.
*/
public RectF getActualCropRect() {
float offsetX = (mImageRect.left / mScale);
float offsetY = (mImageRect.top / mScale);
float l = (mFrameRect.left / mScale) - offsetX;
float t = (mFrameRect.top / mScale) - offsetY;
float r = (mFrameRect.right / mScale) - offsetX;
float b = (mFrameRect.bottom / mScale) - offsetY;
return new RectF(l, t, r, b);
}
/**
* Set crop mode
*
* @param mode crop mode
*/
public void setCropMode(CropMode mode) {
if (mode == CropMode.RATIO_CUSTOM) {
setCustomRatio(1, 1);
} else {
mCropMode = mode;
adjustRatio();
}
}
/**
* Set custom aspect ratio to crop frame
*
* @param ratioX aspect ratio X
* @param ratioY aspect ratio Y
*/
public void setCustomRatio(int ratioX, int ratioY) {
if (ratioX == 0 || ratioY == 0) return;
mCropMode = CropMode.RATIO_CUSTOM;
mCustomRatio = new PointF(ratioX, ratioY);
adjustRatio();
}
/**
* Set image overlay color
*
* @param overlayColor color resId or color int(ex. 0xFFFFFFFF)
*/
public void setOverlayColor(int overlayColor) {
this.mOverlayColor = overlayColor;
invalidate();
}
/**
* Set crop frame color
*
* @param frameColor color resId or color int(ex. 0xFFFFFFFF)
*/
public void setFrameColor(int frameColor) {
this.mFrameColor = frameColor;
invalidate();
}
/**
* Set handle color
*
* @param handleColor color resId or color int(ex. 0xFFFFFFFF)
*/
public void setHandleColor(int handleColor) {
this.mHandleColor = handleColor;
invalidate();
}
/**
* Set guide color
*
* @param guideColor color resId or color int(ex. 0xFFFFFFFF)
*/
public void setGuideColor(int guideColor) {
this.mGuideColor = guideColor;
invalidate();
}
/**
* Set view background color
*
* @param bgColor color resId or color int(ex. 0xFFFFFFFF)
*/
public void setBackgroundColor(int bgColor) {
this.mBackgroundColor = bgColor;
super.setBackgroundColor(this.mBackgroundColor);
invalidate();
}
/**
* Set crop frame minimum size in density-independent pixels.
*
* @param minDp crop frame minimum size in density-independent pixels
*/
public void setMinFrameSizeInDp(int minDp) {
mMinFrameSize = minDp * getDensity();
}
/**
* Set crop frame minimum size in pixels.
*
* @param minPx crop frame minimum size in pixels
*/
public void setMinFrameSizeInPx(int minPx) {
mMinFrameSize = minPx;
}
/**
* Set handle radius in density-independent pixels.
*
* @param handleDp handle radius in density-independent pixels
*/
public void setHandleSizeInDp(int handleDp) {
mHandleSize = (int) (handleDp * getDensity());
}
/**
* Set crop frame handle touch padding(touch area) in density-independent pixels.
* <p/>
* handle touch area : a circle of radius R.(R = handle size + touch padding)
*
* @param paddingDp crop frame handle touch padding(touch area) in density-independent pixels
*/
public void setTouchPaddingInDp(int paddingDp) {
mTouchPadding = (int) (paddingDp * getDensity());
}
/**
* Set guideline show mode.
* (SHOW_ALWAYS/NOT_SHOW/SHOW_ON_TOUCH)
*
* @param mode guideline show mode
*/
public void setGuideShowMode(ShowMode mode) {
mGuideShowMode = mode;
switch (mode) {
case SHOW_ALWAYS:
mShowGuide = true;
break;
case NOT_SHOW:
case SHOW_ON_TOUCH:
mShowGuide = false;
break;
}
invalidate();
}
/**
* Set handle show mode.
* (SHOW_ALWAYS/NOT_SHOW/SHOW_ON_TOUCH)
*
* @param mode handle show mode
*/
public void setHandleShowMode(ShowMode mode) {
mHandleShowMode = mode;
switch (mode) {
case SHOW_ALWAYS:
mShowHandle = true;
break;
case NOT_SHOW:
case SHOW_ON_TOUCH:
mShowHandle = false;
break;
}
invalidate();
}
/**
* Set frame stroke weight in density-independent pixels.
*
* @param weightDp frame stroke weight in density-independent pixels.
*/
public void setFrameStrokeWeightInDp(int weightDp) {
mFrameStrokeWeight = weightDp * getDensity();
invalidate();
}
/**
* Set guideline stroke weight in density-independent pixels.
*
* @param weightDp guideline stroke weight in density-independent pixels.
*/
public void setGuideStrokeWeightInDp(int weightDp) {
mGuideStrokeWeight = weightDp * getDensity();
invalidate();
}
/**
* Set whether to show crop frame.
*
* @param enabled should show crop frame?
*/
public void setCropEnabled(boolean enabled) {
mIsCropEnabled = enabled;
invalidate();
}
/**
* Set locking the crop frame.
*
* @param enabled should lock crop frame?
*/
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
mIsEnabled = enabled;
}
/**
* Set initial scale of the frame.(0.01 ~ 1.0)
*
* @param initialScale initial scale
*/
public void setInitialFrameScale(float initialScale) {
mInitialFrameScale = constrain(initialScale, 0.01f, 1.0f, DEFAULT_INITIAL_FRAME_SCALE);
}
private void setScale(float mScale) {
this.mScale = mScale;
}
private void setCenter(PointF mCenter) {
this.mCenter = mCenter;
}
private float getFrameW() {
return (mFrameRect.right - mFrameRect.left);
}
private float getFrameH() {
return (mFrameRect.bottom - mFrameRect.top);
}
// Enum ////////////////////////////////////////////////////////////////////////////////////////
private enum TouchArea {
OUT_OF_BOUNDS, CENTER, LEFT_TOP, RIGHT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM;
}
public enum CropMode {
RATIO_FIT_IMAGE(0), RATIO_4_3(1), RATIO_3_4(2), RATIO_1_1(3), RATIO_16_9(4), RATIO_9_16(
5), RATIO_FREE(6), RATIO_CUSTOM(7), CIRCLE(8);
private final int ID;
private CropMode(final int id) {
this.ID = id;
}
public int getId() {
return ID;
}
}
public enum ShowMode {
SHOW_ALWAYS(1), SHOW_ON_TOUCH(2), NOT_SHOW(3);
private final int ID;
private ShowMode(final int id) {
this.ID = id;
}
public int getId() {
return ID;
}
}
public enum RotateDegrees {
ROTATE_90D(90), ROTATE_180D(180), ROTATE_270D(270);
private final int VALUE;
private RotateDegrees(final int value) {
this.VALUE = value;
}
public int getValue() {
return VALUE;
}
}
// Save/Restore support ////////////////////////////////////////////////////////////////////////
public static class SavedState extends BaseSavedState {
Bitmap image;
CropMode mode;
int backgroundColor;
int overlayColor;
int frameColor;
ShowMode guideShowMode;
ShowMode handleShowMode;
boolean showGuide;
boolean showHandle;
int handleSize;
int touchPadding;
float minFrameSize;
float customRatioX;
float customRatioY;
float frameStrokeWeight;
float guideStrokeWeight;
boolean isCropEnabled;
int handleColor;
int guideColor;
float initialFrameScale;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
image = in.readParcelable(Bitmap.class.getClassLoader());
mode = (CropMode) in.readSerializable();
backgroundColor = in.readInt();
overlayColor = in.readInt();
frameColor = in.readInt();
guideShowMode = (ShowMode) in.readSerializable();
handleShowMode = (ShowMode) in.readSerializable();
showGuide = (in.readInt() != 0);
showHandle = (in.readInt() != 0);
handleSize = in.readInt();
touchPadding = in.readInt();
minFrameSize = in.readFloat();
customRatioX = in.readFloat();
customRatioY = in.readFloat();
frameStrokeWeight = in.readFloat();
guideStrokeWeight = in.readFloat();
isCropEnabled = (in.readInt() != 0);
handleColor = in.readInt();
guideColor = in.readInt();
initialFrameScale = in.readFloat();
}
@Override
public void writeToParcel(Parcel out, int flag) {
super.writeToParcel(out, flag);
out.writeParcelable(image, flag);
out.writeSerializable(mode);
out.writeInt(backgroundColor);
out.writeInt(overlayColor);
out.writeInt(frameColor);
out.writeSerializable(guideShowMode);
out.writeSerializable(handleShowMode);
out.writeInt(showGuide ? 1 : 0);
out.writeInt(showHandle ? 1 : 0);
out.writeInt(handleSize);
out.writeInt(touchPadding);
out.writeFloat(minFrameSize);
out.writeFloat(customRatioX);
out.writeFloat(customRatioY);
out.writeFloat(frameStrokeWeight);
out.writeFloat(guideStrokeWeight);
out.writeInt(isCropEnabled ? 1 : 0);
out.writeInt(handleColor);
out.writeInt(guideColor);
out.writeFloat(initialFrameScale);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public SavedState createFromParcel(final Parcel inParcel) {
return new SavedState(inParcel);
}
public SavedState[] newArray(final int inSize) {
return new SavedState[inSize];
}
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment