From 26cf2d92ab72d9d099a86ef0bdf85150d2abfaf8 Mon Sep 17 00:00:00 2001 From: Zac Morris Date: Fri, 25 Nov 2016 15:38:12 -0500 Subject: [PATCH 1/4] Added passing exception to onError of various callbacks Added ability to register a "preview" ImageView that is updated with the cropped area on the "onUp" event, and on rotate and load events. Updated graded properties to add jitpack.io repo, upgrade to grade 2.2.2, and compiled SDK to version 25 --- simplecropview/build.gradle | 5 +- .../simplecropview/CropImageView.java | 101 +++++++++++++----- .../simplecropview/callback/Callback.java | 2 +- .../simplecropview/callback/CropCallback.java | 1 - .../simplecropview/callback/LoadCallback.java | 1 - .../simplecropview/callback/SaveCallback.java | 1 - 6 files changed, 75 insertions(+), 36 deletions(-) diff --git a/simplecropview/build.gradle b/simplecropview/build.gradle index b5433a5..cc7e543 100644 --- a/simplecropview/build.gradle +++ b/simplecropview/build.gradle @@ -1,9 +1,8 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" - + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 10 targetSdkVersion 23 diff --git a/simplecropview/src/main/java/com/isseiaoki/simplecropview/CropImageView.java b/simplecropview/src/main/java/com/isseiaoki/simplecropview/CropImageView.java index e34561e..d618b35 100644 --- a/simplecropview/src/main/java/com/isseiaoki/simplecropview/CropImageView.java +++ b/simplecropview/src/main/java/com/isseiaoki/simplecropview/CropImageView.java @@ -1,16 +1,4 @@ package com.isseiaoki.simplecropview; - -import com.isseiaoki.simplecropview.animation.SimpleValueAnimator; -import com.isseiaoki.simplecropview.animation.SimpleValueAnimatorListener; -import com.isseiaoki.simplecropview.animation.ValueAnimatorV14; -import com.isseiaoki.simplecropview.animation.ValueAnimatorV8; -import com.isseiaoki.simplecropview.callback.Callback; -import com.isseiaoki.simplecropview.callback.CropCallback; -import com.isseiaoki.simplecropview.callback.LoadCallback; -import com.isseiaoki.simplecropview.callback.SaveCallback; -import com.isseiaoki.simplecropview.util.Logger; -import com.isseiaoki.simplecropview.util.Utils; - import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -41,6 +29,17 @@ import android.view.animation.Interpolator; import android.widget.ImageView; +import com.isseiaoki.simplecropview.animation.SimpleValueAnimator; +import com.isseiaoki.simplecropview.animation.SimpleValueAnimatorListener; +import com.isseiaoki.simplecropview.animation.ValueAnimatorV14; +import com.isseiaoki.simplecropview.animation.ValueAnimatorV8; +import com.isseiaoki.simplecropview.callback.Callback; +import com.isseiaoki.simplecropview.callback.CropCallback; +import com.isseiaoki.simplecropview.callback.LoadCallback; +import com.isseiaoki.simplecropview.callback.SaveCallback; +import com.isseiaoki.simplecropview.util.Logger; +import com.isseiaoki.simplecropview.util.Utils; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -111,6 +110,7 @@ public class CropImageView extends ImageView { private int mOutputImageWidth = 0; private int mOutputImageHeight = 0; private boolean mIsLoading = false; + private ImageView mPreviewImageView = null; // Instance variables for customizable attributes ////////////////////////////////////////////// private TouchArea mTouchArea = TouchArea.OUT_OF_BOUNDS; @@ -284,7 +284,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (getDrawable() != null) setupLayout(mViewWidth, mViewHeight); + if (getDrawable() != null && !mIsInitialized) + setupLayout(mViewWidth, mViewHeight); } @Override @@ -302,6 +303,7 @@ public void onDraw(Canvas canvas) { if (mIsDebug) { drawDebugInfo(canvas); } + } } @@ -544,6 +546,7 @@ private void setupLayout(int viewW, int viewH) { mFrameRect = calcFrameRect(mImageRect); mIsInitialized = true; invalidate(); + int s=1; } private float calcScale(int viewW, int viewH, float angle) { @@ -671,6 +674,8 @@ private void onUp(MotionEvent e) { if (mHandleShowMode == ShowMode.SHOW_ON_TOUCH) mShowHandle = false; mTouchArea = TouchArea.OUT_OF_BOUNDS; invalidate(); + updatePreview(); + } private void onCancel() { @@ -1043,6 +1048,7 @@ public void onAnimationUpdated(float scale) { @Override public void onAnimationFinished() { mFrameRect = newRect; + updatePreview(); invalidate(); mIsAnimating = false; } @@ -1168,15 +1174,15 @@ private float constrain(float val, float min, float max, float defaultVal) { return val; } - private void postErrorOnMainThread(final Callback callback) { + private void postErrorOnMainThread(final Callback callback,final Throwable exception) { if (callback == null) return; if (Looper.myLooper() == Looper.getMainLooper()) { - callback.onError(); + callback.onError(exception); } else { mHandler.post(new Runnable() { @Override public void run() { - callback.onError(); + callback.onError(exception); } }); } @@ -1334,8 +1340,9 @@ private void saveToFile(Bitmap bitmap, final Uri uri) { bitmap.compress(mCompressFormat, mCompressQuality, outputStream); } } catch (IOException e) { - Logger.e("An error occurred while saving the image: " + uri, e); - postErrorOnMainThread(mSaveCallback); + final String msg = "An error occurred while saving the image: " + uri; + Logger.e(msg, e); + postErrorOnMainThread(mSaveCallback,new IOException(msg,e)); } finally { Utils.closeQuietly(outputStream); } @@ -1408,7 +1415,7 @@ public void setImageURI(Uri uri) { private void updateLayout() { resetImageInfo(); Drawable d = getDrawable(); - if (d != null) { + if (d != null && !mIsInitialized) { setupLayout(mViewWidth, mViewHeight); } } @@ -1430,11 +1437,24 @@ private void resetImageInfo() { * @param sourceUri Image Uri * @param callback Callback */ - public void startLoad(Uri sourceUri, LoadCallback callback) { + public void startLoad(Uri sourceUri, LoadCallback callback){ + startLoad(sourceUri,callback,null); + } + + /** + * Load image from Uri. + * + * @param sourceUri Image Uri + * @param callback Callback + * @param preview ImageView to be populated with the cropped area on event onUp + */ + public void startLoad(Uri sourceUri, LoadCallback callback, ImageView preview) { mLoadCallback = callback; mSourceUri = sourceUri; + mPreviewImageView = preview; + mPreviewImageView.setScaleType(ScaleType.FIT_XY); if (sourceUri == null) { - postErrorOnMainThread(mLoadCallback); + postErrorOnMainThread(mLoadCallback,new IllegalStateException("Source Uri must not be null.")); throw new IllegalStateException("Source Uri must not be null."); } mExecutor.submit(new Runnable() { @@ -1456,23 +1476,43 @@ public void run() { public void run() { mAngle = mExifRotation; setImageBitmap(sampledBitmap); + updatePreview(); if (mLoadCallback != null) mLoadCallback.onSuccess(); mIsLoading = false; } }); } catch (OutOfMemoryError e) { - Logger.e("OOM Error: " + e.getMessage(), e); - postErrorOnMainThread(mLoadCallback); + final String msg = "Oot of Memory Error: " + e.getMessage(); + Logger.e(msg, e); + postErrorOnMainThread(mLoadCallback,new OutOfMemoryError(msg)); mIsLoading = false; } catch (Exception e) { - Logger.e("An unexpected error has occurred: " + e.getMessage(), e); - postErrorOnMainThread(mLoadCallback); + final String msg = "An unexpected error has occurred: " + e.getMessage(); + Logger.e(msg, e); + postErrorOnMainThread(mLoadCallback,new Exception(msg,e)); mIsLoading = false; } } }); } + private void updatePreview(){ + mHandler.post(new Runnable(){ + @Override public void run(){ + float h=mPreviewImageView.getHeight(); + float w=mPreviewImageView.getWidth(); + float hr=getRatioY(h); + float wr=getRatioX(w); + try{ + mPreviewImageView.getLayoutParams().width=Math.round(h*(wr/hr)); + mPreviewImageView.setImageBitmap(getCroppedBitmap()); + }catch(Exception e){ + e.printStackTrace(); + } + } + } + ); + } /** * Rotate image * @@ -1510,6 +1550,7 @@ public void onAnimationFinished() { mAngle = newAngle % 360; mScale = newScale; setupLayout(mViewWidth, mViewHeight); + updatePreview(); mIsRotating = false; } }); @@ -1561,6 +1602,7 @@ public Bitmap getCroppedBitmap() { } cropped = circle; } + //mIsInitialized=false; return cropped; } @@ -1603,8 +1645,9 @@ public void startCrop(Uri saveUri, CropCallback cropCallback, SaveCallback saveC mCropCallback = cropCallback; mSaveCallback = saveCallback; if (mIsCropping) { - postErrorOnMainThread(mCropCallback); - postErrorOnMainThread(mSaveCallback); + final String msg = "Another cropping operation is already active."; + postErrorOnMainThread(mCropCallback,new RuntimeException(msg)); + postErrorOnMainThread(mSaveCallback,new RuntimeException(msg)); return; } mIsCropping = true; @@ -1645,11 +1688,11 @@ public void run() { } // Error else { - postErrorOnMainThread(mCropCallback); + postErrorOnMainThread(mCropCallback,new NullPointerException("Resulting crop generated a null value")); } if (mSaveUri == null) { - postErrorOnMainThread(mSaveCallback); + postErrorOnMainThread(mSaveCallback,new NullPointerException("The save location for the crop was null or invalid")); return; } saveToFile(cropped, mSaveUri); diff --git a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/Callback.java b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/Callback.java index 11fe903..f6e9340 100644 --- a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/Callback.java +++ b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/Callback.java @@ -1,5 +1,5 @@ package com.isseiaoki.simplecropview.callback; public interface Callback { - void onError(); + void onError(Throwable e); } diff --git a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/CropCallback.java b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/CropCallback.java index c49da34..d169190 100644 --- a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/CropCallback.java +++ b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/CropCallback.java @@ -4,5 +4,4 @@ public interface CropCallback extends Callback { void onSuccess(Bitmap cropped); - void onError(); } diff --git a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/LoadCallback.java b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/LoadCallback.java index 39cdd93..858d475 100644 --- a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/LoadCallback.java +++ b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/LoadCallback.java @@ -3,5 +3,4 @@ public interface LoadCallback extends Callback{ void onSuccess(); - void onError(); } diff --git a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/SaveCallback.java b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/SaveCallback.java index 11ffa33..0d727ec 100644 --- a/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/SaveCallback.java +++ b/simplecropview/src/main/java/com/isseiaoki/simplecropview/callback/SaveCallback.java @@ -5,5 +5,4 @@ public interface SaveCallback extends Callback{ void onSuccess(Uri outputUri); - void onError(); } From 4f17e2902481b30f9bf822bb3ae6502d09711ca2 Mon Sep 17 00:00:00 2001 From: Zac Morris Date: Fri, 25 Nov 2016 16:07:18 -0500 Subject: [PATCH 2/4] Added jitpack.io link and note that this is a fork --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e35f1f0..dcac7e2 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,14 @@ -![](https://raw.github.com/wiki/IsseiAoki/SimpleCropView/images/device-art/cover-art.png) +Fork of SimpleCropView https://raw.github.com/wiki/IsseiAoki/SimpleCropView + +[![](https://jitpack.io/v/ZacWolf/SimpleCropView.svg)](https://jitpack.io/#ZacWolf/SimpleCropView) -#SimpleCropView -[![build status](https://travis-ci.org/IsseiAoki/SimpleCropView.svg)](https://travis-ci.org/IsseiAoki/SimpleCropView) -[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-SimpleCropView-green.svg?style=flat)](https://android-arsenal.com/details/1/2366) -[![Android Gems](http://www.android-gems.com/badge/IsseiAoki/SimpleCropView.svg?branch=master)](http://www.android-gems.com/lib/IsseiAoki/SimpleCropView) +![](https://raw.github.com/wiki/IsseiAoki/SimpleCropView/images/device-art/cover-art.png) The SimpleCropView is an image cropping library for Android.
It simplifies your code for cropping image and provides an easily customizable UI.

Supported on API Level 10 and above. -![demo](https://raw.github.com/wiki/IsseiAoki/SimpleCropView/images/1.1.0/demo_basic_usage.gif) - - ##Table of Contents * [Download](#download) * [Example](#example) From 75d3c39bd4be5114b01a0af5cb3768a6ef29a594 Mon Sep 17 00:00:00 2001 From: Zac Morris Date: Fri, 25 Nov 2016 16:08:21 -0500 Subject: [PATCH 3/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dcac7e2..f8fdfa7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Fork of SimpleCropView https://raw.github.com/wiki/IsseiAoki/SimpleCropView +Fork of SimpleCropView https://github.com/IsseiAoki/SimpleCropView [![](https://jitpack.io/v/ZacWolf/SimpleCropView.svg)](https://jitpack.io/#ZacWolf/SimpleCropView) From fb965eb19fef8666a6362313409c3b199dc7d1ec Mon Sep 17 00:00:00 2001 From: Zac Morris Date: Fri, 25 Nov 2016 15:51:13 -0500 Subject: [PATCH 4/4] better onError handing for Callbacks and new registerd preview ImageView Added passing exception to onError of various callbacks Added ability to register a "preview" ImageView that is updated with the cropped area on the "onUp" event, and on rotate and load events. Updated graded properties to add jitpack.io repo, upgrade to grade 2.2.2, and compiled SDK to version 25 --- build.gradle | 10 ++++-- gradle/wrapper/gradle-wrapper.properties | 2 +- simplecropview-sample/build.gradle | 8 ++--- .../simplecropviewsample/MainFragment.java | 32 +++++++++---------- .../res/drawable/border_black_fill_trans.xml | 7 ++++ .../res/drawable/border_black_fill_white.xml | 7 ++++ .../src/main/res/layout/fragment_main.xml | 31 +++++++++++++++++- .../src/main/res/values/colors.xml | 5 ++- 8 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 simplecropview-sample/src/main/res/drawable/border_black_fill_trans.xml create mode 100644 simplecropview-sample/src/main/res/drawable/border_black_fill_white.xml diff --git a/build.gradle b/build.gradle index da96688..c60b8a7 100644 --- a/build.gradle +++ b/build.gradle @@ -3,11 +3,12 @@ buildscript { repositories { jcenter() + maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0' + classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -17,5 +18,10 @@ buildscript { allprojects { repositories { jcenter() + maven { url "https://jitpack.io" } } } + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0ecc9c0..1081cc3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/simplecropview-sample/build.gradle b/simplecropview-sample/build.gradle index c1dd61e..076e051 100644 --- a/simplecropview-sample/build.gradle +++ b/simplecropview-sample/build.gradle @@ -2,13 +2,13 @@ apply plugin: 'com.android.application' apply plugin: 'android-apt' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { applicationId "com.example.simplecropviewsample" minSdkVersion 13 - targetSdkVersion 23 + targetSdkVersion 24 versionCode 1 versionName "1.0.0" } @@ -38,7 +38,7 @@ ext { } dependencies { - compile "com.android.support:appcompat-v7:23.3.0" + compile "com.android.support:appcompat-v7:25+" compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':simplecropview') compile "com.github.hotchemi:permissionsdispatcher:${permissionsDispatcherVersion}" diff --git a/simplecropview-sample/src/main/java/com/example/simplecropviewsample/MainFragment.java b/simplecropview-sample/src/main/java/com/example/simplecropviewsample/MainFragment.java index 9d5ce5b..02763d9 100644 --- a/simplecropview-sample/src/main/java/com/example/simplecropviewsample/MainFragment.java +++ b/simplecropview-sample/src/main/java/com/example/simplecropviewsample/MainFragment.java @@ -1,11 +1,4 @@ package com.example.simplecropviewsample; - -import com.isseiaoki.simplecropview.CropImageView; -import com.isseiaoki.simplecropview.callback.CropCallback; -import com.isseiaoki.simplecropview.callback.LoadCallback; -import com.isseiaoki.simplecropview.callback.SaveCallback; -import com.isseiaoki.simplecropview.util.Utils; - import android.Manifest; import android.app.Activity; import android.content.DialogInterface; @@ -21,8 +14,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.LinearLayout; +import com.isseiaoki.simplecropview.CropImageView; +import com.isseiaoki.simplecropview.callback.CropCallback; +import com.isseiaoki.simplecropview.callback.LoadCallback; +import com.isseiaoki.simplecropview.callback.SaveCallback; +import com.isseiaoki.simplecropview.util.Utils; + import java.io.File; import permissions.dispatcher.NeedsPermission; @@ -38,6 +38,7 @@ public class MainFragment extends Fragment { // Views /////////////////////////////////////////////////////////////////////////////////////// private CropImageView mCropView; + private ImageView mPreView; private LinearLayout mRootLayout; // Note: only the system can call this constructor by reflection. @@ -71,9 +72,6 @@ public void onViewCreated(View view, Bundle savedInstanceState) { FontUtils.setFont(mRootLayout); // mCropView.setDebug(true); // set bitmap to CropImageView - if (mCropView.getImageBitmap() == null) { - mCropView.setImageResource(R.drawable.sample5); - } } @Override @@ -81,10 +79,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent result) { super.onActivityResult(requestCode, resultCode, result); if (requestCode == REQUEST_PICK_IMAGE && resultCode == Activity.RESULT_OK) { showProgress(); - mCropView.startLoad(result.getData(), mLoadCallback); + mCropView.startLoad(result.getData(), mLoadCallback,mPreView); } else if (requestCode == REQUEST_SAF_PICK_IMAGE && resultCode == Activity.RESULT_OK) { showProgress(); - mCropView.startLoad(Utils.ensureUriPermission(getContext(), result), mLoadCallback); + mCropView.startLoad(Utils.ensureUriPermission(getContext(), result), mLoadCallback,mPreView); } } @@ -98,6 +96,8 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis private void bindViews(View view) { mCropView = (CropImageView) view.findViewById(R.id.cropImageView); + mPreView = (ImageView) view.findViewById(R.id.previewImageView); + view.findViewById(R.id.buttonDone).setOnClickListener(btnListener); view.findViewById(R.id.buttonFitImage).setOnClickListener(btnListener); view.findViewById(R.id.button1_1).setOnClickListener(btnListener); @@ -245,7 +245,7 @@ public void onSuccess() { } @Override - public void onError() { + public void onError(Throwable e) { dismissProgress(); } }; @@ -256,7 +256,7 @@ public void onSuccess(Bitmap cropped) { } @Override - public void onError() { + public void onError(Throwable e) { } }; @@ -268,8 +268,8 @@ public void onSuccess(Uri outputUri) { } @Override - public void onError() { + public void onError(Throwable e) { dismissProgress(); } }; -} \ No newline at end of file +} diff --git a/simplecropview-sample/src/main/res/drawable/border_black_fill_trans.xml b/simplecropview-sample/src/main/res/drawable/border_black_fill_trans.xml new file mode 100644 index 0000000..c76bfd5 --- /dev/null +++ b/simplecropview-sample/src/main/res/drawable/border_black_fill_trans.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/simplecropview-sample/src/main/res/drawable/border_black_fill_white.xml b/simplecropview-sample/src/main/res/drawable/border_black_fill_white.xml new file mode 100644 index 0000000..6eb4e5b --- /dev/null +++ b/simplecropview-sample/src/main/res/drawable/border_black_fill_white.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/simplecropview-sample/src/main/res/layout/fragment_main.xml b/simplecropview-sample/src/main/res/layout/fragment_main.xml index 9b06019..5754504 100644 --- a/simplecropview-sample/src/main/res/layout/fragment_main.xml +++ b/simplecropview-sample/src/main/res/layout/fragment_main.xml @@ -48,6 +48,35 @@ custom:scv_guide_stroke_weight="1dp" /> + + + + + + + + - \ No newline at end of file + diff --git a/simplecropview-sample/src/main/res/values/colors.xml b/simplecropview-sample/src/main/res/values/colors.xml index 9dc18a7..c68c2cc 100644 --- a/simplecropview-sample/src/main/res/values/colors.xml +++ b/simplecropview-sample/src/main/res/values/colors.xml @@ -9,4 +9,7 @@ #1C1C1C #AA1C1C1C #333333 - \ No newline at end of file + + #000000 + #FFFFFF +